From a600bd1bd7a15059374e6d527b23403a8133b410 Mon Sep 17 00:00:00 2001 From: "raveit65 (via Travis CI)" Date: Wed, 10 Jul 2024 10:11:07 +0000 Subject: Deploy mate-desktop/mate-calc to github.com/mate-desktop/mate-calc.git:gh-pages --- .../index.html | 124 + .../report-0e4c8f.html | 1651 ++++++++++++ .../report-1d4839.html | 1270 ++++++++++ .../report-397825.html | 1733 +++++++++++++ .../report-458ccc.html | 2072 +++++++++++++++ .../report-720c65.html | 1270 ++++++++++ .../report-90c61f.html | 2630 ++++++++++++++++++++ .../report-b1189a.html | 1270 ++++++++++ .../report-c223fe.html | 1651 ++++++++++++ .../report-c8cbaf.html | 1062 ++++++++ .../scanview.css | 62 + .../sorttable.js | 492 ++++ 12 files changed, 15287 insertions(+) create mode 100644 2024-07-10-100902-3667-1@fe495df3ec39_master/index.html create mode 100644 2024-07-10-100902-3667-1@fe495df3ec39_master/report-0e4c8f.html create mode 100644 2024-07-10-100902-3667-1@fe495df3ec39_master/report-1d4839.html create mode 100644 2024-07-10-100902-3667-1@fe495df3ec39_master/report-397825.html create mode 100644 2024-07-10-100902-3667-1@fe495df3ec39_master/report-458ccc.html create mode 100644 2024-07-10-100902-3667-1@fe495df3ec39_master/report-720c65.html create mode 100644 2024-07-10-100902-3667-1@fe495df3ec39_master/report-90c61f.html create mode 100644 2024-07-10-100902-3667-1@fe495df3ec39_master/report-b1189a.html create mode 100644 2024-07-10-100902-3667-1@fe495df3ec39_master/report-c223fe.html create mode 100644 2024-07-10-100902-3667-1@fe495df3ec39_master/report-c8cbaf.html create mode 100644 2024-07-10-100902-3667-1@fe495df3ec39_master/scanview.css create mode 100644 2024-07-10-100902-3667-1@fe495df3ec39_master/sorttable.js (limited to '2024-07-10-100902-3667-1@fe495df3ec39_master') diff --git a/2024-07-10-100902-3667-1@fe495df3ec39_master/index.html b/2024-07-10-100902-3667-1@fe495df3ec39_master/index.html new file mode 100644 index 0000000..fc851d8 --- /dev/null +++ b/2024-07-10-100902-3667-1@fe495df3ec39_master/index.html @@ -0,0 +1,124 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@456fa4479045
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 18.1.6 (Fedora 18.1.6-3.fc40) +
Date:Wed Jul 10 10:09:02 2024
+

Bug Summary

+ + + + + + + + + + +
Bug TypeQuantityDisplay?
All Bugs9
Logic error
Dereference of null pointer1
Security
Potential insecure memory buffer bounds restriction in call 'strcat'1
Potential insecure memory buffer bounds restriction in call 'strcpy'1
Unused code
Dead assignment3
Dead nested assignment3
+

Reports

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Unused codeDead assignmentmath-buttons.cbase_changed_cb4721View Report
Unused codeDead assignmentmath-equation.cmath_equation_get_equation8021View Report
Unused codeDead assignmentmath-preferences.cset_combo_box_from_int1501View Report
Unused codeDead nested assignmentlexer.cl_insert_next_token2041View Report
Unused codeDead nested assignmentlexer.cl_insert_next_token2411View Report
Unused codeDead nested assignmentlexer.cl_insert_next_token1251View Report
Logic errorDereference of null pointermp.cmp_factorize95612View Report
SecurityPotential insecure memory buffer bounds restriction in call 'strcat'parserfunc.cpf_apply_func_with_npower3661View Report
SecurityPotential insecure memory buffer bounds restriction in call 'strcpy'parserfunc.cpf_apply_func_with_npower3651View Report
+ + diff --git a/2024-07-10-100902-3667-1@fe495df3ec39_master/report-0e4c8f.html b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-0e4c8f.html new file mode 100644 index 0000000..361f554 --- /dev/null +++ b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-0e4c8f.html @@ -0,0 +1,1651 @@ + + + +parserfunc.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:parserfunc.c
Warning:line 365, column 5
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name parserfunc.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D LOCALE_DIR="/usr/local/share/locale" -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/atk-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/gio-unix-2.0 -D WITH_GZFILEOP -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-07-10-100902-3667-1 -x c parserfunc.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1#include <glib.h>
2#include <string.h>
3#include <stdlib.h>
4#include <stdio.h>
5
6#include "parser.h"
7#include "parserfunc.h"
8
9/* Register error variables in ParserState structure. */
10void
11set_error(ParserState* state, gint errorno, const gchar *token)
12{
13 state->error = errorno;
14 if(token)
15 state->error_token = strdup(token);
16}
17
18/* Unused function pointer. This won't be called anytime. */
19void*
20pf_none(ParseNode* self)
21{
22 return NULL((void*)0);
23}
24
25/* Set variable. */
26void*
27pf_set_var(ParseNode* self)
28{
29 MPNumber* val;
30 val = (MPNumber *) (*(self->right->evaluate))(self->right);
31 if(!val || !(self->state->set_variable))
32 {
33 if(val)
34 mp_free(val);
35 return NULL((void*)0);
36 }
37 (*(self->state->set_variable))(self->state, self->left->token->string, val);
38 return val;
39}
40
41/* Converts Number from one unit to other. */
42void*
43pf_convert_number(ParseNode* self)
44{
45 gchar* from;
46 gchar* to;
47 gint free_from = 0;
48 gint free_to = 0;
49 MPNumber tmp = mp_new();
50 MPNumber* ans = mp_new_ptr();
51 if(self->left->value)
52 {
53 from = (gchar*) self->left->value;
54 free_from = 1;
55 }
56 else
57 from = self->left->token->string;
58 if(self->right->value)
59 {
60 to = (gchar*) self->right->value;
61 free_to = 1;
62 }
63 else
64 to = self->right->token->string;
65
66 if(mp_set_from_string(self->left->left->token->string, self->state->options->base, &tmp) != 0)
67 {
68 mp_free(ans);
69 ans = NULL((void*)0);
70 goto END_PF_CONVERT_NUMBER;
71 }
72 if(!(self->state->convert))
73 {
74 mp_free(ans);
75 ans = NULL((void*)0);
76 goto END_PF_CONVERT_NUMBER;
77 }
78 if(!(*(self->state->convert))(self->state, &tmp, from, to, ans))
79 {
80 set_error(self->state, PARSER_ERR_UNKNOWN_CONVERSION, NULL((void*)0));
81 mp_free(ans);
82 ans = NULL((void*)0);
83 }
84END_PF_CONVERT_NUMBER:
85 if(free_from)
86 {
87 g_free(self->left->value);
88 self->left->value = NULL((void*)0);
89 }
90 if(free_to)
91 {
92 g_free(self->right->value);
93 self->right->value = NULL((void*)0);
94 }
95 mp_clear(&tmp);
96 return ans;
97}
98
99/* Conversion rate. */
100void*
101pf_convert_1(ParseNode* self )
102{
103 gchar* from;
104 gchar* to;
105 gint free_from = 0;
106 gint free_to = 0;
107 MPNumber tmp = mp_new();
108 MPNumber* ans = mp_new_ptr();
109 if(self->left->value)
110 {
111 from = (gchar*) self->left->value;
112 free_from = 1;
113 }
114 else
115 from = self->left->token->string;
116 if(self->right->value)
117 {
118 to = (gchar*) self->right->value;
119 free_to = 1;
120 }
121 else
122 to = self->right->token->string;
123 mp_set_from_integer(1, &tmp);
124 if(!(self->state->convert))
125 {
126 mp_free(ans);
127 return NULL((void*)0);
128 }
129 if(!(*(self->state->convert))(self->state, &tmp, from, to, ans))
130 {
131 set_error(self->state, PARSER_ERR_UNKNOWN_CONVERSION, NULL((void*)0));
132 mp_free(ans);
133 ans = NULL((void*)0);
134 }
135 if(free_from)
136 {
137 g_free(self->left->value);
138 self->left->value = NULL((void*)0);
139 }
140 if(free_to)
141 {
142 g_free(self->right->value);
143 self->right->value = NULL((void*)0);
144 }
145 mp_clear(&tmp);
146 return ans;
147}
148
149/* Join source unit and power. */
150gchar*
151pf_make_unit(gchar* source, gchar* power)
152{
153 return g_strjoin(NULL((void*)0), source, power, NULL((void*)0));
154}
155
156static gchar *
157utf8_next_char(const gchar *c)
158{
159 c++;
160 while((*c & 0xC0) == 0x80)
161 c++;
162 return(gchar *) c;
163}
164
165/* Get value of variable. */
166void*
167pf_get_variable(ParseNode* self)
168{
169 gint result = 0;
170
171 const gchar *c, *next;
172 gchar *buffer;
173 MPNumber value = mp_new();
174
175 MPNumber t = mp_new();
176 MPNumber* ans = mp_new_ptr();
177
178 if(!(self->state->get_variable))
179 {
180 free(ans);
181 return NULL((void*)0);
182 }
183
184 /* If defined, then get the variable */
185 if((*(self->state->get_variable))(self->state, self->token->string, ans))
186 {
187 return ans;
188 }
189
190 /* If has more than one character then assume a multiplication of variables */
191 if(utf8_next_char(self->token->string)[0] != '\0')
192 {
193 result = 1;
194 buffer = (gchar*) malloc(sizeof(gchar) * strlen(self->token->string));
195 mp_set_from_integer(1, &value);
196 for(c = self->token->string; *c != '\0'; c = next)
197 {
198 next = utf8_next_char(c);
199 snprintf(buffer, next - c + 1, "%s", c);
200 if(!(*(self->state->get_variable))(self->state, buffer, &t))
201 {
202 result = 0;
203 break;
204 }
205 mp_multiply(&value, &t, &value);
206 }
207 free(buffer);
208 if(result)
209 mp_set_from_mp(&value, ans);
210 }
211 if(!result)
212 {
213 free (ans);
214 ans = NULL((void*)0);
215 set_error(self->state, PARSER_ERR_UNKNOWN_VARIABLE, self->token->string);
216 }
217 return ans;
218}
219
220/* Get value of variable with power. */
221void*
222pf_get_variable_with_power(ParseNode* self)
223{
224 gint result = 0;
225 gint pow;
226
227 const gchar *c, *next;
228 gchar *buffer;
229 MPNumber value = mp_new();
230
231 MPNumber t = mp_new();
232 MPNumber* ans = mp_new_ptr();
233 pow = super_atoi(((LexerToken*) self->value)->string);
234
235 /* No need to free the memory. It is allocated and freed somewhere else. */
236 self->value = NULL((void*)0);
237
238 if(!(self->state->get_variable))
239 {
240 free(ans);
241 return NULL((void*)0);
242 }
243
244 /* If defined, then get the variable */
245 if((*(self->state->get_variable))(self->state, self->token->string, ans))
246 {
247 mp_xpowy_integer(ans, pow, ans);
248 return ans;
249 }
250
251 /* If has more than one character then assume a multiplication of variables */
252 if(utf8_next_char(self->token->string)[0] != '\0')
253 {
254 result = 1;
255 buffer = (gchar*) malloc(sizeof(gchar) * strlen(self->token->string));
256 mp_set_from_integer(1, &value);
257 for(c = self->token->string; *c != '\0'; c = next)
258 {
259 next = utf8_next_char(c);
260 snprintf(buffer, next - c + 1, "%s", c);
261 if(!(*(self->state->get_variable))(self->state, buffer, &t))
262 {
263 result = 0;
264 break;
265 }
266
267 /* If last term do power */
268 if(*next == '\0')
269 mp_xpowy_integer(&t, pow, &t);
270 mp_multiply(&value, &t, &value);
271 }
272 free(buffer);
273 if(result)
274 mp_set_from_mp(&value, ans);
275 }
276 if(!result)
277 {
278 free(ans);
279 ans = NULL((void*)0);
280 set_error(self->state, PARSER_ERR_UNKNOWN_VARIABLE, self->token->string);
281 }
282 return ans;
283}
284
285/* Apply function on child. */
286void*
287pf_apply_func(ParseNode* self)
288{
289 MPNumber* val;
290 MPNumber* ans = mp_new_ptr();
291 val = (MPNumber*) (*(self->right->evaluate))(self->right);
292 if(!(self->state->get_function))
293 {
294 free(val);
295 free(ans);
296 return NULL((void*)0);
297 }
298 if(!val)
299 {
300 free(ans);
301 return NULL((void*)0);
302 }
303 if(!(*(self->state->get_function))(self->state, self->token->string, val, ans))
304 {
305 free(val);
306 free(ans);
307 set_error(self->state, PARSER_ERR_UNKNOWN_FUNCTION, self->token->string);
308 return NULL((void*)0);
309 }
310 free(val);
311 return ans;
312}
313
314/* Apply function with +ve power. */
315void*
316pf_apply_func_with_power(ParseNode* self)
317{
318 MPNumber* val;
319 MPNumber* tmp = mp_new_ptr();
320 MPNumber* ans = mp_new_ptr();
321 gint pow;
322 val = (MPNumber*) (*(self->right->evaluate))(self->right);
323 if(!(self->state->get_function))
324 {
325 mp_free(tmp);
326 mp_free(ans);
327 mp_free(val);
328 self->value = NULL((void*)0);
329 return NULL((void*)0);
330 }
331 if(!val)
332 {
333 mp_free(tmp);
334 mp_free(ans);
335 self->value = NULL((void*)0);
336 return NULL((void*)0);
337 }
338 if(!(*(self->state->get_function))(self->state, self->token->string, val, tmp))
339 {
340 mp_free(tmp);
341 mp_free(ans);
342 mp_free(val);
343 self->value = NULL((void*)0);
344 set_error(self->state, PARSER_ERR_UNKNOWN_FUNCTION, self->token->string);
345 return NULL((void*)0);
346 }
347 pow = super_atoi(((LexerToken*) self->value)->string);
348 mp_xpowy_integer(tmp, pow, ans);
349 mp_free(val);
350 mp_free(tmp);
351 self->value = NULL((void*)0);
352 return ans;
353}
354
355/* Apply function with -ve power. */
356void*
357pf_apply_func_with_npower(ParseNode* self)
358{
359 MPNumber* val;
360 MPNumber* tmp = mp_new_ptr();
361 MPNumber* ans = mp_new_ptr();
362 gint pow;
363 gchar* inv_name;
364 inv_name = (gchar*) malloc(sizeof(gchar) * strlen(self->token->string) + strlen("⁻¹") + 1);
365 strcpy(inv_name, self->token->string);
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
366 strcat(inv_name, "⁻¹");
367 val = (MPNumber*) (*(self->right->evaluate))(self->right);
368 if(!val)
369 {
370 mp_free(tmp);
371 free(inv_name);
372 mp_free(ans);
373 self->value = NULL((void*)0);
374 return NULL((void*)0);
375 }
376 if(!(self->state->get_function))
377 {
378 mp_free(tmp);
379 mp_free(ans);
380 free(inv_name);
381 self->value = NULL((void*)0);
382 return NULL((void*)0);
383 }
384 if(!(*(self->state->get_function))(self->state, inv_name, val, tmp))
385 {
386 mp_free(tmp);
387 mp_free(ans);
388 mp_free(val);
389 free(inv_name);
390 self->value = NULL((void*)0);
391 set_error(self->state, PARSER_ERR_UNKNOWN_FUNCTION, self->token->string);
392 return NULL((void*)0);
393 }
394 pow = super_atoi(((LexerToken*) self->value)->string);
395 mp_xpowy_integer(tmp, -pow, ans);
396 mp_free(val);
397 mp_free(tmp);
398 free(inv_name);
399 self->value = NULL((void*)0);
400 return ans;
401}
402
403/* Find nth root of child. */
404void*
405pf_do_nth_root(ParseNode* self)
406{
407 MPNumber* val;
408 gint pow;
409 MPNumber* ans = mp_new_ptr();
410 pow = sub_atoi(((LexerToken*) self->value)->string);
411 self->value = NULL((void*)0);
412 val = (MPNumber*) (*(self->right->evaluate))(self->right);
413 if(!val)
414 {
415 mp_free(ans);
416 return NULL((void*)0);
417 }
418 mp_root(val, pow, ans);
419 mp_free(val);
420 return ans;
421}
422
423/* Find sqrt of child. */
424void*
425pf_do_sqrt(ParseNode* self)
426{
427 MPNumber* val;
428 MPNumber* ans = mp_new_ptr();
429 val = (MPNumber*) (*(self->right->evaluate))(self->right);
430 if(!val)
431 {
432 free(ans);
433 return NULL((void*)0);
434 }
435 mp_sqrt(val, ans);
436 free(val);
437 return ans;
438}
439
440/* Find 3rd root of child. */
441void*
442pf_do_root_3(ParseNode* self)
443{
444 MPNumber* val;
445 MPNumber* ans = mp_new_ptr();
446 val = (MPNumber*) (*(self->right->evaluate))(self->right);
447 if(!val)
448 {
449 mp_free(ans);
450 return NULL((void*)0);
451 }
452 mp_root(val, 3, ans);
453 mp_free(val);
454 return ans;
455}
456
457/* Find 4th root of child. */
458void*
459pf_do_root_4(ParseNode* self)
460{
461 MPNumber* val;
462 MPNumber* ans = mp_new_ptr();
463 val = (MPNumber*) (*(self->right->evaluate))(self->right);
464 if(!val)
465 {
466 mp_free(ans);
467 return NULL((void*)0);
468 }
469 mp_root(val, 4, ans);
470 mp_free(val);
471 return ans;
472}
473
474/* Apply floor function. */
475void*
476pf_do_floor(ParseNode* self)
477{
478 MPNumber* val;
479 MPNumber* ans = mp_new_ptr();
480 val = (MPNumber*) (*(self->right->evaluate))(self->right);
481 if(!val)
482 {
483 mp_free(ans);
484 return NULL((void*)0);
485 }
486 mp_floor(val, ans);
487 mp_free(val);
488 return ans;
489}
490
491/* Apply ceiling function. */
492void* pf_do_ceiling (ParseNode* self)
493{
494 MPNumber* val;
495 MPNumber* ans = mp_new_ptr();
496 val = (MPNumber*) (*(self->right->evaluate))(self->right);
497 if(!val)
498 {
499 mp_free(ans);
500 return NULL((void*)0);
501 }
502 mp_ceiling(val, ans);
503 mp_free(val);
504 return ans;
505}
506
507/* Round off. */
508void*
509pf_do_round(ParseNode* self)
510{
511 MPNumber* val;
512 MPNumber* ans = mp_new_ptr();
513 val = (MPNumber*) (*(self->right->evaluate))(self->right);
514 if(!val)
515 {
516 mp_free(ans);
517 return NULL((void*)0);
518 }
519 mp_round(val, ans);
520 mp_free(val);
521 return ans;
522}
523
524/* Fraction. */
525void*
526pf_do_fraction(ParseNode* self)
527{
528 MPNumber* val;
529 MPNumber* ans = mp_new_ptr();
530 val = (MPNumber*) (*(self->right->evaluate))(self->right);
531 if(!val)
532 {
533 mp_free(ans);
534 return NULL((void*)0);
535 }
536 mp_fractional_part(val, ans);
537 mp_free(val);
538 return ans;
539}
540
541/* Absolute value. */
542void*
543pf_do_abs(ParseNode* self)
544{
545 MPNumber* val;
546 MPNumber* ans = mp_new_ptr();
547 val = (MPNumber*) (*(self->right->evaluate))(self->right);
548 if(!val)
549 {
550 mp_free(ans);
551 return NULL((void*)0);
552 }
553 mp_abs(val, ans);
554 mp_free(val);
555 return ans;
556}
557
558/* Find x^y for x and y being MPNumber. */
559void*
560pf_do_x_pow_y(ParseNode* self)
561{
562 MPNumber* val;
563 MPNumber* pow;
564 MPNumber* ans = mp_new_ptr();
565 val = (MPNumber*) (*(self->left->evaluate))(self->left);
566 pow = (MPNumber*) (*(self->right->evaluate))(self->right);
567 if(!val || !pow)
568 {
569 if(val)
570 mp_free(val);
571 if(pow)
572 mp_free(pow);
573 mp_free(ans);
574 return NULL((void*)0);
575 }
576 mp_xpowy(val, pow, ans);
577 mp_free(val);
578 mp_free(pow);
579 return ans;
580}
581
582/* Find x^y for MPNumber x and integer y. */
583void*
584pf_do_x_pow_y_int(ParseNode* self)
585{
586 MPNumber* val;
587 long pow;
588 MPNumber* ans = mp_new_ptr();
589 val = (MPNumber*) (*(self->left->evaluate))(self->left);
590
591 if(!val)
592 {
593 val = mp_new_ptr();
594 mp_set_from_integer(super_atoi(self->left->token->string), val);
595 }
596
597 if (self->right->token != NULL((void*)0))
598 {
599 pow = super_atoi(self->right->token->string);
600 }
601 else
602 {
603 MPNumber* aux = (MPNumber*) (*(self->right->evaluate))(self->right);
604 pow = mp_to_integer(aux);
605 mp_free(aux);
606 }
607
608 if(!val)
609 {
610 mp_free(ans);
611 return NULL((void*)0);
612 }
613 mp_xpowy_integer(val, pow, ans);
614 mp_free(val);
615 return ans;
616}
617
618/* Find factorial. */
619void*
620pf_do_factorial(ParseNode* self)
621{
622 MPNumber* val;
623 MPNumber* ans = mp_new_ptr();
624 val = (MPNumber*) (*(self->right->evaluate))(self->right);
625 if(!val)
626 {
627 mp_free(ans);
628 return NULL((void*)0);
629 }
630 mp_factorial(val, ans);
631 mp_free(val);
632 return ans;
633}
634
635/* Apply unary minus. */
636void*
637pf_unary_minus(ParseNode* self)
638{
639 MPNumber* val;
640 MPNumber* ans = mp_new_ptr();
641 val = (MPNumber*) (*(self->right->evaluate))(self->right);
642 if(!val)
643 {
644 mp_free(ans);
645 return NULL((void*)0);
646 }
647 mp_invert_sign(val, ans);
648 mp_free(val);
649 return ans;
650}
651
652/* Divide. */
653void*
654pf_do_divide(ParseNode* self)
655{
656 MPNumber* left;
657 MPNumber* right;
658 MPNumber* ans = mp_new_ptr();
659 left = (MPNumber*) (*(self->left->evaluate))(self->left);
660 right = (MPNumber*) (*(self->right->evaluate))(self->right);
661 if(!left || !right)
662 {
663 if(left)
664 mp_free(left);
665 if(right)
666 mp_free(right);
667 mp_free(ans);
668 return NULL((void*)0);
669 }
670 mp_divide(left, right, ans);
671 mp_free(left);
672 mp_free(right);
673 return ans;
674}
675
676/* Modulus. */
677void*
678pf_do_mod(ParseNode* self)
679{
680 MPNumber* left;
681 MPNumber* right;
682 MPNumber* ans = mp_new_ptr();
683 left = (MPNumber*) (*(self->left->evaluate))(self->left);
684 right = (MPNumber*) (*(self->right->evaluate))(self->right);
685 if(!left || !right)
686 {
687 if(left)
688 mp_free(left);
689 if(right)
690 mp_free(right);
691 mp_free(ans);
692 return NULL((void*)0);
693 }
694 if (self->left->evaluate == pf_do_x_pow_y)
695 {
696 MPNumber* base_value = (MPNumber*) (*(self->left->left->evaluate))(self->left->left);
697 MPNumber* exponent = (MPNumber*) (*(self->left->right->evaluate))(self->left->right);
698 if(!base_value || !exponent)
699 {
700 if(base_value)
701 mp_free(base_value);
702 if(exponent)
703 mp_free(exponent);
704 mp_free(ans);
705 return NULL((void*)0);
706 }
707 mp_modular_exponentiation(base_value, exponent, right, ans);
708 mp_free(base_value);
709 mp_free(exponent);
710 }
711 else
712 mp_modulus_divide(left, right, ans);
713
714 mp_free(left);
715 mp_free(right);
716 return ans;
717}
718
719/* Multiply two numbers. */
720void*
721pf_do_multiply(ParseNode* self)
722{
723 MPNumber* left;
724 MPNumber* right;
725 MPNumber* ans = mp_new_ptr();
726 left = (MPNumber*) (*(self->left->evaluate))(self->left);
727 right = (MPNumber*) (*(self->right->evaluate))(self->right);
728 if(!left || !right)
729 {
730 if(left)
731 mp_free(left);
732 if(right)
733 mp_free(right);
734 mp_free(ans);
735 return NULL((void*)0);
736 }
737 mp_multiply(left, right, ans);
738 mp_free(left);
739 mp_free(right);
740 return ans;
741}
742
743/* Subtract two numbers. */
744void*
745pf_do_subtract(ParseNode* self)
746{
747 MPNumber* left;
748 MPNumber* right;
749 MPNumber* ans = mp_new_ptr();
750 left = (MPNumber*) (*(self->left->evaluate))(self->left);
751 right = (MPNumber*) (*(self->right->evaluate))(self->right);
752 if(!left || !right)
753 {
754 if(left)
755 mp_free(left);
756 if(right)
757 mp_free(right);
758 free(ans);
759 return NULL((void*)0);
760 }
761 mp_subtract(left, right, ans);
762 mp_free(left);
763 mp_free(right);
764 return ans;
765}
766
767/* Add two numbers. */
768void*
769pf_do_add(ParseNode* self)
770{
771 MPNumber* left;
772 MPNumber* right;
773 MPNumber* ans = mp_new_ptr();
774 left = (MPNumber*) (*(self->left->evaluate))(self->left);
775 right = (MPNumber*) (*(self->right->evaluate))(self->right);
776 if(!left || !right)
777 {
778 if(left)
779 mp_free(left);
780 if(right)
781 mp_free(right);
782 free(ans);
783 return NULL((void*)0);
784 }
785 mp_add(left, right, ans);
786 mp_free(left);
787 mp_free(right);
788 return ans;
789}
790
791/* Add (x) Percentage to value. */
792void*
793pf_do_add_percent(ParseNode* self)
794{
795 MPNumber* ans = mp_new_ptr();
796 MPNumber* val;
797 MPNumber* per;
798 val = (MPNumber*) (*(self->left->evaluate))(self->left);
799 per = (MPNumber*) (*(self->right->evaluate))(self->right);
800 if(!val || !per)
801 {
802 if(val)
803 mp_free(val);
804 if(per)
805 mp_free(per);
806 mp_free(ans);
807 return NULL((void*)0);
808 }
809 mp_add_integer(per, 100, per);
810 mp_divide_integer(per, 100, per);
811 mp_multiply(val, per, ans);
812 mp_free(val);
813 mp_free(per);
814 return ans;
815}
816
817/* Subtract (x) Percentage to value. */
818void*
819pf_do_subtract_percent(ParseNode* self)
820{
821 MPNumber* ans = mp_new_ptr();
822 MPNumber* val;
823 MPNumber* per;
824 val = (MPNumber*) (*(self->left->evaluate))(self->left);
825 per = (MPNumber*) (*(self->right->evaluate))(self->right);
826 if(!val || !per)
827 {
828 if(val)
829 mp_free(val);
830 if(per)
831 mp_free(per);
832 free(ans);
833 return NULL((void*)0);
834 }
835 mp_add_integer(per, -100, per);
836 mp_divide_integer(per, -100, per);
837 mp_multiply(val, per, ans);
838 mp_free(val);
839 mp_free(per);
840 return ans;
841}
842
843/* Converts a constant into percentage. */
844void*
845pf_do_percent(ParseNode* self)
846{
847 MPNumber* val;
848 MPNumber* ans = mp_new_ptr();
849 val = (MPNumber*) (*(self->right->evaluate))(self->right);
850 if(!val)
851 {
852 mp_free(ans);
853 return NULL((void*)0);
854 }
855 mp_divide_integer(val, 100, ans);
856 mp_free(val);
857 return ans;
858}
859
860/* NOT. */
861void*
862pf_do_not(ParseNode* self)
863{
864 MPNumber* val;
865 MPNumber* ans = mp_new_ptr();
866 val = (MPNumber*) (*(self->right->evaluate))(self->right);
867 if(!val)
868 {
869 mp_free(ans);
870 return NULL((void*)0);
871 }
872 if(!mp_is_overflow(val, self->state->options->wordlen))
873 {
874 set_error(self->state, PARSER_ERR_OVERFLOW, NULL((void*)0));
875 mp_free(ans);
876 mp_free(val);
877 return NULL((void*)0);
878 }
879 mp_not(val, self->state->options->wordlen, ans);
880 mp_free(val);
881 return ans;
882}
883
884/* AND. */
885void*
886pf_do_and(ParseNode* self)
887{
888 MPNumber* left;
889 MPNumber* right;
890 MPNumber* ans = mp_new_ptr();
891 left = (MPNumber*) (*(self->left->evaluate))(self->left);
892 right = (MPNumber*) (*(self->right->evaluate))(self->right);
893 if(!left || !right)
894 {
895 if(left)
896 mp_free(left);
897 if(right)
898 mp_free(right);
899 mp_free(ans);
900 return NULL((void*)0);
901 }
902 mp_and(left, right, ans);
903 mp_free(left);
904 mp_free(right);
905 return ans;
906}
907
908/* OR. */
909void*
910pf_do_or(ParseNode* self)
911{
912 MPNumber* left;
913 MPNumber* right;
914 MPNumber* ans = mp_new_ptr();
915 left = (MPNumber*) (*(self->left->evaluate))(self->left);
916 right = (MPNumber*) (*(self->right->evaluate))(self->right);
917 if(!left || !right)
918 {
919 if(left)
920 mp_free(left);
921 if(right)
922 mp_free(right);
923 mp_free(ans);
924 return NULL((void*)0);
925 }
926 mp_or(left, right, ans);
927 mp_free(left);
928 mp_free(right);
929 return ans;
930}
931
932/* XOR. */
933void*
934pf_do_xor(ParseNode* self)
935{
936 MPNumber* left;
937 MPNumber* right;
938 MPNumber* ans = mp_new_ptr();
939 left = (MPNumber*) (*(self->left->evaluate))(self->left);
940 right = (MPNumber*) (*(self->right->evaluate))(self->right);
941 if(!left || !right)
942 {
943 if(left)
944 mp_free(left);
945 if(right)
946 mp_free(right);
947 free(ans);
948 return NULL((void*)0);
949 }
950 mp_xor(left, right, ans);
951 mp_free(left);
952 mp_free(right);
953 return ans;
954}
955
956/* Constant value. Convert into MPNumber and return. */
957void*
958pf_constant(ParseNode* self)
959{
960 MPNumber* ans = mp_new_ptr();
961 if(mp_set_from_string(self->token->string, self->state->options->base, ans) != 0)
962 {
963 /* This should never happen, as l_check_if_number() has already passed the string once. */
964 /* If the code reaches this point, something is really wrong. X( */
965 mp_free(ans);
966 set_error(self->state, PARSER_ERR_INVALID, self->token->string);
967 return NULL((void*)0);
968 }
969 return ans;
970}
971
diff --git a/2024-07-10-100902-3667-1@fe495df3ec39_master/report-1d4839.html b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-1d4839.html new file mode 100644 index 0000000..8b8d2d6 --- /dev/null +++ b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-1d4839.html @@ -0,0 +1,1270 @@ + + + +lexer.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:lexer.c
Warning:line 204, column 29
Although the value stored to 'type' is used in the enclosing expression, the value is never actually read from 'type'
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name lexer.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D LOCALE_DIR="/usr/local/share/locale" -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/atk-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/gio-unix-2.0 -D WITH_GZFILEOP -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-07-10-100902-3667-1 -x c lexer.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1#include <stdlib.h>
2#include <assert.h>
3#include <string.h>
4
5#include "lexer.h"
6#include "parserfunc.h"
7#include "mp-equation.h"
8
9static gboolean
10l_check_if_function(LexerState* state)
11{
12 gchar* name = pl_get_marked_substring(state->prelexer);
13 if(!state->parent->function_is_defined)
14 {
15 free(name);
16 return FALSE(0);
17 }
18 if ((*(state->parent->function_is_defined))(state->parent, name))
19 {
20 free(name);
21 return TRUE(!(0));
22 }
23 else
24 {
25 free(name);
26 return FALSE(0);
27 }
28}
29
30static gboolean
31l_check_if_number(LexerState* state)
32{
33 MPNumber tmp = mp_new();
34 int count = 0;
35 gchar* text = pl_get_marked_substring(state->prelexer);
36 if(mp_set_from_string(text, state->parent->options->base, &tmp) == 0)
37 {
38 free(text);
39 mp_clear(&tmp);
40 return TRUE(!(0));
41 }
42 else
43 {
44 /* Try to rollback several characters to see, if that yeilds any number. */
45 while(strlen (text) > 0)
46 {
47 if(mp_set_from_string(text, state->parent->options->base, &tmp) == 0)
48 {
49 free(text);
50 mp_clear(&tmp);
51 return TRUE(!(0));
52 }
53 free(text);
54 count++;
55 pl_roll_back(state->prelexer);
56 text = pl_get_marked_substring(state->prelexer);
57 }
58 /* Undo all rollbacks. */
59 while(count--)
60 pl_get_next_token (state->prelexer);
61 free(text);
62 mp_clear(&tmp);
63 return FALSE(0);
64 }
65}
66
67/* Insert generated token to the LexerState structure. */
68static LexerToken*
69l_insert_token(LexerState* state, const LexerTokenType type)
70{
71 state->tokens = (LexerToken *) realloc(state->tokens, (state->token_count + 1) * sizeof(LexerToken));
72 assert(state->tokens != NULL)((void) sizeof ((state->tokens != ((void*)0)) ? 1 : 0), __extension__
({ if (state->tokens != ((void*)0)) ; else __assert_fail (
"state->tokens != NULL", "lexer.c", 72, __extension__ __PRETTY_FUNCTION__
); }))
;
73 state->tokens[state->token_count].string = pl_get_marked_substring(state->prelexer);
74 state->tokens[state->token_count].start_index = state->prelexer->mark_index;
75 state->tokens[state->token_count].end_index = state->prelexer->next_index;
76 state->tokens[state->token_count].token_type = type;
77 state->token_count++;
78 return &state->tokens[state->token_count - 1];
79}
80
81/* Generates next token from pre-lexer stream and call l_insert_token() to insert it at the end. */
82static LexerToken*
83l_insert_next_token(LexerState* lstate)
84{
85 PreLexerState* state = lstate->prelexer;
86 LexerTokenType type;
87 gchar* tmp;
88 pl_set_marker(state);
89 /* Ignore all blank spaces. :) */
90 while((type = pl_get_next_token(state)) == PL_SKIP)
91 /* Set marker. Beginning of new token. */
92 pl_set_marker(state);
93 if(type == T_AND
94 ||type == T_OR
95 ||type == T_XOR
96 ||type == T_NOT
97 ||type == T_ADD
98 ||type == T_SUBTRACT
99 ||type == T_MULTIPLY
100 ||type == T_DIV
101 ||type == T_L_FLOOR
102 ||type == T_R_FLOOR
103 ||type == T_L_CEILING
104 ||type == T_R_CEILING
105 ||type == T_ROOT
106 ||type == T_ROOT_3
107 ||type == T_ROOT_4
108 ||type == T_ASSIGN
109 ||type == T_L_R_BRACKET
110 ||type == T_R_R_BRACKET
111 ||type == T_L_S_BRACKET
112 ||type == T_R_S_BRACKET
113 ||type == T_L_C_BRACKET
114 ||type == T_R_C_BRACKET
115 ||type == T_ABS
116 ||type == T_POWER
117 ||type == T_FACTORIAL
118 ||type == T_PERCENTAGE)
119 {
120 return l_insert_token(lstate, type);
121 }
122 /* [PL_SUPER_MINUS][PL_SUPER_DIGIT]+ */
123 if(type == PL_SUPER_MINUS)
124 {
125 if((type = pl_get_next_token(state)) != PL_SUPER_DIGIT)
126 {
127 /* ERROR: expected PL_SUP_DIGIT */
128 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring (state));
129 free(tmp);
130 return l_insert_token(lstate, T_UNKNOWN);
131 }
132 /* Get all PL_SUPER_DIGITs. */
133 while (pl_get_next_token(state) == PL_SUPER_DIGIT);
134 pl_roll_back(state);
135 return l_insert_token(lstate, T_NSUP_NUMBER);
136 }
137 /* [PL_SUPER_DIGIT]+ */
138 if(type == PL_SUPER_DIGIT)
139 {
140 while(pl_get_next_token(state) == PL_SUPER_DIGIT);
141 pl_roll_back(state);
142 return l_insert_token(lstate, T_SUP_NUMBER);
143 }
144 /* [PL_SUB_DIGIT]+ */
145 if(type == PL_SUB_DIGIT)
146 {
147 while(pl_get_next_token(state) == PL_SUB_DIGIT);
148 pl_roll_back(state);
149 return l_insert_token(lstate, T_SUB_NUMBER);
150 }
151 /* [PL_FRACTION] */
152 if(type == PL_FRACTION)
153 {
154 return l_insert_token(lstate, T_NUMBER);
155 }
156 if(type == PL_DIGIT)
157 {
158 while((type = pl_get_next_token(state)) == PL_DIGIT);
159 if(type == PL_FRACTION)
160 {
161 return l_insert_token(lstate, T_NUMBER);
162 }
163 else if(type == PL_SUB_DIGIT)
164 {
165 while(pl_get_next_token(state) == PL_SUB_DIGIT);
166 pl_roll_back(state);
167 return l_insert_token(lstate, T_NUMBER);
168 }
169 else if(type == PL_DEGREE)
170 {
171 type = pl_get_next_token(state);
172 if(type == PL_DIGIT)
173 {
174 while((type = pl_get_next_token(state)) == PL_DIGIT);
175 if(type == PL_DECIMAL)
176 {
177 goto ANGLE_NUM_DM_STATE;
178 }
179 else if(type == PL_MINUTE)
180 {
181 type = pl_get_next_token(state);
182 if(type == PL_DIGIT)
183 {
184 while((type = pl_get_next_token(state)) == PL_DIGIT);
185 if(type == PL_DECIMAL)
186 {
187 goto ANGLE_NUM_DMS_STATE;
188 }
189 else if(type == PL_SECOND)
190 {
191 return l_insert_token(lstate, T_NUMBER);
192 }
193 else
194 {
195 /* ERROR: expected PL_SECOND */
196 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring (state));
197 free(tmp);
198 return l_insert_token(lstate, T_UNKNOWN);
199 }
200 }
201 else if(type == PL_DECIMAL)
202 {
203ANGLE_NUM_DMS_STATE:
204 if((type = pl_get_next_token (state)) != PL_DIGIT)
Although the value stored to 'type' is used in the enclosing expression, the value is never actually read from 'type'
205 {
206 /* ERROR: expected PL_DIGIT */
207 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
208 free(tmp);
209 return l_insert_token(lstate, T_UNKNOWN);
210 }
211 while((type = pl_get_next_token(state)) == PL_DIGIT);
212 if(type == PL_SECOND)
213 {
214 return l_insert_token(lstate, T_NUMBER);
215 }
216 else
217 {
218 /* ERROR: expected PL_SECOND */
219 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
220 free(tmp);
221 return l_insert_token(lstate, T_UNKNOWN);
222 }
223 }
224 else
225 {
226 pl_roll_back(state);
227 return l_insert_token(lstate, T_NUMBER);
228 }
229 }
230 else
231 {
232 /* ERROR: expected PL_MINUTE | PL_DIGIT */
233 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
234 free(tmp);
235 return l_insert_token(lstate, T_UNKNOWN);
236 }
237 }
238 else if(type == PL_DECIMAL)
239 {
240ANGLE_NUM_DM_STATE:
241 if((type = pl_get_next_token(state)) != PL_DIGIT)
242 {
243 /* ERROR: expected PL_DIGIT */
244 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
245 free(tmp);
246 return l_insert_token(lstate, T_UNKNOWN);
247 }
248 while((type = pl_get_next_token(state)) == PL_DIGIT);
249 if(type == PL_MINUTE)
250 {
251 return l_insert_token(lstate, T_NUMBER);
252 }
253 else
254 {
255 /* ERROR: expected PL_MINUTE */
256 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
257 free(tmp);
258 return l_insert_token(lstate, T_UNKNOWN);
259 }
260 }
261 else
262 {
263 return l_insert_token(lstate, T_NUMBER);
264 }
265 }
266 else if(type == PL_DECIMAL)
267 {
268 goto DECIMAL_STATE;
269 }
270 else if(type == PL_HEX)
271 {
272 goto HEX_DEC_STATE;
273 }
274 else
275 {
276 pl_roll_back(state);
277 return l_insert_token(lstate, T_NUMBER);
278 }
279 }
280 if(type == PL_DECIMAL)
281 {
282DECIMAL_STATE:
283 type = pl_get_next_token(state);
284 if(type == PL_DIGIT)
285 {
286 while((type = pl_get_next_token(state)) == PL_DIGIT);
287 if(type == PL_DEGREE)
288 {
289 return l_insert_token(lstate, T_NUMBER);
290 }
291 else if(type == PL_HEX)
292 {
293 goto DECIMAL_HEX_STATE;
294 }
295 else if(type == PL_SUB_DIGIT)
296 {
297 while(pl_get_next_token(state) == PL_SUB_DIGIT);
298 pl_roll_back(state);
299 return l_insert_token(lstate, T_NUMBER);
300 }
301 else
302 {
303 pl_roll_back(state);
304 return l_insert_token(lstate, T_NUMBER);
305 }
306 }
307 else if(type == PL_HEX)
308 {
309 goto DECIMAL_HEX_STATE;
310 }
311 else
312 {
313 /* ERROR: expected PL_DIGIT | PL_HEX */
314 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
315 free(tmp);
316 return l_insert_token(lstate, T_UNKNOWN);
317 }
318 }
319 if(type == PL_HEX)
320 {
321 while((type = pl_get_next_token(state)) == PL_HEX);
322 if(type == PL_DIGIT)
323 {
324HEX_DEC_STATE:
325 while(1)
326 {
327 type = pl_get_next_token(state);
328 if(type == PL_DIGIT || type == PL_HEX)
329 {
330 continue;
331 }
332 else if(type == PL_DECIMAL)
333 {
334 goto DECIMAL_HEX_STATE;
335 }
336 else if(type == PL_SUB_DIGIT)
337 {
338 while(pl_get_next_token(state) == PL_SUB_DIGIT);
339 pl_roll_back(state);
340 return l_insert_token(lstate, T_NUMBER);
341 }
342 else
343 {
344 if(l_check_if_number(lstate))
345 return l_insert_token(lstate, T_NUMBER);
346 /* ERROR: expected PL_DECIMAL | PL_DIGIT | PL_HEX */
347 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
348 free(tmp);
349 return l_insert_token(lstate, T_UNKNOWN);
350 }
351 }
352 }
353 else if(type == PL_DECIMAL)
354 {
355DECIMAL_HEX_STATE:
356 type = pl_get_next_token(state);
357 if(!(type == PL_DIGIT || type == PL_HEX))
358 {
359 /* ERROR: expected PL_DIGIT | PL_HEX */
360 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
361 free(tmp);
362 return l_insert_token(lstate, T_UNKNOWN);
363 }
364 while(1)
365 {
366 type = pl_get_next_token(state);
367 if(type == PL_DIGIT || type == PL_HEX)
368 {
369 continue;
370 }
371 else if(type == PL_SUB_DIGIT)
372 {
373 while(pl_get_next_token(state) == PL_SUB_DIGIT);
374 pl_roll_back(state);
375 return l_insert_token(lstate, T_NUMBER);
376 }
377 else
378 {
379 pl_roll_back(state);
380 return l_insert_token(lstate, T_NUMBER);
381 }
382 }
383 }
384 else if(type == PL_SUB_DIGIT)
385 {
386 while(pl_get_next_token(state) == PL_SUB_DIGIT);
387 pl_roll_back(state);
388 if(l_check_if_number(lstate))
389 {
390 /* NUMBER */
391 return l_insert_token(lstate, T_NUMBER);
392 }
393 else
394 {
395 /* VARIABLE */
396 if(l_check_if_function(lstate))
397 {
398 return l_insert_token(lstate, T_FUNCTION);
399 }
400 else
401 {
402 return l_insert_token(lstate, T_VARIABLE);
403 }
404 }
405 }
406 else if(type == PL_LETTER)
407 {
408 goto LETTER_STATE;
409 }
410 else
411 {
412 pl_roll_back(state);
413 if(l_check_if_number(lstate))
414 {
415 /* NUMBER */
416 return l_insert_token(lstate, T_NUMBER);
417 }
418 else
419 {
420 /* VARIABLE */
421 if(l_check_if_function(lstate))
422 {
423 return l_insert_token(lstate, T_FUNCTION);
424 }
425 else
426 {
427 return l_insert_token(lstate, T_VARIABLE);
428 }
429 }
430 }
431 }
432 if(type == PL_LETTER)
433 {
434LETTER_STATE:
435 while(1)
436 {
437 type = pl_get_next_token(state);
438 if(type == PL_LETTER || type == PL_HEX)
439 {
440 continue;
441 }
442 else if(type == PL_SUB_DIGIT)
443 {
444 while(pl_get_next_token(state) == PL_SUB_DIGIT);
445 pl_roll_back(state);
446 tmp = g_ascii_strdown(pl_get_marked_substring(state), -1);
447 if(g_strcmp0(tmp, "mod") == 0)
448 {
449 return l_insert_token(lstate, T_MOD);
450 }
451 if(g_strcmp0(tmp, "and") == 0)
452 {
453 return l_insert_token(lstate, T_AND);
454 }
455 if(g_strcmp0(tmp, "or") == 0)
456 {
457 return l_insert_token(lstate, T_OR);
458 }
459 if(g_strcmp0(tmp, "xor") == 0)
460 {
461 return l_insert_token(lstate, T_XOR);
462 }
463 if(g_strcmp0(tmp, "not") == 0)
464 {
465 return l_insert_token(lstate, T_NOT);
466 }
467 if(g_strcmp0(tmp, "in") == 0)
468 {
469 return l_insert_token(lstate, T_IN);
470 }
471 if(l_check_if_function(lstate))
472 {
473 return l_insert_token(lstate, T_FUNCTION);
474 }
475 else
476 {
477 return l_insert_token(lstate, T_VARIABLE);
478 }
479 }
480 else
481 {
482 pl_roll_back(state);
483 tmp = g_ascii_strdown(pl_get_marked_substring(state), -1);
484 if(g_strcmp0(tmp, "mod") == 0)
485 {
486 return l_insert_token(lstate, T_MOD);
487 }
488 if(g_strcmp0(tmp, "and") == 0)
489 {
490 return l_insert_token(lstate, T_AND);
491 }
492 if(g_strcmp0(tmp, "or") == 0)
493 {
494 return l_insert_token(lstate, T_OR);
495 }
496 if(g_strcmp0(tmp, "xor") == 0)
497 {
498 return l_insert_token(lstate, T_XOR);
499 }
500 if(g_strcmp0(tmp, "not") == 0)
501 {
502 return l_insert_token(lstate, T_NOT);
503 }
504 if(g_strcmp0(tmp, "in") == 0)
505 {
506 return l_insert_token(lstate, T_IN);
507 }
508 if(l_check_if_function(lstate))
509 {
510 return l_insert_token(lstate, T_FUNCTION);
511 }
512 else
513 {
514 return l_insert_token(lstate, T_VARIABLE);
515 }
516 }
517 }
518 }
519 if(type == PL_EOS)
520 {
521 return l_insert_token(lstate, PL_EOS);
522 }
523 /* ERROR: Unexpected token.. X( */
524 set_error(lstate->parent, PARSER_ERR_INVALID, tmp = pl_get_marked_substring(state));
525 free(tmp);
526 return l_insert_token(lstate, T_UNKNOWN);
527}
528
529/* Call l_insert_next_token() as many times as needed to completely tokenize the string. */
530void
531l_insert_all_tokens(LexerState* state)
532{
533 LexerToken* token;
534 while(1)
535 {
536 token = l_insert_next_token(state);
537 assert(token != NULL)((void) sizeof ((token != ((void*)0)) ? 1 : 0), __extension__
({ if (token != ((void*)0)) ; else __assert_fail ("token != NULL"
, "lexer.c", 537, __extension__ __PRETTY_FUNCTION__); }))
;
538 if(token->token_type == PL_EOS)
539 {
540 break;
541 }
542 }
543}
544
545/* Create a lexer state from given input string. This will take care of pre-lexer state. */
546LexerState*
547l_create_lexer(const gchar* input, struct parser_state* parent)
548{
549 LexerState* ret;
550 ret = (LexerState *) malloc(sizeof(LexerState));
551 assert(ret != NULL)((void) sizeof ((ret != ((void*)0)) ? 1 : 0), __extension__ (
{ if (ret != ((void*)0)) ; else __assert_fail ("ret != NULL",
"lexer.c", 551, __extension__ __PRETTY_FUNCTION__); }))
;
552 ret->prelexer = pl_create_scanner(input);
553 ret->tokens = NULL((void*)0);
554 ret->token_count = 0;
555 ret->next_token = 0;
556 ret->parent = parent;
557 return ret;
558}
559
560/* Destroy lexer state and free memory. */
561void
562l_destroy_lexer(LexerState* state)
563{
564 int l;
565 pl_destroy_scanner(state->prelexer);
566 for(l = 0; l < state->token_count; l++)
567 {
568 free(state->tokens[l].string);
569 }
570 free(state->tokens);
571 free(state);
572}
573
574/* Get next token interface. Will be called by parser to get pointer to next token in token stream. */
575LexerToken*
576l_get_next_token(LexerState* state)
577{
578 /* Return PL_EOS token after token stream reaches to its end. */
579 if(state->next_token >= state->token_count)
580 return &state->tokens[state->token_count - 1];
581 return &state->tokens[state->next_token++];
582}
583
584/* Roll back one lexer token. */
585void
586l_roll_back(LexerState* state)
587{
588 if(state->next_token > 0)
589 state->next_token--;
590}
diff --git a/2024-07-10-100902-3667-1@fe495df3ec39_master/report-397825.html b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-397825.html new file mode 100644 index 0000000..137d256 --- /dev/null +++ b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-397825.html @@ -0,0 +1,1733 @@ + + + +mp.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:mp.c
Warning:line 956, column 24
Access to field 'data' results in a dereference of a null pointer (loaded from variable 'list')
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name mp.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D LOCALE_DIR="/usr/local/share/locale" -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/atk-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/gio-unix-2.0 -D WITH_GZFILEOP -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-07-10-100902-3667-1 -x c mp.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * Copyright (C) 2008-2011 Robert Ancell
4 *
5 * This program is free software: you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation, either version 2 of the License, or (at your option) any later
8 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
9 * license.
10 */
11
12#include <stdlib.h>
13#include <stdio.h>
14#include <stdint.h>
15#include <math.h>
16#include <errno(*__errno_location ()).h>
17
18#include "mp.h"
19
20char *mp_error = NULL((void*)0);
21
22/* THIS ROUTINE IS CALLED WHEN AN ERROR CONDITION IS ENCOUNTERED, AND
23 * AFTER A MESSAGE HAS BEEN WRITTEN TO STDERR.
24 */
25void
26mperr(const char *format, ...)
27{
28 char text[1024];
29 va_list args;
30
31 va_start(args, format)__builtin_va_start(args, format);
32 vsnprintf(text, 1024, format, args);
33 va_end(args)__builtin_va_end(args);
34
35 if (mp_error)
36 free(mp_error);
37 mp_error = strdup(text);
38}
39
40const char *
41mp_get_error()
42{
43 return mp_error;
44}
45
46void mp_clear_error()
47{
48 if (mp_error)
49 free(mp_error);
50 mp_error = NULL((void*)0);
51}
52
53MPNumber
54mp_new(void)
55{
56 MPNumber z;
57 mpc_init2(z.num, PRECISION1000);
58 return z;
59}
60
61MPNumber
62mp_new_from_unsigned_integer(ulong x)
63{
64 MPNumber z;
65 mpc_init2(z.num, PRECISION1000);
66 mpc_set_ui(z.num, x, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
67 return z;
68}
69
70MPNumber *
71mp_new_ptr(void)
72{
73 MPNumber *z = malloc(sizeof(MPNumber));
74 mpc_init2(z->num, PRECISION1000);
75 return z;
76}
77
78void
79mp_clear(MPNumber *z)
80{
81 if (z != NULL((void*)0))
82 mpc_clear(z->num);
83}
84
85void
86mp_free(MPNumber *z)
87{
88 if (z != NULL((void*)0))
89 {
90 mpc_clear(z->num);
91 free(z);
92 }
93}
94
95void
96mp_get_eulers(MPNumber *z)
97{
98 /* e^1, since mpfr doesn't have a function to return e */
99 mpfr_set_ui(mpc_realref(z->num), 1, MPFR_RNDN)(__builtin_constant_p (1) && (mpfr_ulong) (1) == 0 ? __extension__
({ mpfr_ptr _p = (((z->num)->re)); _p->_mpfr_sign =
1; _p->_mpfr_exp = (0 - ((mpfr_exp_t) (((mpfr_uexp_t) -1)
>> 1))); (mpfr_void) (MPFR_RNDN); 0; }) : mpfr_set_ui_2exp
((((z->num)->re)), (1), 0, (MPFR_RNDN)))
;
100 mpfr_exp(mpc_realref(z->num)((z->num)->re), mpc_realref(z->num)((z->num)->re), MPFR_RNDN);
101 mpfr_set_zero(mpc_imagref(z->num)((z->num)->im), 0);
102}
103
104void
105mp_get_i(MPNumber *z)
106{
107 mpc_set_si_si(z->num, 0, 1, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
108}
109
110void
111mp_abs(const MPNumber *x, MPNumber *z)
112{
113 mpfr_set_zero(mpc_imagref(z->num)((z->num)->im), MPFR_RNDN);
114 mpc_abs(mpc_realref(z->num)((z->num)->re), x->num, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
115}
116
117void
118mp_arg(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
119{
120 if (mp_is_zero(x))
121 {
122 /* Translators: Error display when attempting to take argument of zero */
123 mperr(_("Argument not defined for zero")dcgettext (((void*)0), "Argument not defined for zero", 5));
124 mp_set_from_integer(0, z);
125 return;
126 }
127
128 mpfr_set_zero(mpc_imagref(z->num)((z->num)->im), MPFR_RNDN);
129 mpc_arg(mpc_realref(z->num)((z->num)->re), x->num, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
130 convert_from_radians(z, unit, z);
131 // MPC returns -π for the argument of negative real numbers if
132 // their imaginary part is -0, we want +π for all real negative
133 // numbers
134 if (!mp_is_complex (x) && mp_is_negative (x))
135 mpfr_abs(mpc_realref(z->num), mpc_realref(z->num), MPFR_RNDN)mpfr_set4(((z->num)->re),((z->num)->re),MPFR_RNDN
,1)
;
136}
137
138void
139mp_conjugate(const MPNumber *x, MPNumber *z)
140{
141 mpc_conj(z->num, x->num, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
142}
143
144void
145mp_real_component(const MPNumber *x, MPNumber *z)
146{
147 mpc_set_fr(z->num, mpc_realref(x->num)((x->num)->re), MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
148}
149
150void
151mp_imaginary_component(const MPNumber *x, MPNumber *z)
152{
153 mpc_set_fr(z->num, mpc_imagref(x->num)((x->num)->im), MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
154}
155
156void
157mp_add(const MPNumber *x, const MPNumber *y, MPNumber *z)
158{
159 mpc_add(z->num, x->num, y->num, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
160}
161
162void
163mp_add_integer(const MPNumber *x, long y, MPNumber *z)
164{
165 mpc_add_si(z->num, x->num, y, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
166}
167
168void
169mp_subtract(const MPNumber *x, const MPNumber *y, MPNumber *z)
170{
171 mpc_sub(z->num, x->num, y->num, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
172}
173
174void
175mp_sgn(const MPNumber *x, MPNumber *z)
176{
177 mpc_set_si(z->num, mpfr_sgn(mpc_realref(x->num))((((x->num)->re))->_mpfr_exp < (2 - ((mpfr_exp_t)
(((mpfr_uexp_t) -1) >> 1))) ? ((((mpfr_srcptr) (0 ? ((
(x->num)->re)) : (mpfr_srcptr) (((x->num)->re))))
->_mpfr_exp == (1 - ((mpfr_exp_t) (((mpfr_uexp_t) -1) >>
1)))) ? mpfr_set_erangeflag () : (mpfr_void) 0), 0 : ((((x->
num)->re))->_mpfr_sign))
, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
178}
179
180void
181mp_integer_component(const MPNumber *x, MPNumber *z)
182{
183 mpfr_set_zero(mpc_imagref(z->num)((z->num)->im), MPFR_RNDN);
184 mpfr_trunc(mpc_realref(z->num), mpc_realref(x->num))mpfr_rint((((z->num)->re)), (((x->num)->re)), MPFR_RNDZ
)
;
185}
186
187void
188mp_fractional_component(const MPNumber *x, MPNumber *z)
189{
190 mpfr_set_zero(mpc_imagref(z->num)((z->num)->im), MPFR_RNDN);
191 mpfr_frac(mpc_realref(z->num)((z->num)->re), mpc_realref(x->num)((x->num)->re), MPFR_RNDN);
192}
193
194void
195mp_fractional_part(const MPNumber *x, MPNumber *z)
196{
197 MPNumber f = mp_new();
198 mp_floor(x, &f);
199 mp_subtract(x, &f, z);
200 mp_clear(&f);
201}
202
203void
204mp_floor(const MPNumber *x, MPNumber *z)
205{
206 mpfr_set_zero(mpc_imagref(z->num)((z->num)->im), MPFR_RNDN);
207 mpfr_floor(mpc_realref(z->num), mpc_realref(x->num))mpfr_rint((((z->num)->re)), (((x->num)->re)), MPFR_RNDD
)
;
208}
209
210void
211mp_ceiling(const MPNumber *x, MPNumber *z)
212{
213 mpfr_set_zero(mpc_imagref(z->num)((z->num)->im), MPFR_RNDN);
214 mpfr_ceil(mpc_realref(z->num), mpc_realref(x->num))mpfr_rint((((z->num)->re)), (((x->num)->re)), MPFR_RNDU
)
;
215}
216
217void
218mp_round(const MPNumber *x, MPNumber *z)
219{
220 mpfr_set_zero(mpc_imagref(z->num)((z->num)->im), MPFR_RNDN);
221 mpfr_round(mpc_realref(z->num), mpc_realref(x->num))mpfr_rint((((z->num)->re)), (((x->num)->re)), MPFR_RNDNA
)
;
222}
223
224int
225mp_compare(const MPNumber *x, const MPNumber *y)
226{
227 return mpfr_cmp(mpc_realref(x->num), mpc_realref(y->num))mpfr_cmp3(((x->num)->re), ((y->num)->re), 1);
228}
229
230void
231mp_divide(const MPNumber *x, const MPNumber *y, MPNumber *z)
232{
233 if (mp_is_zero(y))
234 {
235 /* Translators: Error displayed attempted to divide by zero */
236 mperr(_("Division by zero is undefined")dcgettext (((void*)0), "Division by zero is undefined", 5));
237 mp_set_from_integer(0, z);
238 return;
239 }
240 mpc_div(z->num, x->num, y->num, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
241}
242
243void
244mp_divide_integer(const MPNumber *x, long y, MPNumber *z)
245{
246 MPNumber t1 = mp_new();
247
248 mp_set_from_integer(y, &t1);
249 mp_divide(x, &t1, z);
250 mp_clear(&t1);
251}
252
253bool_Bool
254mp_is_integer(const MPNumber *x)
255{
256 if (mp_is_complex(x))
257 return false0;
258
259 return mpfr_integer_p(mpc_realref(x->num)((x->num)->re)) != 0;
260}
261
262bool_Bool
263mp_is_positive_integer(const MPNumber *x)
264{
265 if (mp_is_complex(x))
266 return false0;
267 else
268 return mpfr_sgn(mpc_realref(x->num))((((x->num)->re))->_mpfr_exp < (2 - ((mpfr_exp_t)
(((mpfr_uexp_t) -1) >> 1))) ? ((((mpfr_srcptr) (0 ? ((
(x->num)->re)) : (mpfr_srcptr) (((x->num)->re))))
->_mpfr_exp == (1 - ((mpfr_exp_t) (((mpfr_uexp_t) -1) >>
1)))) ? mpfr_set_erangeflag () : (mpfr_void) 0), 0 : ((((x->
num)->re))->_mpfr_sign))
>= 0 && mp_is_integer(x);
269}
270
271bool_Bool
272mp_is_natural(const MPNumber *x)
273{
274 if (mp_is_complex(x))
275 return false0;
276 else
277 return mpfr_sgn(mpc_realref(x->num))((((x->num)->re))->_mpfr_exp < (2 - ((mpfr_exp_t)
(((mpfr_uexp_t) -1) >> 1))) ? ((((mpfr_srcptr) (0 ? ((
(x->num)->re)) : (mpfr_srcptr) (((x->num)->re))))
->_mpfr_exp == (1 - ((mpfr_exp_t) (((mpfr_uexp_t) -1) >>
1)))) ? mpfr_set_erangeflag () : (mpfr_void) 0), 0 : ((((x->
num)->re))->_mpfr_sign))
> 0 && mp_is_integer(x);
278}
279
280bool_Bool
281mp_is_complex(const MPNumber *x)
282{
283 return !mpfr_zero_p(mpc_imagref(x->num))(((mpfr_srcptr) (0 ? (((x->num)->im)) : (mpfr_srcptr) (
((x->num)->im))))->_mpfr_exp == (0 - ((mpfr_exp_t) (
((mpfr_uexp_t) -1) >> 1))))
;
284}
285
286bool_Bool
287mp_is_equal(const MPNumber *x, const MPNumber *y)
288{
289 int res = mpc_cmp(x->num, y->num);
290 return MPC_INEX_RE(res)((((res) & 3) == 2) ? -1 : (((res) & 3) == 0) ? 0 : 1
)
== 0 && MPC_INEX_IM(res)((((res) >> 2) == 2) ? -1 : (((res) >> 2) == 0) ?
0 : 1)
== 0;
291}
292
293void
294mp_epowy(const MPNumber *x, MPNumber *z)
295{
296 mpc_exp(z->num, x->num, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
297}
298
299bool_Bool
300mp_is_zero (const MPNumber *x)
301{
302 int res = mpc_cmp_si_si(x->num, 0, 0);
303 return MPC_INEX_RE(res)((((res) & 3) == 2) ? -1 : (((res) & 3) == 0) ? 0 : 1
)
== 0 && MPC_INEX_IM(res)((((res) >> 2) == 2) ? -1 : (((res) >> 2) == 0) ?
0 : 1)
== 0;
304}
305
306bool_Bool
307mp_is_negative(const MPNumber *x)
308{
309 return mpfr_sgn(mpc_realref(x->num))((((x->num)->re))->_mpfr_exp < (2 - ((mpfr_exp_t)
(((mpfr_uexp_t) -1) >> 1))) ? ((((mpfr_srcptr) (0 ? ((
(x->num)->re)) : (mpfr_srcptr) (((x->num)->re))))
->_mpfr_exp == (1 - ((mpfr_exp_t) (((mpfr_uexp_t) -1) >>
1)))) ? mpfr_set_erangeflag () : (mpfr_void) 0), 0 : ((((x->
num)->re))->_mpfr_sign))
< 0;
310}
311
312bool_Bool
313mp_is_greater_equal(const MPNumber *x, const MPNumber *y)
314{
315 return mp_compare(x, y) >= 0;
316}
317
318bool_Bool
319mp_is_greater_than(const MPNumber *x, const MPNumber *y)
320{
321 return mp_compare(x, y) > 0;
322}
323
324bool_Bool
325mp_is_less_equal(const MPNumber *x, const MPNumber *y)
326{
327 return mp_compare(x, y) <= 0;
328}
329
330bool_Bool
331mp_is_less_than(const MPNumber *x, const MPNumber *y)
332{
333 return mp_compare(x, y) < 0;
334}
335
336void
337mp_ln(const MPNumber *x, MPNumber *z)
338{
339 /* ln(0) undefined */
340 if (mp_is_zero(x))
341 {
342 /* Translators: Error displayed when attempting to take logarithm of zero */
343 mperr(_("Logarithm of zero is undefined")dcgettext (((void*)0), "Logarithm of zero is undefined", 5));
344 mp_set_from_integer(0, z);
345 return;
346 }
347
348 /* ln(-x) complex */
349 /* FIXME: Make complex numbers optional */
350 /*if (mp_is_negative(x)) {
351 // Translators: Error displayed attempted to take logarithm of negative value
352 mperr(_("Logarithm of negative values is undefined"));
353 mp_set_from_integer(0, z);
354 return;
355 }*/
356
357 mpc_log(z->num, x->num, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
358 // MPC returns -π for the imaginary part of the log of
359 // negative real numbers if their imaginary part is -0, we want +π
360 if (!mp_is_complex (x) && mp_is_negative (x))
361 mpfr_abs(mpc_imagref(z->num), mpc_imagref(z->num), MPFR_RNDN)mpfr_set4(((z->num)->im),((z->num)->im),MPFR_RNDN
,1)
;
362}
363
364void
365mp_logarithm(long n, const MPNumber *x, MPNumber *z)
366{
367 /* log(0) undefined */
368 if (mp_is_zero(x))
369 {
370 /* Translators: Error displayed when attempting to take logarithm of zero */
371 mperr(_("Logarithm of zero is undefined")dcgettext (((void*)0), "Logarithm of zero is undefined", 5));
372 mp_set_from_integer(0, z);
373 return;
374 }
375
376 /* logn(x) = ln(x) / ln(n) */
377 MPNumber t1 = mp_new();
378 mp_set_from_integer(n, &t1);
379 mp_ln(&t1, &t1);
380 mp_ln(x, z);
381 mp_divide(z, &t1, z);
382 mp_clear(&t1);
383}
384
385void
386mp_multiply(const MPNumber *x, const MPNumber *y, MPNumber *z)
387{
388 mpc_mul(z->num, x->num, y->num, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
389}
390
391void
392mp_multiply_integer(const MPNumber *x, long y, MPNumber *z)
393{
394 mpc_mul_si(z->num, x->num, y, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
395}
396
397void
398mp_invert_sign(const MPNumber *x, MPNumber *z)
399{
400 mpc_neg(z->num, x->num, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
401}
402
403void
404mp_reciprocal(const MPNumber *x, MPNumber *z)
405{
406 mpc_t temp;
407 mpc_init2(temp, PRECISION1000);
408 mpc_set_ui(temp, 1, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
409 mpc_fr_div(z->num, mpc_realref(temp)((temp)->re), x->num, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
410 mpc_clear(temp);
411}
412
413void
414mp_root(const MPNumber *x, long n, MPNumber *z)
415{
416 ulong p;
417
418 if (n < 0)
419 {
420 mpc_ui_div(z->num, 1, x->num, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
421
422 if (n == LONG_MIN(-9223372036854775807L -1L))
423 p = (ulong) LONG_MAX9223372036854775807L + 1;
424 else
425 p = (ulong) -n;
426 }
427 else if (n > 0)
428 {
429 mp_set_from_mp(x, z);
430 p = n;
431 }
432 else
433 { /* Translators: Error displayed when attempting to take zeroth root */
434 mperr(_("The zeroth root of a number is undefined")dcgettext (((void*)0), "The zeroth root of a number is undefined"
, 5)
);
435 mp_set_from_integer(0, z);
436 return;
437 }
438 if (!mp_is_complex(x) && (!mp_is_negative(x) || (p & 1) == 1))
439 {
440 mpfr_rootn_ui(mpc_realref(z->num)((z->num)->re), mpc_realref(z->num)((z->num)->re), p, MPFR_RNDN);
441 mpfr_set_zero(mpc_imagref(z->num)((z->num)->im), MPFR_RNDN);
442 }
443 else
444 {
445 mpfr_t tmp;
446 mpfr_init2(tmp, PRECISION1000);
447 mpfr_set_ui(tmp, p, MPFR_RNDN)(__builtin_constant_p (p) && (mpfr_ulong) (p) == 0 ? __extension__
({ mpfr_ptr _p = (tmp); _p->_mpfr_sign = 1; _p->_mpfr_exp
= (0 - ((mpfr_exp_t) (((mpfr_uexp_t) -1) >> 1))); (mpfr_void
) (MPFR_RNDN); 0; }) : mpfr_set_ui_2exp ((tmp), (p), 0, (MPFR_RNDN
)))
;
448 mpfr_ui_div(tmp, 1, tmp, MPFR_RNDN);
449 mpc_pow_fr(z->num, z->num, tmp, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
450 mpfr_clear(tmp);
451 }
452}
453
454void
455mp_sqrt(const MPNumber *x, MPNumber *z)
456{
457 mp_root(x, 2, z);
458}
459
460void
461mp_factorial(const MPNumber *x, MPNumber *z)
462{
463 /* 0! == 1 */
464 if (mp_is_zero(x))
465 {
466 mpc_set_si(z->num, 1, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
467 return;
468 }
469 if (!mp_is_natural(x))
470 {
471 /* Factorial Not defined for Complex or for negative numbers */
472 if (mp_is_negative(x) || mp_is_complex(x))
473 { /* Translators: Error displayed when attempted take the factorial of a negative or complex number */
474 mperr(_("Factorial is only defined for non-negative real numbers")dcgettext (((void*)0), "Factorial is only defined for non-negative real numbers"
, 5)
);
475 mp_set_from_integer(0, z);
476 return;
477 }
478 MPNumber tmp = mp_new();
479 mpfr_t tmp2;
480 mpfr_init2(tmp2, PRECISION1000);
481 mp_set_from_integer(1, &tmp);
482 mp_add(&tmp, x, &tmp);
483
484 /* Factorial(x) = Gamma(x+1) - This is the formula used to calculate Factorial of positive real numbers.*/
485 mpfr_gamma(tmp2, mpc_realref(tmp.num)((tmp.num)->re), MPFR_RNDN);
486 mpc_set_fr(z->num, tmp2, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
487 mp_clear(&tmp);
488 mpfr_clear(tmp2);
489 }
490 else
491 {
492 /* Convert to integer - if couldn't be converted then the factorial would be too big anyway */
493 ulong value = mp_to_unsigned_integer(x);
494 mpfr_fac_ui(mpc_realref(z->num)((z->num)->re), value, MPFR_RNDN);
495 mpfr_set_zero(mpc_imagref(z->num)((z->num)->im), MPFR_RNDN);
496 }
497}
498
499void
500mp_modulus_divide(const MPNumber *x, const MPNumber *y, MPNumber *z)
501{
502 if (!mp_is_integer(x) || !mp_is_integer(y))
503 { /* Translators: Error displayed when attemping to do a modulus division on non-integer numbers */
504 mperr(_("Modulus division is only defined for integers")dcgettext (((void*)0), "Modulus division is only defined for integers"
, 5)
);
505 mp_set_from_integer(0, z);
506 return;
507 }
508
509 MPNumber t1 = mp_new();
510 MPNumber t2 = mp_new();
511
512 mp_divide(x, y, &t1);
513 mp_floor(&t1, &t1);
514 mp_multiply(&t1, y, &t2);
515 mp_subtract(x, &t2, z);
516
517 mp_set_from_integer(0, &t1);
518 if ((mp_compare(y, &t1) < 0 && mp_compare(z, &t1) > 0) ||
519 (mp_compare(y, &t1) > 0 && mp_compare(z, &t1) < 0))
520 mp_add(z, y, z);
521
522 mp_clear(&t1);
523 mp_clear(&t2);
524}
525
526void
527mp_modular_exponentiation(const MPNumber *x, const MPNumber *y, const MPNumber *p, MPNumber *z)
528{
529 MPNumber base_value = mp_new();
530 MPNumber exp_value = mp_new();
531 MPNumber ans = mp_new();
532 MPNumber two = mp_new();
533 MPNumber tmp = mp_new();
534
535 mp_set_from_integer(1, &ans);
536 mp_set_from_integer(2, &two);
537 mp_abs(y, &exp_value);
538
539 if (mp_is_negative(y))
540 mp_reciprocal(x, &base_value);
541 else
542 mp_set_from_mp(x, &base_value);
543
544 while (!mp_is_zero(&exp_value))
545 {
546 mp_modulus_divide(&exp_value, &two, &tmp);
547
548 bool_Bool is_even = mp_is_zero(&tmp);
549 if (!is_even)
550 {
551 mp_multiply(&ans, &base_value, &ans);
552 mp_modulus_divide(&ans, p, &ans);
553 }
554 mp_multiply(&base_value, &base_value, &base_value);
555 mp_modulus_divide(&base_value, p, &base_value);
556 mp_divide_integer(&exp_value, 2, &exp_value);
557 mp_floor(&exp_value, &exp_value);
558 }
559
560 mp_modulus_divide(&ans, p, z);
561
562 mp_clear(&base_value);
563 mp_clear(&exp_value);
564 mp_clear(&ans);
565 mp_clear(&two);
566 mp_clear(&tmp);
567}
568
569void
570mp_xpowy(const MPNumber *x, const MPNumber *y, MPNumber *z)
571{
572 /* 0^-n invalid */
573 if (mp_is_zero(x) && mp_is_negative(y))
574 { /* Translators: Error displayed when attempted to raise 0 to a negative exponent */
575 mperr(_("The power of zero is undefined for a negative exponent")dcgettext (((void*)0), "The power of zero is undefined for a negative exponent"
, 5)
);
576 mp_set_from_integer(0, z);
577 return;
578 }
579
580 if (!mp_is_complex(x) && !mp_is_complex(y) && !mp_is_integer(y))
581 {
582 MPNumber reciprocal = mp_new();
583 mp_reciprocal(y, &reciprocal);
584 if (mp_is_integer(&reciprocal))
585 {
586 mp_root(x, mp_to_integer(&reciprocal), z);
587 mp_clear(&reciprocal);
588 return;
589 }
590 mp_clear(&reciprocal);
591 }
592
593 mpc_pow(z->num, x->num, y->num, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
594}
595
596void
597mp_xpowy_integer(const MPNumber *x, long n, MPNumber *z)
598{
599 /* 0^-n invalid */
600 if (mp_is_zero(x) && n < 0)
601 { /* Translators: Error displayed when attempted to raise 0 to a negative re_exponent */
602 mperr(_("The power of zero is undefined for a negative exponent")dcgettext (((void*)0), "The power of zero is undefined for a negative exponent"
, 5)
);
603 mp_set_from_integer(0, z);
604 return;
605 }
606
607 mpc_pow_si(z->num, x->num, n, MPC_RNDNN(((int)(MPFR_RNDN)) + ((int)(MPFR_RNDN) << 4)));
608}
609
610void
611mp_erf(const MPNumber *x, MPNumber *z)
612{
613 if (mp_is_complex(x))
614 { /* Translators: Error displayed when error function (erf) value is undefined */
615 mperr(_("The error function is only defined for real numbers")dcgettext (((void*)0), "The error function is only defined for real numbers"
, 5)
);
616 mp_set_from_integer(0, z);
617 return;
618 }
619
620 mpfr_set_zero(mpc_imagref(z->num)((z->num)->im), MPFR_RNDN);
621 mpfr_erf(mpc_realref(z->num)((z->num)->re), mpc_realref(x->num)((x->num)->re), MPFR_RNDN);
622}
623
624void
625mp_zeta(const MPNumber *x, MPNumber *z)
626{
627 MPNumber one = mp_new();
628
629 mp_set_from_integer(1, &one);
630 if (mp_is_complex(x) || mp_compare(x, &one) == 0)
631 { /* Translators: Error displayed when zeta function value is undefined */
632 mperr(_("The Riemann zeta function is only defined for real numbers ≠1")dcgettext (((void*)0), "The Riemann zeta function is only defined for real numbers ≠1"
, 5)
);
633 mp_set_from_integer(0, z);
634 mp_clear(&one);
635 return;
636 }
637
638 mpfr_set_zero(mpc_imagref(z->num)((z->num)->im), MPFR_RNDN);
639 mpfr_zeta(mpc_realref(z->num)((z->num)->re), mpc_realref(x->num)((x->num)->re), MPFR_RNDN);
640
641 mp_clear(&one);
642}
643
644/***********************************************************************/
645/** FACTORIZATION **/
646/***********************************************************************/
647
648/**
649 * mp_is_pprime uses the Miller-Rabin primality test to decide
650 * whether or not a number is probable prime.
651 * For special values of @n and @rounds it can be deterministic,
652 * but in general the probability of declaring @n as prime if it
653 * is not is at most 4^(-@rounds).
654 * @n has to be odd.
655 * Returns TRUE if @n is probable prime and FALSE otherwise.
656 */
657static bool_Bool
658mp_is_pprime(MPNumber *n, ulong rounds)
659{
660 MPNumber tmp = mp_new();
661 MPNumber two = mp_new_from_unsigned_integer(2);
662 ulong l = 0;
663 bool_Bool is_pprime = TRUE(!(0));
664
665 /* Write t := n-1 = 2^l * q with q odd */
666 MPNumber q = mp_new();
667 MPNumber t = mp_new();
668 mp_add_integer(n, -1, &t);
669 mp_set_from_mp(&t, &q);
670 do
671 {
672 mp_divide_integer(&q, 2, &q);
673 mp_modulus_divide(&q, &two, &tmp);
674 l++;
675 } while (mp_is_zero(&tmp));
676
677 /* @rounds Miller-Rabin tests to bases a = 2,3,...,@rounds+1 */
678 MPNumber one = mp_new_from_unsigned_integer(1);
679 MPNumber a = mp_new_from_unsigned_integer(1);
680 MPNumber b = mp_new();
681
682 for (ulong i = 1; (i < mp_to_integer(&t)) && (i <= rounds+1); i++)
683 {
684 mp_add_integer(&a, 1, &a);
685 mp_modular_exponentiation(&a, &q, n, &b);
686 if (mp_compare(&one, &b) == 0 || mp_compare(&t, &b) == 0)
687 {
688 continue;
689 }
690
691 bool_Bool is_witness = FALSE(0);
692 for (long j = 1; j < l; j++)
693 {
694 mp_modular_exponentiation(&b, &two, n, &b);
695 if (mp_compare(&b, &t) == 0)
696 {
697 is_witness = TRUE(!(0));
698 break;
699 }
700 }
701
702 if (!is_witness)
703 {
704 is_pprime = FALSE(0);
705 break;
706 }
707 }
708
709 mp_clear(&t);
710 mp_clear(&q);
711 mp_clear(&a);
712 mp_clear(&b);
713 mp_clear(&one);
714 mp_clear(&two);
715 mp_clear(&tmp);
716
717 return is_pprime;
718}
719
720/**
721 * Sets z = gcd(a,b) where gcd(a,b) is the greatest common divisor of @a and @b.
722 */
723static void
724mp_gcd (const MPNumber *a, const MPNumber *b, MPNumber *z)
725{
726 MPNumber null = mp_new_from_unsigned_integer(0);
727 MPNumber t1 = mp_new();
728 MPNumber t2 = mp_new();
729
730 mp_set_from_mp(a, z);
731 mp_set_from_mp(b, &t2);
732
733 while (mp_compare(&t2, &null) != 0)
734 {
735 mp_set_from_mp(&t2, &t1);
736 mp_modulus_divide(z, &t2, &t2);
737 mp_set_from_mp(&t1, z);
738 }
739
740 mp_clear(&null);
741 mp_clear(&t1);
742 mp_clear(&t2);
743}
744
745/**
746 * mp_pollard_rho searches a divisor of @n using Pollard's rho algorithm.
747 * @i is the start value of the pseudorandom sequence which is generated
748 * by the polynomial x^2+1 mod n.
749 *
750 * Returns TRUE if a divisor was found and stores the divisor in z.
751 * Returns FALSE otherwise.
752 */
753static bool_Bool
754mp_pollard_rho (const MPNumber *n, ulong i, MPNumber *z)
755{
756 MPNumber one = mp_new_from_unsigned_integer(1);
757 MPNumber two = mp_new_from_unsigned_integer(2);
758 MPNumber x = mp_new_from_unsigned_integer(i);
759 MPNumber y = mp_new_from_unsigned_integer(2);
760 MPNumber d = mp_new_from_unsigned_integer(1);
761
762 while (mp_compare(&d, &one) == 0)
763 {
764 mp_modular_exponentiation(&x, &two, n, &x);
765 mp_add(&x, &one, &x);
766
767 mp_modular_exponentiation(&y, &two, n, &y);
768 mp_add(&y, &one, &y);
769
770 mp_modular_exponentiation(&y, &two, n, &y);
771 mp_add(&y, &one, &y);
772
773 mp_subtract(&x, &y,z);
774 mp_abs(z, z);
775 mp_gcd(z, n, &d);
776 }
777
778 if (mp_compare(&d, n) == 0)
779 {
780 mp_clear(&one);
781 mp_clear(&two);
782 mp_clear(&x);
783 mp_clear(&y);
784 mp_clear(&d);
785
786 return FALSE(0);
787 }
788 else
789 {
790 mp_set_from_mp(&d, z);
791
792 mp_clear(&one);
793 mp_clear(&two);
794 mp_clear(&x);
795 mp_clear(&y);
796 mp_clear(&d);
797
798 return TRUE(!(0));
799 }
800}
801
802/**
803 * find_big_prime_factor acts as driver function for mp_pollard_rho which
804 * is run as long as a prime factor is found.
805 * On success sets @z to a prime factor of @n.
806 */
807static void
808find_big_prime_factor (const MPNumber *n, MPNumber *z)
809{
810 MPNumber tmp = mp_new();
811 ulong i = 2;
812
813 while (TRUE(!(0)))
814 {
815 while (mp_pollard_rho (n, i, &tmp) == FALSE(0))
816 {
817 i++;
818 }
819
820 if (!mp_is_pprime(&tmp, 50))
821 {
822 mp_divide(n, &tmp, &tmp);
823 }
824 else
825 break;
826 }
827
828 mp_set_from_mp(&tmp, z);
829 mp_clear(&tmp);
830}
831
832/**
833 * mp_factorize tries to factorize the value of @x.
834 * If @x < 2^64 it calls mp_factorize_unit64 which deals in integers
835 * and should be fast enough for most values.
836 * If @x > 2^64 the approach to find factors of @x is as follows:
837 * - Try to divide @x by prime numbers 2,3,5,7,.. up to min(2^13, sqrt(x))
838 * - Use Pollard rho to find prime factors > 2^13.
839 * Returns a pointer to a GList with all prime factors of @x which needs to
840 * be freed.
841 */
842GList*
843mp_factorize(const MPNumber *x)
844{
845 GList *list = NULL((void*)0);
1
'list' initialized to a null pointer value
846 MPNumber *factor = g_slice_alloc0(sizeof(MPNumber));
847 mpc_init2(factor->num, PRECISION1000);
848
849 MPNumber value = mp_new();
850 mp_abs(x, &value);
851
852 if (mp_is_zero(&value))
2
Taking false branch
853 {
854 mp_set_from_mp(&value, factor);
855 list = g_list_append(list, factor);
856 mp_clear(&value);
857 return list;
858 }
859
860 MPNumber tmp = mp_new();
861 mp_set_from_integer(1, &tmp);
862 if (mp_is_equal(&value, &tmp))
3
Taking false branch
863 {
864 mp_set_from_mp(x, factor);
865 list = g_list_append(list, factor);
866 mp_clear(&value);
867 mp_clear(&tmp);
868 return list;
869 }
870
871 /* If value < 2^64-1, call for factorize_uint64 function which deals in integers */
872 uint64_t num = 1;
873 num = num << 63;
874 num += (num - 1);
875 MPNumber int_max = mp_new();
876 mp_set_from_unsigned_integer(num, &int_max);
877 if (mp_is_less_equal(x, &int_max))
4
Taking false branch
878 {
879 list = mp_factorize_unit64(mp_to_unsigned_integer(&value));
880 if (mp_is_negative(x))
881 mp_invert_sign(list->data, list->data);
882 mp_clear(&value);
883 mp_clear(&tmp);
884 mp_clear(&int_max);
885 return list;
886 }
887
888 MPNumber divisor = mp_new_from_unsigned_integer(2);
889 while (TRUE(!(0)))
5
Loop condition is true. Entering loop body
890 {
891 mp_divide(&value, &divisor, &tmp);
892 if (mp_is_integer(&tmp))
6
Taking false branch
893 {
894 mp_set_from_mp(&tmp, &value);
895 mp_set_from_mp(&divisor, factor);
896 list = g_list_append(list, factor);
897 factor = g_slice_alloc0(sizeof(MPNumber));
898 mpc_init2(factor->num, PRECISION1000);
899 }
900 else
901 break;
902 }
903
904 mp_set_from_integer(3, &divisor);
905
906 MPNumber root = mp_new();
907 mp_sqrt(&value, &root);
908 uint64_t max_trial_division = (uint64_t) (1 << 10);
909 uint64_t iter = 0;
910 while (mp_is_less_equal(&divisor, &root) && (iter++ < max_trial_division))
911 {
912 mp_divide(&value, &divisor, &tmp);
913 if (mp_is_integer(&tmp))
914 {
915 mp_set_from_mp(&tmp, &value);
916 mp_sqrt(&value, &root);
917 mp_set_from_mp(&divisor, factor);
918 list = g_list_append(list, factor);
919 factor = g_slice_alloc0(sizeof(MPNumber));
920 mpc_init2(factor->num, PRECISION1000);
921 }
922 else
923 {
924 mp_add_integer(&divisor, 2, &divisor);
925 }
926 }
927
928 while (!mp_is_pprime(&value, 50))
7
Loop condition is false. Execution continues on line 943
929 {
930 find_big_prime_factor (&value, &divisor);
931
932 mp_divide(&value, &divisor, &tmp);
933 if (mp_is_integer(&tmp))
934 {
935 mp_set_from_mp(&tmp, &value);
936 mp_set_from_mp(&divisor, factor);
937 list = g_list_append(list, factor);
938 factor = g_slice_alloc0(sizeof(MPNumber));
939 mpc_init2(factor->num, PRECISION1000);
940 }
941 }
942
943 mp_set_from_integer(1, &tmp);
944 if (mp_is_greater_than(&value, &tmp))
8
Taking false branch
945 {
946 mp_set_from_mp(&value, factor);
947 list = g_list_append(list, factor);
948 }
949 else
950 {
951 mpc_clear(factor->num);
952 g_slice_free(MPNumber, factor)do { if (1) g_slice_free1 (sizeof (MPNumber), (factor)); else
(void) ((MPNumber*) 0 == (factor)); } while (0)
;
9
Taking true branch
10
Loop condition is false. Exiting loop
953 }
954
955 if (mp_is_negative(x))
11
Taking true branch
956 mp_invert_sign(list->data, list->data);
12
Access to field 'data' results in a dereference of a null pointer (loaded from variable 'list')
957
958 mp_clear(&value);
959 mp_clear(&tmp);
960 mp_clear(&divisor);
961 mp_clear(&root);
962
963 return list;
964}
965
966GList*
967mp_factorize_unit64(uint64_t n)
968{
969 GList *list = NULL((void*)0);
970 MPNumber *factor = g_slice_alloc0(sizeof(MPNumber));
971 mpc_init2(factor->num, PRECISION1000);
972
973 MPNumber tmp = mp_new();
974 mp_set_from_unsigned_integer(2, &tmp);
975 while (n % 2 == 0)
976 {
977 n /= 2;
978 mp_set_from_mp(&tmp, factor);
979 list = g_list_append(list, factor);
980 factor = g_slice_alloc0(sizeof(MPNumber));
981 mpc_init2(factor->num, PRECISION1000);
982 }
983
984 for (uint64_t divisor = 3; divisor <= n / divisor; divisor +=2)
985 {
986 while (n % divisor == 0)
987 {
988 n /= divisor;
989 mp_set_from_unsigned_integer(divisor, factor);
990 list = g_list_append(list, factor);
991 factor = g_slice_alloc0(sizeof(MPNumber));
992 mpc_init2(factor->num, PRECISION1000);
993 }
994 }
995
996 if (n > 1)
997 {
998 mp_set_from_unsigned_integer(n, factor);
999 list = g_list_append(list, factor);
1000 }
1001 else
1002 {
1003 mpc_clear(factor->num);
1004 g_slice_free(MPNumber, factor)do { if (1) g_slice_free1 (sizeof (MPNumber), (factor)); else
(void) ((MPNumber*) 0 == (factor)); } while (0)
;
1005 }
1006 mp_clear(&tmp);
1007
1008 return list;
1009}
diff --git a/2024-07-10-100902-3667-1@fe495df3ec39_master/report-458ccc.html b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-458ccc.html new file mode 100644 index 0000000..84e48b8 --- /dev/null +++ b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-458ccc.html @@ -0,0 +1,2072 @@ + + + +math-buttons.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:math-buttons.c
Warning:line 472, column 9
Value stored to 'valid' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name math-buttons.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D LOCALE_DIR="/usr/local/share/locale" -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/atk-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/gio-unix-2.0 -D WITH_GZFILEOP -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-07-10-100902-3667-1 -x c math-buttons.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright (C) 2008-2011 Robert Ancell
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License as published by the Free Software
6 * Foundation, either version 2 of the License, or (at your option) any later
7 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
8 * license.
9 */
10
11#include <glib/gi18n.h>
12
13#include "math-buttons.h"
14#include "math-converter.h"
15#include "math-variable-popup.h"
16#include "financial.h"
17#include "mp-serializer.h"
18#include "utility.h"
19
20enum {
21 PROP_0,
22 PROP_EQUATION,
23 PROP_MODE,
24 PROP_PROGRAMMING_BASE
25};
26
27static GType button_mode_type;
28
29#define MAXBITS64 64 /* Bit panel: number of bit fields. */
30
31struct MathButtonsPrivate
32{
33 MathEquation *equation;
34
35 ButtonMode mode;
36 gint programming_base;
37
38 MathConverter *converter;
39
40 GtkBuilder *basic_ui, *advanced_ui, *financial_ui, *programming_ui;
41
42 GtkWidget *bas_panel, *adv_panel, *fin_panel, *prog_panel;
43 GtkWidget *active_panel;
44
45 GtkWidget *shift_left_menu, *shift_right_menu;
46
47 GtkWidget *function_menu;
48 GtkWidget *const_menu;
49
50 GList *superscript_toggles;
51 GList *subscript_toggles;
52
53 GtkWidget *base_combo;
54 GtkWidget *base_label;
55 GtkWidget *bit_panel;
56 GtkWidget *bit_labels[MAXBITS64];
57
58 GtkWidget *character_code_dialog;
59 GtkWidget *character_code_entry;
60};
61
62G_DEFINE_TYPE_WITH_PRIVATE (MathButtons, math_buttons, GTK_TYPE_BOX)static void math_buttons_init (MathButtons *self); static void
math_buttons_class_init (MathButtonsClass *klass); static GType
math_buttons_get_type_once (void); static gpointer math_buttons_parent_class
= ((void*)0); static gint MathButtons_private_offset; static
void math_buttons_class_intern_init (gpointer klass) { math_buttons_parent_class
= g_type_class_peek_parent (klass); if (MathButtons_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &MathButtons_private_offset
); math_buttons_class_init ((MathButtonsClass*) klass); } __attribute__
((__unused__)) static inline gpointer math_buttons_get_instance_private
(MathButtons *self) { return (((gpointer) ((guint8*) (self) +
(glong) (MathButtons_private_offset)))); } GType math_buttons_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= math_buttons_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType math_buttons_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
gtk_box_get_type ()), g_intern_static_string ("MathButtons"),
sizeof (MathButtonsClass), (GClassInitFunc)(void (*)(void)) math_buttons_class_intern_init
, sizeof (MathButtons), (GInstanceInitFunc)(void (*)(void)) math_buttons_init
, (GTypeFlags) 0); { {{ MathButtons_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (MathButtonsPrivate)); };} } return
g_define_type_id; }
;
63
64#define UI_BASIC_RESOURCE_PATH"/org/mate/calculator/ui/buttons-basic.ui" "/org/mate/calculator/ui/buttons-basic.ui"
65#define UI_ADVANCED_RESOURCE_PATH"/org/mate/calculator/ui/buttons-advanced.ui" "/org/mate/calculator/ui/buttons-advanced.ui"
66#define UI_FINANCIAL_RESOURCE_PATH"/org/mate/calculator/ui/buttons-financial.ui" "/org/mate/calculator/ui/buttons-financial.ui"
67#define UI_PROGRAMMING_RESOURCE_PATH"/org/mate/calculator/ui/buttons-programming.ui" "/org/mate/calculator/ui/buttons-programming.ui"
68
69#define GET_WIDGET(ui, name)((((GtkWidget*) (void *) ((gtk_builder_get_object((ui), (name
)))))))
\
70 GTK_WIDGET(gtk_builder_get_object((ui), (name)))((((GtkWidget*) (void *) ((gtk_builder_get_object((ui), (name
)))))))
71
72typedef enum
73{
74 NUMBER,
75 NUMBER_BOLD,
76 OPERATOR,
77 FUNCTION,
78 MEMORY,
79 GROUP,
80 ACTION
81} ButtonClass;
82
83typedef struct {
84 const char *widget_name;
85 const char *data;
86 ButtonClass class;
87 const char *tooltip;
88} ButtonData;
89
90static ButtonData button_data[] = {
91 {"pi", "π", NUMBER,
92 /* Tooltip for the Pi button */
93 N_("Pi [Ctrl+P]")("Pi [Ctrl+P]")},
94 {"eulers_number", "e", NUMBER,
95 /* Tooltip for the Euler's Number button */
96 N_("Euler’s Number")("Euler’s Number")},
97 {"imaginary", "i", NUMBER,
98 /* Tooltip for the imaginary number button */
99 N_("Imaginary unit")("Imaginary unit")},
100 {"numeric_point", NULL((void*)0), NUMBER,
101 /* Tooltip for the numeric point button */
102 N_("Decimal point")("Decimal point")},
103 {"subscript", NULL((void*)0), NUMBER_BOLD,
104 /* Tooltip for the subscript button */
105 N_("Subscript mode [Alt]")("Subscript mode [Alt]")},
106 {"superscript", NULL((void*)0), NUMBER_BOLD,
107 /* Tooltip for the superscript button */
108 N_("Superscript mode [Ctrl]")("Superscript mode [Ctrl]")},
109 {"exponential", NULL((void*)0), NUMBER_BOLD,
110 /* Tooltip for the scientific exponent button */
111 N_("Scientific exponent [Ctrl+E]")("Scientific exponent [Ctrl+E]")},
112 {"add", "+", OPERATOR,
113 /* Tooltip for the add button */
114 N_("Add [+]")("Add [+]")},
115 {"subtract", "−", OPERATOR,
116 /* Tooltip for the subtract button */
117 N_("Subtract [-]")("Subtract [-]")},
118 {"multiply", "×", OPERATOR,
119 /* Tooltip for the multiply button */
120 N_("Multiply [*]")("Multiply [*]")},
121 {"divide", "÷", OPERATOR,
122 /* Tooltip for the divide button */
123 N_("Divide [/]")("Divide [/]")},
124 {"modulus_divide", " mod ", OPERATOR,
125 /* Tooltip for the modulus divide button */
126 N_("Modulus divide")("Modulus divide")},
127 {"function", NULL((void*)0), FUNCTION,
128 /* Tooltip for the additional functions button */
129 N_("Additional Functions")("Additional Functions")},
130 {"const", NULL((void*)0), FUNCTION,
131 /* Tooltip for the additional constant button */
132 N_("Additional constants")("Additional constants")},
133 {"x_pow_y", "^", FUNCTION,
134 /* Tooltip for the exponent button */
135 N_("Exponent [^ or **]")("Exponent [^ or **]")},
136 {"x_squared", "²", FUNCTION,
137 /* Tooltip for the square button */
138 N_("Square [Ctrl+2]")("Square [Ctrl+2]")},
139 {"percentage", "%", NUMBER,
140 /* Tooltip for the percentage button */
141 N_("Percentage [%]")("Percentage [%]")},
142 {"factorial", "!", FUNCTION,
143 /* Tooltip for the factorial button */
144 N_("Factorial [!]")("Factorial [!]")},
145 {"abs", "|", FUNCTION,
146 /* Tooltip for the absolute value button */
147 N_("Absolute value [|]")("Absolute value [|]")},
148 {"arg", "Arg ", FUNCTION,
149 /* Tooltip for the complex argument component button */
150 N_("Complex argument")("Complex argument")},
151 {"conjugate", "conj ", FUNCTION,
152 /* Tooltip for the complex conjugate button */
153 N_("Complex conjugate")("Complex conjugate")},
154 {"root", "√", FUNCTION,
155 /* Tooltip for the root button */
156 N_("Root [Ctrl+R]")("Root [Ctrl+R]")},
157 {"square_root", "√", FUNCTION,
158 /* Tooltip for the square root button */
159 N_("Square root [Ctrl+R]")("Square root [Ctrl+R]")},
160 {"logarithm", "log ", FUNCTION,
161 /* Tooltip for the logarithm button */
162 N_("Logarithm")("Logarithm")},
163 {"natural_logarithm", "ln ", FUNCTION,
164 /* Tooltip for the natural logarithm button */
165 N_("Natural Logarithm")("Natural Logarithm")},
166 {"sine", "sin ", FUNCTION,
167 /* Tooltip for the sine button */
168 N_("Sine")("Sine")},
169 {"cosine", "cos ", FUNCTION,
170 /* Tooltip for the cosine button */
171 N_("Cosine")("Cosine")},
172 {"tangent", "tan ", FUNCTION,
173 /* Tooltip for the tangent button */
174 N_("Tangent")("Tangent")},
175 {"hyperbolic_sine", "sinh ", FUNCTION,
176 /* Tooltip for the hyperbolic sine button */
177 N_("Hyperbolic Sine")("Hyperbolic Sine")},
178 {"hyperbolic_cosine", "cosh ", FUNCTION,
179 /* Tooltip for the hyperbolic cosine button */
180 N_("Hyperbolic Cosine")("Hyperbolic Cosine")},
181 {"hyperbolic_tangent", "tanh ", FUNCTION,
182 /* Tooltip for the hyperbolic tangent button */
183 N_("Hyperbolic Tangent")("Hyperbolic Tangent")},
184 {"inverse_sine", "asin ", FUNCTION,
185 /* Tooltip for the inverse sine button */
186 N_("Inverse Sine")("Inverse Sine")},
187 {"inverse_cosine", "acos ", FUNCTION,
188 /* Tooltip for the inverse cosine button */
189 N_("Inverse Cosine")("Inverse Cosine")},
190 {"inverse_tangent", "atan ", FUNCTION,
191 /* Tooltip for the inverse tangent button */
192 N_("Inverse Tangent")("Inverse Tangent")},
193 {"inverse", "⁻¹", FUNCTION,
194 /* Tooltip for the inverse button */
195 N_("Inverse [Ctrl+I]")("Inverse [Ctrl+I]")},
196 {"and", "∧", OPERATOR,
197 /* Tooltip for the boolean AND button */
198 N_("Boolean AND")("Boolean AND")},
199 {"or", "∨", OPERATOR,
200 /* Tooltip for the boolean OR button */
201 N_("Boolean OR")("Boolean OR")},
202 {"xor", "⊻", OPERATOR,
203 /* Tooltip for the exclusive OR button */
204 N_("Boolean Exclusive OR")("Boolean Exclusive OR")},
205 {"not", "¬", FUNCTION,
206 /* Tooltip for the boolean NOT button */
207 N_("Boolean NOT")("Boolean NOT")},
208 {"integer_portion", "int ", FUNCTION,
209 /* Tooltip for the integer component button */
210 N_("Integer Component")("Integer Component")},
211 {"fractional_portion", "frac ", FUNCTION,
212 /* Tooltip for the fractional component button */
213 N_("Fractional Component")("Fractional Component")},
214 {"real_portion", "Re ", FUNCTION,
215 /* Tooltip for the real component button */
216 N_("Real Component")("Real Component")},
217 {"imaginary_portion", "Im ", FUNCTION,
218 /* Tooltip for the imaginary component button */
219 N_("Imaginary Component")("Imaginary Component")},
220 {"ones_complement", "ones ", FUNCTION,
221 /* Tooltip for the ones' complement button */
222 N_("Ones' Complement")("Ones' Complement")},
223 {"twos_complement", "twos ", FUNCTION,
224 /* Tooltip for the two's complement button */
225 N_("Two's Complement")("Two's Complement")},
226 {"start_group", "(", GROUP,
227 /* Tooltip for the start group button */
228 N_("Start Group [(]")("Start Group [(]")},
229 {"end_group", ")", GROUP,
230 /* Tooltip for the end group button */
231 N_("End Group [)]")("End Group [)]")},
232 {"memory", NULL((void*)0), MEMORY,
233 /* Tooltip for the memory button */
234 N_("Memory")("Memory")},
235 {"character", NULL((void*)0), MEMORY,
236 /* Tooltip for the insert character code button */
237 N_("Insert Character Code")("Insert Character Code")},
238 {"result", NULL((void*)0), ACTION,
239 /* Tooltip for the solve button */
240 N_("Calculate Result")("Calculate Result")},
241 {"factor", NULL((void*)0), ACTION,
242 /* Tooltip for the factor button */
243 N_("Factorize [Ctrl+F]")("Factorize [Ctrl+F]")},
244 {"clear", NULL((void*)0), GROUP,
245 /* Tooltip for the clear button */
246 N_("Clear Display [Escape]")("Clear Display [Escape]")},
247 {"undo", NULL((void*)0), GROUP,
248 /* Tooltip for the undo button */
249 N_("Undo [Ctrl+Z]")("Undo [Ctrl+Z]")},
250 {"shift_left", NULL((void*)0), ACTION,
251 /* Tooltip for the shift left button */
252 N_("Shift Left [<<]")("Shift Left [<<]")},
253 {"shift_right", NULL((void*)0), ACTION,
254 /* Tooltip for the shift right button */
255 N_("Shift Right [>>]")("Shift Right [>>]")},
256 {"finc_compounding_term", NULL((void*)0), FUNCTION,
257 /* Tooltip for the compounding term button */
258 N_("Compounding Term")("Compounding Term")},
259 {"finc_double_declining_depreciation", NULL((void*)0), FUNCTION,
260 /* Tooltip for the double declining depreciation button */
261 N_("Double Declining Depreciation")("Double Declining Depreciation")},
262 {"finc_future_value", NULL((void*)0), FUNCTION,
263 /* Tooltip for the future value button */
264 N_("Future Value")("Future Value")},
265 {"finc_term", NULL((void*)0), FUNCTION,
266 /* Tooltip for the financial term button */
267 N_("Financial Term")("Financial Term")},
268 {"finc_sum_of_the_years_digits_depreciation", NULL((void*)0), FUNCTION,
269 /* Tooltip for the sum of the years digits depreciation button */
270 N_("Sum of the Years Digits Depreciation")("Sum of the Years Digits Depreciation")},
271 {"finc_straight_line_depreciation", NULL((void*)0), FUNCTION,
272 /* Tooltip for the straight line depreciation button */
273 N_("Straight Line Depreciation")("Straight Line Depreciation")},
274 {"finc_periodic_interest_rate", NULL((void*)0), FUNCTION,
275 /* Tooltip for the periodic interest rate button */
276 N_("Periodic Interest Rate")("Periodic Interest Rate")},
277 {"finc_present_value", NULL((void*)0), FUNCTION,
278 /* Tooltip for the present value button */
279 N_("Present Value")("Present Value")},
280 {"finc_periodic_payment", NULL((void*)0), FUNCTION,
281 /* Tooltip for the periodic payment button */
282 N_("Periodic Payment")("Periodic Payment")},
283 {"finc_gross_profit_margin", NULL((void*)0), FUNCTION,
284 /* Tooltip for the gross profit margin button */
285 N_("Gross Profit Margin")("Gross Profit Margin")},
286 {NULL((void*)0), NULL((void*)0), 0, NULL((void*)0)}
287};
288
289/* The names of each field in the dialogs for the financial functions */
290static char *finc_dialog_fields[][5] = {
291 {"ctrm_pint", "ctrm_fv", "ctrm_pv", NULL((void*)0), NULL((void*)0)},
292 {"ddb_cost", "ddb_life", "ddb_period", NULL((void*)0), NULL((void*)0)},
293 {"fv_pmt", "fv_pint", "fv_n", NULL((void*)0), NULL((void*)0)},
294 {"gpm_cost", "gpm_margin", NULL((void*)0), NULL((void*)0), NULL((void*)0)},
295 {"pmt_prin", "pmt_pint", "pmt_n", NULL((void*)0), NULL((void*)0)},
296 {"pv_pmt", "pv_pint", "pv_n", NULL((void*)0), NULL((void*)0)},
297 {"rate_fv", "rate_pv", "rate_n", NULL((void*)0), NULL((void*)0)},
298 {"sln_cost", "sln_salvage", "sln_life", NULL((void*)0), NULL((void*)0)},
299 {"syd_cost", "syd_salvage", "syd_life", "syd_period", NULL((void*)0)},
300 {"term_pmt", "term_fv", "term_pint", NULL((void*)0), NULL((void*)0)},
301 {NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)}
302};
303
304MathButtons *
305math_buttons_new(MathEquation *equation)
306{
307 return g_object_new(math_buttons_get_type(), "equation", equation, NULL((void*)0));
308}
309
310static void
311set_data(GtkBuilder *ui, const gchar *object_name, const gchar *name, const char *value)
312{
313 GObject *object;
314 object = gtk_builder_get_object(ui, object_name);
315 if (object)
316 g_object_set_data(object, name, GINT_TO_POINTER(value)((gpointer) (glong) (value)));
317}
318
319static void
320set_int_data(GtkBuilder *ui, const gchar *object_name, const gchar *name, gint value)
321{
322 GObject *object;
323 object = gtk_builder_get_object(ui, object_name);
324 if (object)
325 g_object_set_data(object, name, GINT_TO_POINTER(value)((gpointer) (glong) (value)));
326}
327
328static void
329load_finc_dialogs(MathButtons *buttons)
330{
331 int i, j;
332
333 set_int_data(buttons->priv->financial_ui, "ctrm_dialog", "finc_dialog", FINC_CTRM_DIALOG);
334 set_int_data(buttons->priv->financial_ui, "ddb_dialog", "finc_dialog", FINC_DDB_DIALOG);
335 set_int_data(buttons->priv->financial_ui, "fv_dialog", "finc_dialog", FINC_FV_DIALOG);
336 set_int_data(buttons->priv->financial_ui, "gpm_dialog", "finc_dialog", FINC_GPM_DIALOG);
337 set_int_data(buttons->priv->financial_ui, "pmt_dialog", "finc_dialog", FINC_PMT_DIALOG);
338 set_int_data(buttons->priv->financial_ui, "pv_dialog", "finc_dialog", FINC_PV_DIALOG);
339 set_int_data(buttons->priv->financial_ui, "rate_dialog", "finc_dialog", FINC_RATE_DIALOG);
340 set_int_data(buttons->priv->financial_ui, "sln_dialog", "finc_dialog", FINC_SLN_DIALOG);
341 set_int_data(buttons->priv->financial_ui, "syd_dialog", "finc_dialog", FINC_SYD_DIALOG);
342 set_int_data(buttons->priv->financial_ui, "term_dialog", "finc_dialog", FINC_TERM_DIALOG);
343
344 for (i = 0; finc_dialog_fields[i][0] != NULL((void*)0); i++) {
345 for (j = 0; finc_dialog_fields[i][j]; j++) {
346 GObject *o;
347 o = gtk_builder_get_object (buttons->priv->financial_ui, finc_dialog_fields[i][j]);
348 g_object_set_data(o, "finc_field", GINT_TO_POINTER(j)((gpointer) (glong) (j)));
349 g_object_set_data(o, "finc_dialog", GINT_TO_POINTER(i)((gpointer) (glong) (i)));
350 }
351 }
352}
353
354static void
355update_bit_panel(MathButtons *buttons)
356{
357 MPNumber x;
358 gboolean enabled;
359 guint64 bits;
360 int i;
361 GString *label;
362 gint base;
363
364 if (!buttons->priv->bit_panel)
365 return;
366
367 x = mp_new();
368 enabled = math_equation_get_number(buttons->priv->equation, &x);
369
370 if (enabled) {
371 MPNumber max = mp_new();
372 MPNumber fraction = mp_new();
373
374 mp_set_from_unsigned_integer(G_MAXUINT64(0xffffffffffffffffUL), &max);
375 mp_fractional_part(&x, &fraction);
376 if (mp_is_negative(&x) || mp_is_greater_than(&x, &max) || !mp_is_zero(&fraction))
377 enabled = FALSE(0);
378 else
379 bits = mp_to_unsigned_integer(&x);
380 mp_clear(&max);
381 mp_clear(&fraction);
382 }
383
384 gtk_widget_set_sensitive(buttons->priv->bit_panel, enabled);
385 gtk_widget_set_sensitive(buttons->priv->base_label, enabled);
386
387 if (!enabled)
388 {
389 mp_clear(&x);
390 return;
391 }
392
393 for (i = 0; i < MAXBITS64; i++) {
394 const gchar *bin_label;
395
396 if (bits & (1LLU << (MAXBITS64-i-1)))
397 bin_label = " 1";
398 else
399 bin_label = " 0";
400 gtk_label_set_text(GTK_LABEL(buttons->priv->bit_labels[i])((((GtkLabel*) (void *) ((buttons->priv->bit_labels[i])
))))
, bin_label);
401 }
402
403 base = math_equation_get_base(buttons->priv->equation);
404 label = g_string_new("");
405 if (base != 8) {
406 if (label->len != 0)
407 g_string_append(label, " = ")(__builtin_constant_p (" = ") ? __extension__ ({ const char *
const __val = (" = "); g_string_append_len_inline (label, __val
, (__builtin_expect (__extension__ ({ int _g_boolean_var_19; if
(__val != ((void*)0)) _g_boolean_var_19 = 1; else _g_boolean_var_19
= 0; _g_boolean_var_19; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
label, " = ", (gssize) -1))
;
408 g_string_append_printf(label, "%" G_GINT64_MODIFIER"l" "o", bits);
409 g_string_append(label, "₈")(__builtin_constant_p ("₈") ? __extension__ ({ const char *
const __val = ("₈"); g_string_append_len_inline (label, __val
, (__builtin_expect (__extension__ ({ int _g_boolean_var_20; if
(__val != ((void*)0)) _g_boolean_var_20 = 1; else _g_boolean_var_20
= 0; _g_boolean_var_20; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
label, "₈", (gssize) -1))
;
410 }
411 if (base != 10) {
412 if (label->len != 0)
413 g_string_append(label, " = ")(__builtin_constant_p (" = ") ? __extension__ ({ const char *
const __val = (" = "); g_string_append_len_inline (label, __val
, (__builtin_expect (__extension__ ({ int _g_boolean_var_21; if
(__val != ((void*)0)) _g_boolean_var_21 = 1; else _g_boolean_var_21
= 0; _g_boolean_var_21; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
label, " = ", (gssize) -1))
;
414 g_string_append_printf(label, "%" G_GINT64_MODIFIER"l" "u", bits);
415 g_string_append(label, "₁₀")(__builtin_constant_p ("₁₀") ? __extension__ ({ const char
* const __val = ("₁₀"); g_string_append_len_inline (label
, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_22
; if (__val != ((void*)0)) _g_boolean_var_22 = 1; else _g_boolean_var_22
= 0; _g_boolean_var_22; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
label, "₁₀", (gssize) -1))
;
416 }
417 if (base != 16) {
418 if (label->len != 0)
419 g_string_append(label, " = ")(__builtin_constant_p (" = ") ? __extension__ ({ const char *
const __val = (" = "); g_string_append_len_inline (label, __val
, (__builtin_expect (__extension__ ({ int _g_boolean_var_23; if
(__val != ((void*)0)) _g_boolean_var_23 = 1; else _g_boolean_var_23
= 0; _g_boolean_var_23; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
label, " = ", (gssize) -1))
;
420 g_string_append_printf(label, "%" G_GINT64_MODIFIER"l" "X", bits);
421 g_string_append(label, "₁₆")(__builtin_constant_p ("₁₆") ? __extension__ ({ const char
* const __val = ("₁₆"); g_string_append_len_inline (label
, __val, (__builtin_expect (__extension__ ({ int _g_boolean_var_24
; if (__val != ((void*)0)) _g_boolean_var_24 = 1; else _g_boolean_var_24
= 0; _g_boolean_var_24; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
label, "₁₆", (gssize) -1))
;
422 }
423
424 gtk_label_set_text(GTK_LABEL(buttons->priv->base_label)((((GtkLabel*) (void *) ((buttons->priv->base_label))))
)
, label->str);
425 g_string_free(label, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(label), ((!(0)))) : g_string_free_and_steal (label)) : (g_string_free
) ((label), ((!(0)))))
;
426 mp_clear(&x);
427}
428
429static void
430display_changed_cb(MathEquation *equation, GParamSpec *spec, MathButtons *buttons)
431{
432 update_bit_panel(buttons);
433}
434
435static void
436base_combobox_changed_cb(GtkWidget *combo, MathButtons *buttons)
437{
438 gint value;
439 GtkTreeModel *model;
440 GtkTreeIter iter;
441
442 model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))));
443 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))), &iter);
444 gtk_tree_model_get(model, &iter, 1, &value, -1);
445
446 math_buttons_set_programming_base(buttons, value);
447}
448
449static void
450base_changed_cb(MathEquation *equation, GParamSpec *spec, MathButtons *buttons)
451{
452 GtkTreeModel *model;
453 GtkTreeIter iter;
454 gboolean valid;
455
456 if (buttons->priv->mode != PROGRAMMING)
457 return;
458
459 model = gtk_combo_box_get_model(GTK_COMBO_BOX(buttons->priv->base_combo)((((GtkComboBox*) (void *) ((buttons->priv->base_combo)
))))
);
460 valid = gtk_tree_model_get_iter_first(model, &iter);
461 buttons->priv->programming_base = math_equation_get_base(buttons->priv->equation);
462
463 while (valid) {
464 gint v;
465
466 gtk_tree_model_get(model, &iter, 1, &v, -1);
467 if (v == buttons->priv->programming_base)
468 break;
469 valid = gtk_tree_model_iter_next(model, &iter);
470 }
471 if (!valid)
472 valid = gtk_tree_model_get_iter_first(model, &iter);
Value stored to 'valid' is never read
473
474 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(buttons->priv->base_combo)((((GtkComboBox*) (void *) ((buttons->priv->base_combo)
))))
, &iter);
475}
476
477static GtkWidget *
478load_mode(MathButtons *buttons, ButtonMode mode)
479{
480 GtkBuilder *builder, **builder_ptr;
481 gint i;
482 gchar *name;
483 const gchar *path;
484 static gchar *objects[] = { "button_panel", "character_code_dialog", "currency_dialog",
485 "ctrm_dialog", "ddb_dialog", "fv_dialog", "gpm_dialog",
486 "pmt_dialog", "pv_dialog", "rate_dialog", "sln_dialog",
487 "syd_dialog", "term_dialog", "adjustment1", "adjustment2", NULL((void*)0) };
488 GtkWidget *widget, **panel;
489 GError *error = NULL((void*)0);
490
491 switch (mode) {
492 default:
493 case BASIC:
494 builder_ptr = &buttons->priv->basic_ui;
495 path = UI_BASIC_RESOURCE_PATH"/org/mate/calculator/ui/buttons-basic.ui";
496 panel = &buttons->priv->bas_panel;
497 break;
498 case ADVANCED:
499 builder_ptr = &buttons->priv->advanced_ui;
500 path = UI_ADVANCED_RESOURCE_PATH"/org/mate/calculator/ui/buttons-advanced.ui";
501 panel = &buttons->priv->adv_panel;
502 break;
503 case FINANCIAL:
504 builder_ptr = &buttons->priv->financial_ui;
505 path = UI_FINANCIAL_RESOURCE_PATH"/org/mate/calculator/ui/buttons-financial.ui";
506 panel = &buttons->priv->fin_panel;
507 break;
508 case PROGRAMMING:
509 builder_ptr = &buttons->priv->programming_ui;
510 path = UI_PROGRAMMING_RESOURCE_PATH"/org/mate/calculator/ui/buttons-programming.ui";
511 panel = &buttons->priv->prog_panel;
512 break;
513 }
514
515 if (*panel)
516 goto out;
517
518 builder = *builder_ptr = gtk_builder_new();
519 // FIXME: Show dialog if failed to load
520 gtk_builder_add_objects_from_resource(builder, path, objects, &error);
521 if (error) {
522 g_warning("Error loading button UI: %s", error->message);
523 g_clear_error(&error);
524 }
525 *panel = GET_WIDGET(builder, "button_panel")((((GtkWidget*) (void *) ((gtk_builder_get_object((builder), (
"button_panel")))))))
;
526 gtk_box_pack_end(GTK_BOX(buttons)((((GtkBox*) (void *) ((buttons))))), *panel, TRUE(!(0)), TRUE(!(0)), 0);
527
528 /* Configure buttons */
529 for (i = 0; button_data[i].widget_name != NULL((void*)0); i++) {
530 GObject *object;
531 GtkWidget *button;
532
533 name = g_strdup_printf("calc_%s_button", button_data[i].widget_name);
534 object = gtk_builder_get_object(*builder_ptr, name);
535 g_free(name);
536
537 if (!object)
538 continue;
539 button = GTK_WIDGET(object)((((GtkWidget*) (void *) ((object)))));
540 if (button_data[i].data)
541 g_object_set_data(object, "calc_text", (gpointer) button_data[i].data);
542
543 if (button_data[i].tooltip)
544 gtk_widget_set_tooltip_text(button, _(button_data[i].tooltip)dcgettext (((void*)0), button_data[i].tooltip, 5));
545 }
546
547 /* Set special button data */
548 for (i = 0; i < 16; i++) {
549 GtkWidget *button;
550
551 name = g_strdup_printf("calc_%d_button", i);
552 button = GET_WIDGET(builder, name)((((GtkWidget*) (void *) ((gtk_builder_get_object((builder), (
name)))))))
;
553 if (button) {
554 gchar buffer[7];
555 gint len;
556
557 g_object_set_data(G_OBJECT(button)((((GObject*) (void *) ((button))))), "calc_digit", GINT_TO_POINTER(i)((gpointer) (glong) (i)));
558 len = g_unichar_to_utf8(math_equation_get_digit_text(buttons->priv->equation, i), buffer);
559 buffer[len] = '\0';
560 gtk_button_set_label(GTK_BUTTON(button)((((GtkButton*) (void *) ((button))))), buffer);
561 }
562 g_free(name);
563 }
564 widget = GET_WIDGET(builder, "calc_numeric_point_button")((((GtkWidget*) (void *) ((gtk_builder_get_object((builder), (
"calc_numeric_point_button")))))))
;
565 if (widget) {
566 MpSerializer *serializer = math_equation_get_serializer(buttons->priv->equation);
567 gchar buffer[7];
568 gint len;
569 len = g_unichar_to_utf8(mp_serializer_get_radix(serializer), buffer);
570 buffer[len] = '\0';
571 gtk_button_set_label(GTK_BUTTON(widget)((((GtkButton*) (void *) ((widget))))), buffer);
572 }
573
574 widget = GET_WIDGET(builder, "calc_superscript_button")((((GtkWidget*) (void *) ((gtk_builder_get_object((builder), (
"calc_superscript_button")))))))
;
575 if (widget) {
576 buttons->priv->superscript_toggles = g_list_append(buttons->priv->superscript_toggles, widget);
577 if (math_equation_get_number_mode(buttons->priv->equation) == SUPERSCRIPT)
578 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget)((((GtkToggleButton*) (void *) ((widget))))), TRUE(!(0)));
579 }
580 widget = GET_WIDGET(builder, "calc_subscript_button")((((GtkWidget*) (void *) ((gtk_builder_get_object((builder), (
"calc_subscript_button")))))))
;
581 if (widget) {
582 buttons->priv->subscript_toggles = g_list_append(buttons->priv->subscript_toggles, widget);
583 if (math_equation_get_number_mode(buttons->priv->equation) == SUBSCRIPT)
584 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget)((((GtkToggleButton*) (void *) ((widget))))), TRUE(!(0)));
585 }
586
587 /* put the icon name "process-stop" in the buttons
588 button1, button3, button5, button7, button9,
589 button11, button13, button15, button17, button19
590 taken from buttons-financial.ui */
591 for (i = 1; i < 20; i++) {
592 if (i % 2) {
593 widget = GET_WIDGET (builder, g_strdup_printf ("button%d",i))((((GtkWidget*) (void *) ((gtk_builder_get_object((builder), (
g_strdup_printf ("button%d",i))))))))
;
594 if (GTK_IS_BUTTON(widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(widget)); GType __t = ((gtk_button_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
595 gtk_button_set_image (GTK_BUTTON (widget)((((GtkButton*) (void *) ((widget))))),
596 gtk_image_new_from_icon_name ("process-stop", GTK_ICON_SIZE_BUTTON));
597 }
598 }
599
600 if (mode == PROGRAMMING) {
601 GtkListStore *model;
602 GtkTreeIter iter;
603 GtkCellRenderer *renderer;
604
605 buttons->priv->base_label = GET_WIDGET(builder, "base_label")((((GtkWidget*) (void *) ((gtk_builder_get_object((builder), (
"base_label")))))))
;
606 buttons->priv->character_code_dialog = GET_WIDGET(builder, "character_code_dialog")((((GtkWidget*) (void *) ((gtk_builder_get_object((builder), (
"character_code_dialog")))))))
;
607 buttons->priv->character_code_entry = GET_WIDGET(builder, "character_code_entry")((((GtkWidget*) (void *) ((gtk_builder_get_object((builder), (
"character_code_entry")))))))
;
608
609 buttons->priv->bit_panel = GET_WIDGET(builder, "bit_table")((((GtkWidget*) (void *) ((gtk_builder_get_object((builder), (
"bit_table")))))))
;
610 for (i = 0; i < MAXBITS64; i++) {
611 name = g_strdup_printf("bit_label_%d", i);
612 buttons->priv->bit_labels[i] = GET_WIDGET(builder, name)((((GtkWidget*) (void *) ((gtk_builder_get_object((builder), (
name)))))))
;
613 g_free(name);
614 name = g_strdup_printf("bit_eventbox_%d", i);
615 set_int_data(builder, name, "bit_index", i);
616 }
617
618 buttons->priv->base_combo = GET_WIDGET(builder, "base_combo")((((GtkWidget*) (void *) ((gtk_builder_get_object((builder), (
"base_combo")))))))
;
619 model = gtk_list_store_new(2, G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_INT((GType) ((6) << (2))), G_TYPE_INT((GType) ((6) << (2))));
620 gtk_combo_box_set_model(GTK_COMBO_BOX(buttons->priv->base_combo)((((GtkComboBox*) (void *) ((buttons->priv->base_combo)
))))
, GTK_TREE_MODEL(model)((((GtkTreeModel*) (void *) ((model))))));
621 gtk_list_store_append(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter);
622 gtk_list_store_set(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter, 0,
623 /* Number display mode combo: Binary, e.g. 10011010010₂ */
624 _("Binary")dcgettext (((void*)0), "Binary", 5), 1, 2, -1);
625 gtk_list_store_append(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter);
626 gtk_list_store_set(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter, 0,
627 /* Number display mode combo: Octal, e.g. 2322₈ */
628 _("Octal")dcgettext (((void*)0), "Octal", 5), 1, 8, -1);
629 gtk_list_store_append(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter);
630 gtk_list_store_set(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter, 0,
631 /* Number display mode combo: Decimal, e.g. 1234 */
632 _("Decimal")dcgettext (((void*)0), "Decimal", 5), 1, 10, -1);
633 gtk_list_store_append(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter);
634 gtk_list_store_set(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter, 0,
635 /* Number display mode combo: Hexadecimal, e.g. 4D2₁₆ */
636 _("Hexadecimal")dcgettext (((void*)0), "Hexadecimal", 5), 1, 16, -1);
637 renderer = gtk_cell_renderer_text_new();
638 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(buttons->priv->base_combo)((((GtkCellLayout*) (void *) ((buttons->priv->base_combo
)))))
, renderer, TRUE(!(0)));
639 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(buttons->priv->base_combo)((((GtkCellLayout*) (void *) ((buttons->priv->base_combo
)))))
, renderer, "text", 0);
640
641 g_signal_connect(buttons->priv->base_combo, "changed", G_CALLBACK(base_combobox_changed_cb), buttons)g_signal_connect_data ((buttons->priv->base_combo), ("changed"
), (((GCallback) (base_combobox_changed_cb))), (buttons), ((void
*)0), (GConnectFlags) 0)
;
642 g_signal_connect(buttons->priv->equation, "notify::base", G_CALLBACK(base_changed_cb), buttons)g_signal_connect_data ((buttons->priv->equation), ("notify::base"
), (((GCallback) (base_changed_cb))), (buttons), ((void*)0), (
GConnectFlags) 0)
;
643 base_changed_cb(buttons->priv->equation, NULL((void*)0), buttons);
644 }
645
646 /* Setup financial functions */
647 if (mode == FINANCIAL) {
648 load_finc_dialogs(buttons);
649
650 set_data(builder, "calc_finc_compounding_term_button", "finc_dialog", "ctrm_dialog");
651 set_data(builder, "calc_finc_double_declining_depreciation_button", "finc_dialog", "ddb_dialog");
652 set_data(builder, "calc_finc_future_value_button", "finc_dialog", "fv_dialog");
653 set_data(builder, "calc_finc_gross_profit_margin_button", "finc_dialog", "gpm_dialog");
654 set_data(builder, "calc_finc_periodic_payment_button", "finc_dialog", "pmt_dialog");
655 set_data(builder, "calc_finc_present_value_button", "finc_dialog", "pv_dialog");
656 set_data(builder, "calc_finc_periodic_interest_rate_button", "finc_dialog", "rate_dialog");
657 set_data(builder, "calc_finc_straight_line_depreciation_button", "finc_dialog", "sln_dialog");
658 set_data(builder, "calc_finc_sum_of_the_years_digits_depreciation_button", "finc_dialog", "syd_dialog");
659 set_data(builder, "calc_finc_term_button", "finc_dialog", "term_dialog");
660 }
661
662 gtk_builder_connect_signals(builder, buttons);
663
664 display_changed_cb(buttons->priv->equation, NULL((void*)0), buttons);
665
666out:
667 return *panel;
668}
669
670static void
671converter_changed_cb(MathConverter *converter, MathButtons *buttons)
672{
673 Unit *from_unit, *to_unit;
674
675 math_converter_get_conversion(converter, &from_unit, &to_unit);
676 if (buttons->priv->mode == FINANCIAL) {
677 math_equation_set_source_currency(buttons->priv->equation, unit_get_name(from_unit));
678 math_equation_set_target_currency(buttons->priv->equation, unit_get_name(to_unit));
679 }
680 else {
681 math_equation_set_source_units(buttons->priv->equation, unit_get_name(from_unit));
682 math_equation_set_target_units(buttons->priv->equation, unit_get_name(to_unit));
683 }
684
685 g_object_unref(from_unit);
686 g_object_unref(to_unit);
687}
688
689static void
690load_buttons(MathButtons *buttons)
691{
692 GtkWidget *panel;
693
694 if (!gtk_widget_get_visible(GTK_WIDGET(buttons)((((GtkWidget*) (void *) ((buttons)))))))
695 return;
696
697 if (!buttons->priv->converter) {
698 buttons->priv->converter = math_converter_new(buttons->priv->equation);
699 g_signal_connect(buttons->priv->converter, "changed", G_CALLBACK(converter_changed_cb), buttons)g_signal_connect_data ((buttons->priv->converter), ("changed"
), (((GCallback) (converter_changed_cb))), (buttons), ((void*
)0), (GConnectFlags) 0)
;
700 gtk_box_pack_start(GTK_BOX(buttons)((((GtkBox*) (void *) ((buttons))))), GTK_WIDGET(buttons->priv->converter)((((GtkWidget*) (void *) ((buttons->priv->converter))))
)
, FALSE(0), TRUE(!(0)), 0);
701 }
702
703 panel = load_mode(buttons, buttons->priv->mode);
704 if (buttons->priv->active_panel == panel)
705 return;
706
707 /* Hide old buttons */
708 if (buttons->priv->active_panel)
709 gtk_widget_hide(buttons->priv->active_panel);
710
711 /* Load and display new buttons */
712 buttons->priv->active_panel = panel;
713 if (panel)
714 gtk_widget_show(panel);
715}
716
717void
718math_buttons_set_mode(MathButtons *buttons, ButtonMode mode)
719{
720 g_return_if_fail(buttons != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_25
; if (buttons != ((void*)0)) _g_boolean_var_25 = 1; else _g_boolean_var_25
= 0; _g_boolean_var_25; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "buttons != NULL"
); return; } } while (0)
;
721
722 if (buttons->priv->mode == mode)
723 return;
724
725 buttons->priv->mode = mode;
726
727 if (mode == PROGRAMMING)
728 math_equation_set_base(buttons->priv->equation, buttons->priv->programming_base);
729 else
730 math_equation_set_base(buttons->priv->equation, 10);
731
732 load_buttons(buttons);
733
734 gtk_widget_set_visible(GTK_WIDGET(buttons->priv->converter)((((GtkWidget*) (void *) ((buttons->priv->converter))))
)
, mode == ADVANCED || mode == FINANCIAL);
735 if (mode == ADVANCED) {
736 math_converter_set_category(buttons->priv->converter, NULL((void*)0));
737 math_converter_set_conversion(buttons->priv->converter,
738 math_equation_get_source_units(buttons->priv->equation),
739 math_equation_get_target_units(buttons->priv->equation));
740 }
741 else if (mode == FINANCIAL) {
742 math_converter_set_category(buttons->priv->converter, "currency");
743 math_converter_set_conversion(buttons->priv->converter,
744 math_equation_get_source_currency(buttons->priv->equation),
745 math_equation_get_target_currency(buttons->priv->equation));
746 }
747
748 g_object_notify(G_OBJECT(buttons)((((GObject*) (void *) ((buttons))))), "mode");
749}
750
751ButtonMode
752math_buttons_get_mode(MathButtons *buttons)
753{
754 return buttons->priv->mode;
755}
756
757void
758math_buttons_set_programming_base(MathButtons *buttons, gint base)
759{
760 g_return_if_fail(buttons != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_26
; if (buttons != ((void*)0)) _g_boolean_var_26 = 1; else _g_boolean_var_26
= 0; _g_boolean_var_26; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "buttons != NULL"
); return; } } while (0)
;
761
762 if (base == buttons->priv->programming_base)
763 return;
764
765 buttons->priv->programming_base = base;
766
767 g_settings_set_int(g_settings_var, "base", math_buttons_get_programming_base(buttons));
768
769 if (buttons->priv->mode == PROGRAMMING)
770 math_equation_set_base(buttons->priv->equation, base);
771}
772
773gint
774math_buttons_get_programming_base(MathButtons *buttons)
775{
776 g_return_val_if_fail(buttons != NULL, 10)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_27
; if (buttons != ((void*)0)) _g_boolean_var_27 = 1; else _g_boolean_var_27
= 0; _g_boolean_var_27; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "buttons != NULL"
); return (10); } } while (0)
;
777 return buttons->priv->programming_base;
778}
779
780void exponent_cb(GtkWidget *widget, MathButtons *buttons);
781G_MODULE_EXPORT__attribute__((visibility("default")))
782void
783exponent_cb(GtkWidget *widget, MathButtons *buttons)
784{
785 math_equation_insert_exponent(buttons->priv->equation);
786}
787
788void subtract_cb(GtkWidget *widget, MathButtons *buttons);
789G_MODULE_EXPORT__attribute__((visibility("default")))
790void
791subtract_cb(GtkWidget *widget, MathButtons *buttons)
792{
793 math_equation_insert_subtract(buttons->priv->equation);
794}
795
796void button_cb(GtkWidget *widget, MathButtons *buttons);
797G_MODULE_EXPORT__attribute__((visibility("default")))
798void
799button_cb(GtkWidget *widget, MathButtons *buttons)
800{
801 math_equation_insert(buttons->priv->equation, g_object_get_data(G_OBJECT(widget)((((GObject*) (void *) ((widget))))), "calc_text"));
802}
803
804void solve_cb(GtkWidget *widget, MathButtons *buttons);
805G_MODULE_EXPORT__attribute__((visibility("default")))
806void
807solve_cb(GtkWidget *widget, MathButtons *buttons)
808{
809 math_equation_solve(buttons->priv->equation);
810}
811
812void clear_cb(GtkWidget *widget, MathButtons *buttons);
813G_MODULE_EXPORT__attribute__((visibility("default")))
814void
815clear_cb(GtkWidget *widget, MathButtons *buttons)
816{
817 math_equation_clear(buttons->priv->equation);
818}
819
820void delete_cb(GtkWidget *widget, MathButtons *buttons);
821G_MODULE_EXPORT__attribute__((visibility("default")))
822void
823delete_cb(GtkWidget *widget, MathButtons *buttons)
824{
825 math_equation_delete(buttons->priv->equation);
826}
827
828void undo_cb(GtkWidget *widget, MathButtons *buttons);
829G_MODULE_EXPORT__attribute__((visibility("default")))
830void
831undo_cb(GtkWidget *widget, MathButtons *buttons)
832{
833 math_equation_undo(buttons->priv->equation);
834}
835
836static void
837shift_cb(GtkWidget *widget, MathButtons *buttons)
838{
839 math_equation_shift(buttons->priv->equation, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "shiftcount"))((gint) (glong) (g_object_get_data(((((GObject*) (void *) ((widget
))))), "shiftcount")))
);
840}
841
842static void
843popup_button_menu(GtkWidget *widget, GtkMenu *menu)
844{
845 gtk_menu_popup_at_widget (menu,
846 widget,
847 GDK_GRAVITY_SOUTH_WEST,
848 GDK_GRAVITY_NORTH_WEST,
849 NULL((void*)0));
850}
851
852void memory_cb(GtkWidget *widget, MathButtons *buttons);
853G_MODULE_EXPORT__attribute__((visibility("default")))
854void
855memory_cb(GtkWidget *widget, MathButtons *buttons)
856{
857 MathVariablePopup *popup;
858 GtkAllocation allocation;
859 gint x, y;
860
861 popup = math_variable_popup_new(buttons->priv->equation);
862 gtk_window_set_transient_for(GTK_WINDOW(popup)((((GtkWindow*) (void *) ((popup))))), GTK_WINDOW(gtk_widget_get_toplevel(widget))((((GtkWindow*) (void *) ((gtk_widget_get_toplevel(widget))))
))
);
863
864 gtk_widget_get_allocation(widget, &allocation);
865 gdk_window_get_root_coords(gtk_widget_get_window(widget), allocation.x, allocation.y, &x, &y);
866 gtk_window_move(GTK_WINDOW(popup)((((GtkWindow*) (void *) ((popup))))), x, y);
867 gtk_widget_show(GTK_WIDGET(popup)((((GtkWidget*) (void *) ((popup))))));
868}
869
870void shift_left_cb(GtkWidget *widget, MathButtons *buttons);
871G_MODULE_EXPORT__attribute__((visibility("default")))
872void
873shift_left_cb(GtkWidget *widget, MathButtons *buttons)
874{
875 if (!buttons->priv->shift_left_menu) {
876 gint i;
877 GtkWidget *menu;
878
879 menu = buttons->priv->shift_left_menu = gtk_menu_new();
880 gtk_menu_set_reserve_toggle_size(GTK_MENU(menu)((((GtkMenu*) (void *) ((menu))))), FALSE(0));
881
882 for (i = 1; i < 16; i++) {
883 GtkWidget *item, *label;
884 gchar *text;
885
886 if (i < 10) {
887 /* Left Shift Popup: Menu item to shift left by n places (n < 10) */
888 text = g_strdup_printf(ngettext("_%d place", "_%d places", i)dcngettext (((void*)0), "_%d place", "_%d places", i, 5), i);
889 }
890 else {
891 /* Left Shift Popup: Menu item to shift left by n places (n >= 10) */
892 text = g_strdup_printf(ngettext("%d place", "%d places", i)dcngettext (((void*)0), "%d place", "%d places", i, 5), i);
893 }
894 label = gtk_label_new_with_mnemonic(text);
895
896 item = gtk_menu_item_new();
897 g_object_set_data(G_OBJECT(item)((((GObject*) (void *) ((item))))), "shiftcount", GINT_TO_POINTER(i)((gpointer) (glong) (i)));
898 gtk_container_add(GTK_CONTAINER(item)((((GtkContainer*) (void *) ((item))))), label);
899 gtk_menu_shell_append(GTK_MENU_SHELL(menu)((((GtkMenuShell*) (void *) ((menu))))), item);
900 g_signal_connect(item, "activate", G_CALLBACK(shift_cb), buttons)g_signal_connect_data ((item), ("activate"), (((GCallback) (shift_cb
))), (buttons), ((void*)0), (GConnectFlags) 0)
;
901
902 gtk_widget_show(label);
903 gtk_widget_show(item);
904 g_free(text);
905 }
906 }
907
908 popup_button_menu(widget, GTK_MENU(buttons->priv->shift_left_menu)((((GtkMenu*) (void *) ((buttons->priv->shift_left_menu
)))))
);
909}
910
911void shift_right_cb(GtkWidget *widget, MathButtons *buttons);
912G_MODULE_EXPORT__attribute__((visibility("default")))
913void
914shift_right_cb(GtkWidget *widget, MathButtons *buttons)
915{
916 if (!buttons->priv->shift_right_menu) {
917 gint i;
918 GtkWidget *menu;
919
920 menu = buttons->priv->shift_right_menu = gtk_menu_new();
921 gtk_menu_set_reserve_toggle_size(GTK_MENU(menu)((((GtkMenu*) (void *) ((menu))))), FALSE(0));
922
923 for (i = 1; i < 16; i++) {
924 GtkWidget *item, *label;
925 gchar *text;
926
927 if (i < 10) {
928 /* Right Shift Popup: Menu item to shift right by n places (n < 10) */
929 text = g_strdup_printf(ngettext("_%d place", "_%d places", i)dcngettext (((void*)0), "_%d place", "_%d places", i, 5), i);
930 }
931 else {
932 /* Right Shift Popup: Menu item to shift right by n places (n >= 10) */
933 text = g_strdup_printf(ngettext("%d place", "%d places", i)dcngettext (((void*)0), "%d place", "%d places", i, 5), i);
934 }
935 label = gtk_label_new_with_mnemonic(text);
936
937 item = gtk_menu_item_new();
938 g_object_set_data(G_OBJECT(item)((((GObject*) (void *) ((item))))), "shiftcount", GINT_TO_POINTER(-i)((gpointer) (glong) (-i)));
939 gtk_container_add(GTK_CONTAINER(item)((((GtkContainer*) (void *) ((item))))), label);
940 gtk_menu_shell_append(GTK_MENU_SHELL(menu)((((GtkMenuShell*) (void *) ((menu))))), item);
941 g_signal_connect(item, "activate", G_CALLBACK(shift_cb), buttons)g_signal_connect_data ((item), ("activate"), (((GCallback) (shift_cb
))), (buttons), ((void*)0), (GConnectFlags) 0)
;
942
943 gtk_widget_show(label);
944 gtk_widget_show(item);
945 g_free(text);
946 }
947 }
948
949 popup_button_menu(widget, GTK_MENU(buttons->priv->shift_right_menu)((((GtkMenu*) (void *) ((buttons->priv->shift_right_menu
)))))
);
950}
951
952static void
953insert_function_cb(GtkWidget *widget, MathButtons *buttons)
954{
955 math_equation_insert(buttons->priv->equation, g_object_get_data(G_OBJECT(widget)((((GObject*) (void *) ((widget))))), "function"));
956}
957
958void function_cb(GtkWidget *widget, MathButtons *buttons);
959G_MODULE_EXPORT__attribute__((visibility("default")))
960void
961function_cb(GtkWidget *widget, MathButtons *buttons)
962{
963 if (!buttons->priv->function_menu) {
964 gint i;
965 GtkWidget *menu;
966 struct
967 {
968 gchar *name, *function;
969 } functions[] =
970 {
971 { /* Tooltip for the integer component button */
972 N_("Integer Component")("Integer Component"), "int " },
973 { /* Tooltip for the fractional component button */
974 N_("Fractional Component")("Fractional Component"), "frac " },
975 { /* Tooltip for the round button */
976 N_("Round")("Round"), "round " },
977 { /* Tooltip for the floor button */
978 N_("Floor")("Floor"), "floor " },
979 { /* Tooltip for the ceiling button */
980 N_("Ceiling")("Ceiling"), "ceil " },
981 { /* Tooltip for the ceiling button */
982 N_("Sign")("Sign"), "sgn " },
983 { NULL((void*)0), NULL((void*)0) }
984 };
985
986 menu = buttons->priv->function_menu = gtk_menu_new();
987 gtk_menu_set_reserve_toggle_size(GTK_MENU(menu)((((GtkMenu*) (void *) ((menu))))), FALSE(0));
988
989 for (i = 0; functions[i].name != NULL((void*)0); i++) {
990 GtkWidget *item;
991
992 item = gtk_menu_item_new_with_label(_(functions[i].name)dcgettext (((void*)0), functions[i].name, 5));
993 g_object_set_data(G_OBJECT(item)((((GObject*) (void *) ((item))))), "function", g_strdup(functions[i].function)g_strdup_inline (functions[i].function));
994 gtk_menu_shell_append(GTK_MENU_SHELL(menu)((((GtkMenuShell*) (void *) ((menu))))), item);
995 g_signal_connect(item, "activate", G_CALLBACK(insert_function_cb), buttons)g_signal_connect_data ((item), ("activate"), (((GCallback) (insert_function_cb
))), (buttons), ((void*)0), (GConnectFlags) 0)
;
996 gtk_widget_show(item);
997 }
998 }
999
1000 popup_button_menu(widget, GTK_MENU(buttons->priv->function_menu)((((GtkMenu*) (void *) ((buttons->priv->function_menu))
)))
);
1001}
1002
1003static void
1004insert_const_cb(GtkWidget *widget, MathButtons *buttons)
1005{
1006 math_equation_insert(buttons->priv->equation, g_object_get_data(G_OBJECT(widget)((((GObject*) (void *) ((widget))))), "const"));
1007}
1008
1009void const_cb(GtkWidget *widget, MathButtons *buttons);
1010G_MODULE_EXPORT__attribute__((visibility("default")))
1011void
1012const_cb(GtkWidget *widget, MathButtons *buttons)
1013{
1014 if (!buttons->priv->const_menu) {
1015 gint i;
1016 GtkWidget *menu;
1017 struct
1018 {
1019 gchar *name, *constant, *tooltip;
1020 } constants[] =
1021 {
1022 { /* Tooltip for the c₀ component button */
1023 N_("Velocity of Light")("Velocity of Light"), "c₀", N_("299,792,458 m/s")("299,792,458 m/s") },
1024 { /* Tooltip for the μ₀ component button */
1025 N_("Magnetic constant")("Magnetic constant"), "μ₀", N_("1.2566370614×10⁻⁶ N/A²")("1.2566370614×10⁻⁶ N/A²") },
1026 { /* Tooltip for the ε₀ button */
1027 N_("Electric constant")("Electric constant"), "ε₀", N_("8.85418782×10⁻¹² s⁴A²/m³kg")("8.85418782×10⁻¹² s⁴A²/m³kg") },
1028 { /* Tooltip for the G button */
1029 N_("Newtonian constant of gravitation")("Newtonian constant of gravitation"), "G", N_("6.67408×10⁻¹¹ m³/(s²kg)")("6.67408×10⁻¹¹ m³/(s²kg)") },
1030 { /* Tooltip for the h button */
1031 N_("Planck constant")("Planck constant"), "h", N_("6.62607004×10⁻³⁴ m²kg/s")("6.62607004×10⁻³⁴ m²kg/s") },
1032 { /* Tooltip for the e button */
1033 N_("Elementary charge")("Elementary charge"), "e", N_("1.6021766208(98)×10⁻¹⁹ C")("1.6021766208(98)×10⁻¹⁹ C") },
1034 { /* Tooltip for the mₑ button */
1035 N_("Electron mass")("Electron mass"), "mₑ", N_("9.10938356×10⁻³¹ kg")("9.10938356×10⁻³¹ kg") },
1036 { /* Tooltip for the mₚ button */
1037 N_("Proton mass")("Proton mass"), "mₚ", N_("1.672621898(21)×10⁻²⁷ kg")("1.672621898(21)×10⁻²⁷ kg") },
1038 { /* Tooltip for the Nₐ button */
1039 N_("Avogadro constant")("Avogadro constant"), "Nₐ", N_("6.02214086×10²³ mol⁻¹")("6.02214086×10²³ mol⁻¹") },
1040 { NULL((void*)0), NULL((void*)0), NULL((void*)0) }
1041 };
1042
1043 menu = buttons->priv->const_menu = gtk_menu_new();
1044 gtk_menu_set_reserve_toggle_size(GTK_MENU(menu)((((GtkMenu*) (void *) ((menu))))), FALSE(0));
1045
1046 for (i = 0; constants[i].name != NULL((void*)0); i++) {
1047 GtkWidget *item;
1048
1049 item = gtk_menu_item_new_with_label(_(constants[i].name)dcgettext (((void*)0), constants[i].name, 5));
1050 gtk_widget_set_tooltip_text(item, _(constants[i].tooltip)dcgettext (((void*)0), constants[i].tooltip, 5));
1051 g_object_set_data(G_OBJECT(item)((((GObject*) (void *) ((item))))), "const", g_strdup(constants[i].constant)g_strdup_inline (constants[i].constant));
1052 gtk_menu_shell_append(GTK_MENU_SHELL(menu)((((GtkMenuShell*) (void *) ((menu))))), item);
1053 g_signal_connect(item, "activate", G_CALLBACK(insert_const_cb), buttons)g_signal_connect_data ((item), ("activate"), (((GCallback) (insert_const_cb
))), (buttons), ((void*)0), (GConnectFlags) 0)
;
1054 gtk_widget_show(item);
1055 }
1056 }
1057
1058 popup_button_menu(widget, GTK_MENU(buttons->priv->const_menu)((((GtkMenu*) (void *) ((buttons->priv->const_menu))))));
1059}
1060
1061void factorize_cb(GtkWidget *widget, MathButtons *buttons);
1062G_MODULE_EXPORT__attribute__((visibility("default")))
1063void
1064factorize_cb(GtkWidget *widget, MathButtons *buttons)
1065{
1066 math_equation_factorize(buttons->priv->equation);
1067}
1068
1069void digit_cb(GtkWidget *widget, MathButtons *buttons);
1070G_MODULE_EXPORT__attribute__((visibility("default")))
1071void
1072digit_cb(GtkWidget *widget, MathButtons *buttons)
1073{
1074 math_equation_insert_digit(buttons->priv->equation, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "calc_digit"))((gint) (glong) (g_object_get_data(((((GObject*) (void *) ((widget
))))), "calc_digit")))
);
1075}
1076
1077void numeric_point_cb(GtkWidget *widget, MathButtons *buttons);
1078G_MODULE_EXPORT__attribute__((visibility("default")))
1079void
1080numeric_point_cb(GtkWidget *widget, MathButtons *buttons)
1081{
1082 math_equation_insert_numeric_point(buttons->priv->equation);
1083}
1084
1085void finc_cb(GtkWidget *widget, MathButtons *buttons);
1086G_MODULE_EXPORT__attribute__((visibility("default")))
1087void
1088finc_cb(GtkWidget *widget, MathButtons *buttons)
1089{
1090 gchar *name;
1091
1092 name = g_object_get_data(G_OBJECT(widget)((((GObject*) (void *) ((widget))))), "finc_dialog");
1093 gtk_dialog_run(GTK_DIALOG(GET_WIDGET(buttons->priv->financial_ui, name))((((GtkDialog*) (void *) ((((((GtkWidget*) (void *) ((gtk_builder_get_object
((buttons->priv->financial_ui), (name))))))))))))
);
1094 gtk_widget_hide(GTK_WIDGET(GET_WIDGET(buttons->priv->financial_ui, name))((((GtkWidget*) (void *) ((((((GtkWidget*) (void *) ((gtk_builder_get_object
((buttons->priv->financial_ui), (name))))))))))))
);
1095}
1096
1097void insert_character_code_cb(GtkWidget *widget, MathButtons *buttons);
1098G_MODULE_EXPORT__attribute__((visibility("default")))
1099void
1100insert_character_code_cb(GtkWidget *widget, MathButtons *buttons)
1101{
1102 gtk_window_present(GTK_WINDOW(buttons->priv->character_code_dialog)((((GtkWindow*) (void *) ((buttons->priv->character_code_dialog
)))))
);
1103}
1104
1105void finc_activate_cb(GtkWidget *widget, MathButtons *buttons);
1106G_MODULE_EXPORT__attribute__((visibility("default")))
1107void
1108finc_activate_cb(GtkWidget *widget, MathButtons *buttons)
1109{
1110 gint dialog, field;
1111
1112 dialog = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "finc_dialog"))((gint) (glong) (g_object_get_data(((((GObject*) (void *) ((widget
))))), "finc_dialog")))
;
1113 field = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "finc_field"))((gint) (glong) (g_object_get_data(((((GObject*) (void *) ((widget
))))), "finc_field")))
;
1114
1115 if (finc_dialog_fields[dialog][field+1] == NULL((void*)0)) {
1116 GtkWidget *dialog_widget;
1117 dialog_widget = gtk_widget_get_toplevel(widget);
1118 if (gtk_widget_is_toplevel(dialog_widget)) {
1119 gtk_dialog_response(GTK_DIALOG(dialog_widget)((((GtkDialog*) (void *) ((dialog_widget))))),
1120 GTK_RESPONSE_OK);
1121 return;
1122 }
1123 }
1124 else {
1125 GtkWidget *next_widget;
1126 next_widget = GET_WIDGET(buttons->priv->financial_ui, finc_dialog_fields[dialog][field+1])((((GtkWidget*) (void *) ((gtk_builder_get_object((buttons->
priv->financial_ui), (finc_dialog_fields[dialog][field+1])
))))))
;
1127 gtk_widget_grab_focus(next_widget);
1128 }
1129}
1130
1131void finc_response_cb(GtkWidget *widget, gint response_id, MathButtons *buttons);
1132G_MODULE_EXPORT__attribute__((visibility("default")))
1133void
1134finc_response_cb(GtkWidget *widget, gint response_id, MathButtons *buttons)
1135{
1136 int dialog;
1137 int i;
1138 MPNumber arg[4];
1139 GtkWidget *entry;
1140
1141 if (response_id != GTK_RESPONSE_OK)
1142 return;
1143
1144 dialog = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "finc_dialog"))((gint) (glong) (g_object_get_data(((((GObject*) (void *) ((widget
))))), "finc_dialog")))
;
1145
1146 for (i = 0; i < 4; i++) {
1147 arg[i] = mp_new();
1148 if (finc_dialog_fields[dialog][i] == NULL((void*)0)) {
1149 continue;
1150 }
1151 entry = GET_WIDGET(buttons->priv->financial_ui, finc_dialog_fields[dialog][i])((((GtkWidget*) (void *) ((gtk_builder_get_object((buttons->
priv->financial_ui), (finc_dialog_fields[dialog][i])))))))
;
1152 mp_set_from_string(gtk_entry_get_text(GTK_ENTRY(entry)((((GtkEntry*) (void *) ((entry)))))), 10, &arg[i]);
1153 gtk_entry_set_text(GTK_ENTRY(entry)((((GtkEntry*) (void *) ((entry))))), "0");
1154 }
1155 gtk_widget_grab_focus(GET_WIDGET(buttons->priv->financial_ui, finc_dialog_fields[dialog][0])((((GtkWidget*) (void *) ((gtk_builder_get_object((buttons->
priv->financial_ui), (finc_dialog_fields[dialog][0])))))))
);
1156
1157 do_finc_expression(buttons->priv->equation, dialog, &arg[0], &arg[1], &arg[2], &arg[3]);
1158
1159 for (i = 0; i < 4; i++) {
1160 mp_clear(&arg[i]);
1161 }
1162}
1163
1164void character_code_dialog_response_cb(GtkWidget *dialog, gint response_id, MathButtons *buttons);
1165G_MODULE_EXPORT__attribute__((visibility("default")))
1166void
1167character_code_dialog_response_cb(GtkWidget *dialog, gint response_id, MathButtons *buttons)
1168{
1169 const gchar *text;
1170
1171 text = gtk_entry_get_text(GTK_ENTRY(buttons->priv->character_code_entry)((((GtkEntry*) (void *) ((buttons->priv->character_code_entry
)))))
);
1172
1173 if (response_id == GTK_RESPONSE_OK) {
1174 MPNumber x = mp_new();
1175 int i = 0;
1176
1177 mp_set_from_integer(0, &x);
1178 while (TRUE(!(0))) {
1179 mp_add_integer(&x, text[i], &x);
1180 if (text[i+1]) {
1181 mp_shift(&x, 8, &x);
1182 i++;
1183 }
1184 else
1185 break;
1186 }
1187 math_equation_insert_number(buttons->priv->equation, &x);
1188 mp_clear(&x);
1189 }
1190 gtk_widget_hide(dialog);
1191}
1192
1193void character_code_dialog_activate_cb(GtkWidget *entry, MathButtons *buttons);
1194G_MODULE_EXPORT__attribute__((visibility("default")))
1195void
1196character_code_dialog_activate_cb(GtkWidget *entry, MathButtons *buttons)
1197{
1198 character_code_dialog_response_cb(buttons->priv->character_code_dialog, GTK_RESPONSE_OK, buttons);
1199}
1200
1201gboolean character_code_dialog_delete_cb(GtkWidget *dialog, GdkEvent *event, MathButtons *buttons);
1202G_MODULE_EXPORT__attribute__((visibility("default")))
1203gboolean
1204character_code_dialog_delete_cb(GtkWidget *dialog, GdkEvent *event, MathButtons *buttons)
1205{
1206 character_code_dialog_response_cb(dialog, GTK_RESPONSE_CANCEL, buttons);
1207 return TRUE(!(0));
1208}
1209
1210gboolean bit_toggle_cb(GtkWidget *event_box, GdkEventButton *event, MathButtons *buttons);
1211G_MODULE_EXPORT__attribute__((visibility("default")))
1212gboolean
1213bit_toggle_cb(GtkWidget *event_box, GdkEventButton *event, MathButtons *buttons)
1214{
1215 math_equation_toggle_bit(buttons->priv->equation, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(event_box), "bit_index"))((gint) (glong) (g_object_get_data(((((GObject*) (void *) ((event_box
))))), "bit_index")))
);
1216 return TRUE(!(0));
1217}
1218
1219static void
1220remove_trailing_spaces(MathButtons *buttons)
1221{
1222 GtkTextMark *insert_mark;
1223 GtkTextIter start, end;
1224 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER(buttons->priv->equation)((((GtkTextBuffer*) (void *) ((buttons->priv->equation)
))))
);
1225 gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(buttons->priv->equation)((((GtkTextBuffer*) (void *) ((buttons->priv->equation)
))))
, &end, insert_mark);
1226 start = end;
1227 while (gtk_text_iter_backward_char(&start)) {
1228 if (!g_unichar_isspace(gtk_text_iter_get_char(&start)))
1229 break;
1230 gtk_text_buffer_delete(GTK_TEXT_BUFFER(buttons->priv->equation)((((GtkTextBuffer*) (void *) ((buttons->priv->equation)
))))
, &start, &end);
1231 }
1232}
1233
1234void set_superscript_cb(GtkWidget *widget, MathButtons *buttons);
1235G_MODULE_EXPORT__attribute__((visibility("default")))
1236void
1237set_superscript_cb(GtkWidget *widget, MathButtons *buttons)
1238{
1239 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)((((GtkToggleButton*) (void *) ((widget))))))) {
1240 math_equation_set_number_mode(buttons->priv->equation, SUPERSCRIPT);
1241 if (!gtk_text_buffer_get_has_selection(GTK_TEXT_BUFFER(buttons->priv->equation)((((GtkTextBuffer*) (void *) ((buttons->priv->equation)
))))
)) {
1242 remove_trailing_spaces(buttons);
1243 }
1244 }
1245 else if (math_equation_get_number_mode(buttons->priv->equation) == SUPERSCRIPT)
1246 math_equation_set_number_mode(buttons->priv->equation, NORMAL);
1247}
1248
1249void set_subscript_cb(GtkWidget *widget, MathButtons *buttons);
1250G_MODULE_EXPORT__attribute__((visibility("default")))
1251void
1252set_subscript_cb(GtkWidget *widget, MathButtons *buttons)
1253{
1254 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)((((GtkToggleButton*) (void *) ((widget))))))) {
1255 math_equation_set_number_mode(buttons->priv->equation, SUBSCRIPT);
1256 if (!gtk_text_buffer_get_has_selection(GTK_TEXT_BUFFER(buttons->priv->equation)((((GtkTextBuffer*) (void *) ((buttons->priv->equation)
))))
)) {
1257 remove_trailing_spaces(buttons);
1258 }
1259 }
1260 else if (math_equation_get_number_mode(buttons->priv->equation) == SUBSCRIPT)
1261 math_equation_set_number_mode(buttons->priv->equation, NORMAL);
1262}
1263
1264static void
1265number_mode_changed_cb(MathEquation *equation, GParamSpec *spec, MathButtons *buttons)
1266{
1267 GList *i;
1268 NumberMode mode;
1269
1270 mode = math_equation_get_number_mode(equation);
1271
1272 for (i = buttons->priv->superscript_toggles; i; i = i->next) {
1273 GtkWidget *widget = i->data;
1274 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget)((((GtkToggleButton*) (void *) ((widget))))), mode == SUPERSCRIPT);
1275 }
1276 for (i = buttons->priv->subscript_toggles; i; i = i->next) {
1277 GtkWidget *widget = i->data;
1278 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget)((((GtkToggleButton*) (void *) ((widget))))), mode == SUBSCRIPT);
1279 }
1280}
1281
1282static void
1283math_buttons_set_property(GObject *object,
1284 guint prop_id,
1285 const GValue *value,
1286 GParamSpec *pspec)
1287{
1288 MathButtons *self;
1289
1290 self = MATH_BUTTONS(object)((((MathButtons*) (void *) ((object)))));
1291
1292 switch (prop_id) {
1293 case PROP_EQUATION:
1294 self->priv->equation = g_value_get_object(value);
1295 math_buttons_set_mode(self, self->priv->mode);
1296 g_signal_connect(self->priv->equation, "notify::display", G_CALLBACK(display_changed_cb), self)g_signal_connect_data ((self->priv->equation), ("notify::display"
), (((GCallback) (display_changed_cb))), (self), ((void*)0), (
GConnectFlags) 0)
;
1297 g_signal_connect(self->priv->equation, "notify::number-mode", G_CALLBACK(number_mode_changed_cb), self)g_signal_connect_data ((self->priv->equation), ("notify::number-mode"
), (((GCallback) (number_mode_changed_cb))), (self), ((void*)
0), (GConnectFlags) 0)
;
1298 g_signal_connect(self->priv->equation, "notify::angle-units", G_CALLBACK(display_changed_cb), self)g_signal_connect_data ((self->priv->equation), ("notify::angle-units"
), (((GCallback) (display_changed_cb))), (self), ((void*)0), (
GConnectFlags) 0)
;
1299 g_signal_connect(self->priv->equation, "notify::number-format", G_CALLBACK(display_changed_cb), self)g_signal_connect_data ((self->priv->equation), ("notify::number-format"
), (((GCallback) (display_changed_cb))), (self), ((void*)0), (
GConnectFlags) 0)
;
1300 number_mode_changed_cb(self->priv->equation, NULL((void*)0), self);
1301 display_changed_cb(self->priv->equation, NULL((void*)0), self);
1302 break;
1303 case PROP_MODE:
1304 math_buttons_set_mode(self, g_value_get_int(value));
1305 break;
1306 case PROP_PROGRAMMING_BASE:
1307 math_buttons_set_programming_base(self, g_value_get_int(value));
1308 break;
1309 default:
1310 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "math-buttons.c", 1310, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
1311 break;
1312 }
1313}
1314
1315static void
1316math_buttons_get_property(GObject *object,
1317 guint prop_id,
1318 GValue *value,
1319 GParamSpec *pspec)
1320{
1321 MathButtons *self;
1322
1323 self = MATH_BUTTONS(object)((((MathButtons*) (void *) ((object)))));
1324
1325 switch (prop_id) {
1326 case PROP_EQUATION:
1327 g_value_set_object(value, self->priv->equation);
1328 break;
1329 case PROP_MODE:
1330 g_value_set_int(value, self->priv->mode);
1331 break;
1332 case PROP_PROGRAMMING_BASE:
1333 g_value_set_int(value, math_buttons_get_programming_base(self));
1334 break;
1335 default:
1336 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "math-buttons.c", 1336, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
1337 break;
1338 }
1339}
1340
1341static void
1342math_buttons_class_init(MathButtonsClass *klass)
1343{
1344 static GEnumValue button_mode_values[] =
1345 {
1346 {BASIC, "basic", "basic"},
1347 {ADVANCED, "advanced", "advanced"},
1348 {FINANCIAL, "financial", "financial"},
1349 {PROGRAMMING, "programming", "programming"},
1350 {0, NULL((void*)0), NULL((void*)0)}
1351 };
1352 GObjectClass *object_class = G_OBJECT_CLASS(klass)((((GObjectClass*) (void *) ((klass)))));
1353
1354 object_class->get_property = math_buttons_get_property;
1355 object_class->set_property = math_buttons_set_property;
1356
1357 button_mode_type = g_enum_register_static("ButtonMode", button_mode_values);
1358
1359 g_object_class_install_property(object_class,
1360 PROP_EQUATION,
1361 g_param_spec_object("equation",
1362 "equation",
1363 "Equation being controlled",
1364 math_equation_get_type(),
1365 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1366 g_object_class_install_property(object_class,
1367 PROP_MODE,
1368 g_param_spec_enum("mode",
1369 "mode",
1370 "Button mode",
1371 button_mode_type,
1372 BASIC,
1373 G_PARAM_READWRITE));
1374 g_object_class_install_property(object_class,
1375 PROP_PROGRAMMING_BASE,
1376 g_param_spec_int("programming-base",
1377 "programming-base",
1378 "Base to use in programming mode",
1379 2, 16, 10,
1380 G_PARAM_READWRITE));
1381}
1382
1383static void
1384math_buttons_init(MathButtons *buttons)
1385{
1386 buttons->priv = math_buttons_get_instance_private (buttons);
1387 gtk_box_set_spacing(GTK_BOX(buttons)((((GtkBox*) (void *) ((buttons))))), 6);
1388 gtk_orientable_set_orientation (GTK_ORIENTABLE (buttons)((((GtkOrientable*) (void *) ((buttons))))),
1389 GTK_ORIENTATION_VERTICAL);
1390 buttons->priv->programming_base = 10;
1391 g_signal_connect(G_OBJECT(buttons), "show", G_CALLBACK(load_buttons), NULL)g_signal_connect_data ((((((GObject*) (void *) ((buttons)))))
), ("show"), (((GCallback) (load_buttons))), (((void*)0)), ((
void*)0), (GConnectFlags) 0)
;
1392}
diff --git a/2024-07-10-100902-3667-1@fe495df3ec39_master/report-720c65.html b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-720c65.html new file mode 100644 index 0000000..14bfdda --- /dev/null +++ b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-720c65.html @@ -0,0 +1,1270 @@ + + + +lexer.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:lexer.c
Warning:line 241, column 21
Although the value stored to 'type' is used in the enclosing expression, the value is never actually read from 'type'
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name lexer.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D LOCALE_DIR="/usr/local/share/locale" -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/atk-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/gio-unix-2.0 -D WITH_GZFILEOP -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-07-10-100902-3667-1 -x c lexer.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1#include <stdlib.h>
2#include <assert.h>
3#include <string.h>
4
5#include "lexer.h"
6#include "parserfunc.h"
7#include "mp-equation.h"
8
9static gboolean
10l_check_if_function(LexerState* state)
11{
12 gchar* name = pl_get_marked_substring(state->prelexer);
13 if(!state->parent->function_is_defined)
14 {
15 free(name);
16 return FALSE(0);
17 }
18 if ((*(state->parent->function_is_defined))(state->parent, name))
19 {
20 free(name);
21 return TRUE(!(0));
22 }
23 else
24 {
25 free(name);
26 return FALSE(0);
27 }
28}
29
30static gboolean
31l_check_if_number(LexerState* state)
32{
33 MPNumber tmp = mp_new();
34 int count = 0;
35 gchar* text = pl_get_marked_substring(state->prelexer);
36 if(mp_set_from_string(text, state->parent->options->base, &tmp) == 0)
37 {
38 free(text);
39 mp_clear(&tmp);
40 return TRUE(!(0));
41 }
42 else
43 {
44 /* Try to rollback several characters to see, if that yeilds any number. */
45 while(strlen (text) > 0)
46 {
47 if(mp_set_from_string(text, state->parent->options->base, &tmp) == 0)
48 {
49 free(text);
50 mp_clear(&tmp);
51 return TRUE(!(0));
52 }
53 free(text);
54 count++;
55 pl_roll_back(state->prelexer);
56 text = pl_get_marked_substring(state->prelexer);
57 }
58 /* Undo all rollbacks. */
59 while(count--)
60 pl_get_next_token (state->prelexer);
61 free(text);
62 mp_clear(&tmp);
63 return FALSE(0);
64 }
65}
66
67/* Insert generated token to the LexerState structure. */
68static LexerToken*
69l_insert_token(LexerState* state, const LexerTokenType type)
70{
71 state->tokens = (LexerToken *) realloc(state->tokens, (state->token_count + 1) * sizeof(LexerToken));
72 assert(state->tokens != NULL)((void) sizeof ((state->tokens != ((void*)0)) ? 1 : 0), __extension__
({ if (state->tokens != ((void*)0)) ; else __assert_fail (
"state->tokens != NULL", "lexer.c", 72, __extension__ __PRETTY_FUNCTION__
); }))
;
73 state->tokens[state->token_count].string = pl_get_marked_substring(state->prelexer);
74 state->tokens[state->token_count].start_index = state->prelexer->mark_index;
75 state->tokens[state->token_count].end_index = state->prelexer->next_index;
76 state->tokens[state->token_count].token_type = type;
77 state->token_count++;
78 return &state->tokens[state->token_count - 1];
79}
80
81/* Generates next token from pre-lexer stream and call l_insert_token() to insert it at the end. */
82static LexerToken*
83l_insert_next_token(LexerState* lstate)
84{
85 PreLexerState* state = lstate->prelexer;
86 LexerTokenType type;
87 gchar* tmp;
88 pl_set_marker(state);
89 /* Ignore all blank spaces. :) */
90 while((type = pl_get_next_token(state)) == PL_SKIP)
91 /* Set marker. Beginning of new token. */
92 pl_set_marker(state);
93 if(type == T_AND
94 ||type == T_OR
95 ||type == T_XOR
96 ||type == T_NOT
97 ||type == T_ADD
98 ||type == T_SUBTRACT
99 ||type == T_MULTIPLY
100 ||type == T_DIV
101 ||type == T_L_FLOOR
102 ||type == T_R_FLOOR
103 ||type == T_L_CEILING
104 ||type == T_R_CEILING
105 ||type == T_ROOT
106 ||type == T_ROOT_3
107 ||type == T_ROOT_4
108 ||type == T_ASSIGN
109 ||type == T_L_R_BRACKET
110 ||type == T_R_R_BRACKET
111 ||type == T_L_S_BRACKET
112 ||type == T_R_S_BRACKET
113 ||type == T_L_C_BRACKET
114 ||type == T_R_C_BRACKET
115 ||type == T_ABS
116 ||type == T_POWER
117 ||type == T_FACTORIAL
118 ||type == T_PERCENTAGE)
119 {
120 return l_insert_token(lstate, type);
121 }
122 /* [PL_SUPER_MINUS][PL_SUPER_DIGIT]+ */
123 if(type == PL_SUPER_MINUS)
124 {
125 if((type = pl_get_next_token(state)) != PL_SUPER_DIGIT)
126 {
127 /* ERROR: expected PL_SUP_DIGIT */
128 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring (state));
129 free(tmp);
130 return l_insert_token(lstate, T_UNKNOWN);
131 }
132 /* Get all PL_SUPER_DIGITs. */
133 while (pl_get_next_token(state) == PL_SUPER_DIGIT);
134 pl_roll_back(state);
135 return l_insert_token(lstate, T_NSUP_NUMBER);
136 }
137 /* [PL_SUPER_DIGIT]+ */
138 if(type == PL_SUPER_DIGIT)
139 {
140 while(pl_get_next_token(state) == PL_SUPER_DIGIT);
141 pl_roll_back(state);
142 return l_insert_token(lstate, T_SUP_NUMBER);
143 }
144 /* [PL_SUB_DIGIT]+ */
145 if(type == PL_SUB_DIGIT)
146 {
147 while(pl_get_next_token(state) == PL_SUB_DIGIT);
148 pl_roll_back(state);
149 return l_insert_token(lstate, T_SUB_NUMBER);
150 }
151 /* [PL_FRACTION] */
152 if(type == PL_FRACTION)
153 {
154 return l_insert_token(lstate, T_NUMBER);
155 }
156 if(type == PL_DIGIT)
157 {
158 while((type = pl_get_next_token(state)) == PL_DIGIT);
159 if(type == PL_FRACTION)
160 {
161 return l_insert_token(lstate, T_NUMBER);
162 }
163 else if(type == PL_SUB_DIGIT)
164 {
165 while(pl_get_next_token(state) == PL_SUB_DIGIT);
166 pl_roll_back(state);
167 return l_insert_token(lstate, T_NUMBER);
168 }
169 else if(type == PL_DEGREE)
170 {
171 type = pl_get_next_token(state);
172 if(type == PL_DIGIT)
173 {
174 while((type = pl_get_next_token(state)) == PL_DIGIT);
175 if(type == PL_DECIMAL)
176 {
177 goto ANGLE_NUM_DM_STATE;
178 }
179 else if(type == PL_MINUTE)
180 {
181 type = pl_get_next_token(state);
182 if(type == PL_DIGIT)
183 {
184 while((type = pl_get_next_token(state)) == PL_DIGIT);
185 if(type == PL_DECIMAL)
186 {
187 goto ANGLE_NUM_DMS_STATE;
188 }
189 else if(type == PL_SECOND)
190 {
191 return l_insert_token(lstate, T_NUMBER);
192 }
193 else
194 {
195 /* ERROR: expected PL_SECOND */
196 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring (state));
197 free(tmp);
198 return l_insert_token(lstate, T_UNKNOWN);
199 }
200 }
201 else if(type == PL_DECIMAL)
202 {
203ANGLE_NUM_DMS_STATE:
204 if((type = pl_get_next_token (state)) != PL_DIGIT)
205 {
206 /* ERROR: expected PL_DIGIT */
207 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
208 free(tmp);
209 return l_insert_token(lstate, T_UNKNOWN);
210 }
211 while((type = pl_get_next_token(state)) == PL_DIGIT);
212 if(type == PL_SECOND)
213 {
214 return l_insert_token(lstate, T_NUMBER);
215 }
216 else
217 {
218 /* ERROR: expected PL_SECOND */
219 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
220 free(tmp);
221 return l_insert_token(lstate, T_UNKNOWN);
222 }
223 }
224 else
225 {
226 pl_roll_back(state);
227 return l_insert_token(lstate, T_NUMBER);
228 }
229 }
230 else
231 {
232 /* ERROR: expected PL_MINUTE | PL_DIGIT */
233 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
234 free(tmp);
235 return l_insert_token(lstate, T_UNKNOWN);
236 }
237 }
238 else if(type == PL_DECIMAL)
239 {
240ANGLE_NUM_DM_STATE:
241 if((type = pl_get_next_token(state)) != PL_DIGIT)
Although the value stored to 'type' is used in the enclosing expression, the value is never actually read from 'type'
242 {
243 /* ERROR: expected PL_DIGIT */
244 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
245 free(tmp);
246 return l_insert_token(lstate, T_UNKNOWN);
247 }
248 while((type = pl_get_next_token(state)) == PL_DIGIT);
249 if(type == PL_MINUTE)
250 {
251 return l_insert_token(lstate, T_NUMBER);
252 }
253 else
254 {
255 /* ERROR: expected PL_MINUTE */
256 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
257 free(tmp);
258 return l_insert_token(lstate, T_UNKNOWN);
259 }
260 }
261 else
262 {
263 return l_insert_token(lstate, T_NUMBER);
264 }
265 }
266 else if(type == PL_DECIMAL)
267 {
268 goto DECIMAL_STATE;
269 }
270 else if(type == PL_HEX)
271 {
272 goto HEX_DEC_STATE;
273 }
274 else
275 {
276 pl_roll_back(state);
277 return l_insert_token(lstate, T_NUMBER);
278 }
279 }
280 if(type == PL_DECIMAL)
281 {
282DECIMAL_STATE:
283 type = pl_get_next_token(state);
284 if(type == PL_DIGIT)
285 {
286 while((type = pl_get_next_token(state)) == PL_DIGIT);
287 if(type == PL_DEGREE)
288 {
289 return l_insert_token(lstate, T_NUMBER);
290 }
291 else if(type == PL_HEX)
292 {
293 goto DECIMAL_HEX_STATE;
294 }
295 else if(type == PL_SUB_DIGIT)
296 {
297 while(pl_get_next_token(state) == PL_SUB_DIGIT);
298 pl_roll_back(state);
299 return l_insert_token(lstate, T_NUMBER);
300 }
301 else
302 {
303 pl_roll_back(state);
304 return l_insert_token(lstate, T_NUMBER);
305 }
306 }
307 else if(type == PL_HEX)
308 {
309 goto DECIMAL_HEX_STATE;
310 }
311 else
312 {
313 /* ERROR: expected PL_DIGIT | PL_HEX */
314 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
315 free(tmp);
316 return l_insert_token(lstate, T_UNKNOWN);
317 }
318 }
319 if(type == PL_HEX)
320 {
321 while((type = pl_get_next_token(state)) == PL_HEX);
322 if(type == PL_DIGIT)
323 {
324HEX_DEC_STATE:
325 while(1)
326 {
327 type = pl_get_next_token(state);
328 if(type == PL_DIGIT || type == PL_HEX)
329 {
330 continue;
331 }
332 else if(type == PL_DECIMAL)
333 {
334 goto DECIMAL_HEX_STATE;
335 }
336 else if(type == PL_SUB_DIGIT)
337 {
338 while(pl_get_next_token(state) == PL_SUB_DIGIT);
339 pl_roll_back(state);
340 return l_insert_token(lstate, T_NUMBER);
341 }
342 else
343 {
344 if(l_check_if_number(lstate))
345 return l_insert_token(lstate, T_NUMBER);
346 /* ERROR: expected PL_DECIMAL | PL_DIGIT | PL_HEX */
347 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
348 free(tmp);
349 return l_insert_token(lstate, T_UNKNOWN);
350 }
351 }
352 }
353 else if(type == PL_DECIMAL)
354 {
355DECIMAL_HEX_STATE:
356 type = pl_get_next_token(state);
357 if(!(type == PL_DIGIT || type == PL_HEX))
358 {
359 /* ERROR: expected PL_DIGIT | PL_HEX */
360 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
361 free(tmp);
362 return l_insert_token(lstate, T_UNKNOWN);
363 }
364 while(1)
365 {
366 type = pl_get_next_token(state);
367 if(type == PL_DIGIT || type == PL_HEX)
368 {
369 continue;
370 }
371 else if(type == PL_SUB_DIGIT)
372 {
373 while(pl_get_next_token(state) == PL_SUB_DIGIT);
374 pl_roll_back(state);
375 return l_insert_token(lstate, T_NUMBER);
376 }
377 else
378 {
379 pl_roll_back(state);
380 return l_insert_token(lstate, T_NUMBER);
381 }
382 }
383 }
384 else if(type == PL_SUB_DIGIT)
385 {
386 while(pl_get_next_token(state) == PL_SUB_DIGIT);
387 pl_roll_back(state);
388 if(l_check_if_number(lstate))
389 {
390 /* NUMBER */
391 return l_insert_token(lstate, T_NUMBER);
392 }
393 else
394 {
395 /* VARIABLE */
396 if(l_check_if_function(lstate))
397 {
398 return l_insert_token(lstate, T_FUNCTION);
399 }
400 else
401 {
402 return l_insert_token(lstate, T_VARIABLE);
403 }
404 }
405 }
406 else if(type == PL_LETTER)
407 {
408 goto LETTER_STATE;
409 }
410 else
411 {
412 pl_roll_back(state);
413 if(l_check_if_number(lstate))
414 {
415 /* NUMBER */
416 return l_insert_token(lstate, T_NUMBER);
417 }
418 else
419 {
420 /* VARIABLE */
421 if(l_check_if_function(lstate))
422 {
423 return l_insert_token(lstate, T_FUNCTION);
424 }
425 else
426 {
427 return l_insert_token(lstate, T_VARIABLE);
428 }
429 }
430 }
431 }
432 if(type == PL_LETTER)
433 {
434LETTER_STATE:
435 while(1)
436 {
437 type = pl_get_next_token(state);
438 if(type == PL_LETTER || type == PL_HEX)
439 {
440 continue;
441 }
442 else if(type == PL_SUB_DIGIT)
443 {
444 while(pl_get_next_token(state) == PL_SUB_DIGIT);
445 pl_roll_back(state);
446 tmp = g_ascii_strdown(pl_get_marked_substring(state), -1);
447 if(g_strcmp0(tmp, "mod") == 0)
448 {
449 return l_insert_token(lstate, T_MOD);
450 }
451 if(g_strcmp0(tmp, "and") == 0)
452 {
453 return l_insert_token(lstate, T_AND);
454 }
455 if(g_strcmp0(tmp, "or") == 0)
456 {
457 return l_insert_token(lstate, T_OR);
458 }
459 if(g_strcmp0(tmp, "xor") == 0)
460 {
461 return l_insert_token(lstate, T_XOR);
462 }
463 if(g_strcmp0(tmp, "not") == 0)
464 {
465 return l_insert_token(lstate, T_NOT);
466 }
467 if(g_strcmp0(tmp, "in") == 0)
468 {
469 return l_insert_token(lstate, T_IN);
470 }
471 if(l_check_if_function(lstate))
472 {
473 return l_insert_token(lstate, T_FUNCTION);
474 }
475 else
476 {
477 return l_insert_token(lstate, T_VARIABLE);
478 }
479 }
480 else
481 {
482 pl_roll_back(state);
483 tmp = g_ascii_strdown(pl_get_marked_substring(state), -1);
484 if(g_strcmp0(tmp, "mod") == 0)
485 {
486 return l_insert_token(lstate, T_MOD);
487 }
488 if(g_strcmp0(tmp, "and") == 0)
489 {
490 return l_insert_token(lstate, T_AND);
491 }
492 if(g_strcmp0(tmp, "or") == 0)
493 {
494 return l_insert_token(lstate, T_OR);
495 }
496 if(g_strcmp0(tmp, "xor") == 0)
497 {
498 return l_insert_token(lstate, T_XOR);
499 }
500 if(g_strcmp0(tmp, "not") == 0)
501 {
502 return l_insert_token(lstate, T_NOT);
503 }
504 if(g_strcmp0(tmp, "in") == 0)
505 {
506 return l_insert_token(lstate, T_IN);
507 }
508 if(l_check_if_function(lstate))
509 {
510 return l_insert_token(lstate, T_FUNCTION);
511 }
512 else
513 {
514 return l_insert_token(lstate, T_VARIABLE);
515 }
516 }
517 }
518 }
519 if(type == PL_EOS)
520 {
521 return l_insert_token(lstate, PL_EOS);
522 }
523 /* ERROR: Unexpected token.. X( */
524 set_error(lstate->parent, PARSER_ERR_INVALID, tmp = pl_get_marked_substring(state));
525 free(tmp);
526 return l_insert_token(lstate, T_UNKNOWN);
527}
528
529/* Call l_insert_next_token() as many times as needed to completely tokenize the string. */
530void
531l_insert_all_tokens(LexerState* state)
532{
533 LexerToken* token;
534 while(1)
535 {
536 token = l_insert_next_token(state);
537 assert(token != NULL)((void) sizeof ((token != ((void*)0)) ? 1 : 0), __extension__
({ if (token != ((void*)0)) ; else __assert_fail ("token != NULL"
, "lexer.c", 537, __extension__ __PRETTY_FUNCTION__); }))
;
538 if(token->token_type == PL_EOS)
539 {
540 break;
541 }
542 }
543}
544
545/* Create a lexer state from given input string. This will take care of pre-lexer state. */
546LexerState*
547l_create_lexer(const gchar* input, struct parser_state* parent)
548{
549 LexerState* ret;
550 ret = (LexerState *) malloc(sizeof(LexerState));
551 assert(ret != NULL)((void) sizeof ((ret != ((void*)0)) ? 1 : 0), __extension__ (
{ if (ret != ((void*)0)) ; else __assert_fail ("ret != NULL",
"lexer.c", 551, __extension__ __PRETTY_FUNCTION__); }))
;
552 ret->prelexer = pl_create_scanner(input);
553 ret->tokens = NULL((void*)0);
554 ret->token_count = 0;
555 ret->next_token = 0;
556 ret->parent = parent;
557 return ret;
558}
559
560/* Destroy lexer state and free memory. */
561void
562l_destroy_lexer(LexerState* state)
563{
564 int l;
565 pl_destroy_scanner(state->prelexer);
566 for(l = 0; l < state->token_count; l++)
567 {
568 free(state->tokens[l].string);
569 }
570 free(state->tokens);
571 free(state);
572}
573
574/* Get next token interface. Will be called by parser to get pointer to next token in token stream. */
575LexerToken*
576l_get_next_token(LexerState* state)
577{
578 /* Return PL_EOS token after token stream reaches to its end. */
579 if(state->next_token >= state->token_count)
580 return &state->tokens[state->token_count - 1];
581 return &state->tokens[state->next_token++];
582}
583
584/* Roll back one lexer token. */
585void
586l_roll_back(LexerState* state)
587{
588 if(state->next_token > 0)
589 state->next_token--;
590}
diff --git a/2024-07-10-100902-3667-1@fe495df3ec39_master/report-90c61f.html b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-90c61f.html new file mode 100644 index 0000000..baaf359 --- /dev/null +++ b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-90c61f.html @@ -0,0 +1,2630 @@ + + + +math-equation.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:math-equation.c
Warning:line 802, column 14
Value stored to 'is_digit' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name math-equation.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D LOCALE_DIR="/usr/local/share/locale" -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/atk-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/gio-unix-2.0 -D WITH_GZFILEOP -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-07-10-100902-3667-1 -x c math-equation.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright (C) 1987-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * Copyright (C) 2008-2011 Robert Ancell
4 *
5 * This program is free software: you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation, either version 2 of the License, or (at your option) any later
8 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
9 * license.
10 */
11
12#include <stdlib.h>
13#include <stdio.h>
14#include <string.h>
15#include <ctype.h>
16#include <math.h>
17#include <errno(*__errno_location ()).h>
18#include <glib.h>
19#include <glib/gi18n.h>
20
21#include "math-equation.h"
22
23#include "mp.h"
24#include "mp-equation.h"
25#include "mp-serializer.h"
26#include "mp-enums.h"
27#include "unit-manager.h"
28#include "utility.h"
29
30enum {
31 PROP_0,
32 PROP_STATUS,
33 PROP_DISPLAY,
34 PROP_EQUATION,
35 PROP_NUMBER_MODE,
36 PROP_ACCURACY,
37 PROP_SHOW_THOUSANDS_SEPARATORS,
38 PROP_SHOW_TRAILING_ZEROES,
39 PROP_NUMBER_FORMAT,
40 PROP_BASE,
41 PROP_WORD_SIZE,
42 PROP_ANGLE_UNITS,
43 PROP_SOURCE_CURRENCY,
44 PROP_TARGET_CURRENCY,
45 PROP_SOURCE_UNITS,
46 PROP_TARGET_UNITS,
47 PROP_SERIALIZER
48};
49
50static GType number_mode_type, number_format_type, angle_unit_type;
51
52/* Expression mode state */
53typedef struct {
54 MPNumber ans; /* Previously calculated answer */
55 gchar *expression; /* Expression entered by user */
56 gint ans_start, ans_end; /* Start and end characters for ans variable in expression */
57 gint cursor; /* ??? */
58 NumberMode number_mode; /* ??? */
59 gboolean can_super_minus; /* TRUE if entering minus can generate a superscript minus */
60 gboolean entered_multiply; /* Last insert was a multiply character */
61 gchar *status; /* Equation status */
62} MathEquationState;
63
64struct MathEquationPrivate
65{
66 GtkTextTag *ans_tag;
67
68 gint word_size; /* Word size in bits */
69 MPAngleUnit angle_units; /* Units for trigonometric functions */
70 char *source_currency;
71 char *target_currency;
72 char *source_units;
73 char *target_units;
74 NumberMode number_mode; /* ??? */
75 gboolean can_super_minus; /* TRUE if entering minus can generate a superscript minus */
76
77 gunichar digits[16]; /* Localized digits */
78
79 GtkTextMark *ans_start, *ans_end;
80
81 MathEquationState state; /* Equation state */
82 GList *undo_stack; /* History of expression mode states */
83 GList *redo_stack;
84 gboolean in_undo_operation;
85
86 gboolean in_reformat;
87
88 gboolean in_delete;
89
90 gboolean in_solve;
91
92 MathVariables *variables;
93 MpSerializer *serializer;
94
95 GAsyncQueue *queue;
96};
97
98typedef struct {
99 MPNumber *number_result;
100 gchar *text_result;
101 gchar *error;
102} SolveData;
103
104G_DEFINE_TYPE_WITH_PRIVATE (MathEquation, math_equation, GTK_TYPE_TEXT_BUFFER)static void math_equation_init (MathEquation *self); static void
math_equation_class_init (MathEquationClass *klass); static GType
math_equation_get_type_once (void); static gpointer math_equation_parent_class
= ((void*)0); static gint MathEquation_private_offset; static
void math_equation_class_intern_init (gpointer klass) { math_equation_parent_class
= g_type_class_peek_parent (klass); if (MathEquation_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &MathEquation_private_offset
); math_equation_class_init ((MathEquationClass*) klass); } __attribute__
((__unused__)) static inline gpointer math_equation_get_instance_private
(MathEquation *self) { return (((gpointer) ((guint8*) (self)
+ (glong) (MathEquation_private_offset)))); } GType math_equation_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= math_equation_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType math_equation_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
gtk_text_buffer_get_type ()), g_intern_static_string ("MathEquation"
), sizeof (MathEquationClass), (GClassInitFunc)(void (*)(void
)) math_equation_class_intern_init, sizeof (MathEquation), (GInstanceInitFunc
)(void (*)(void)) math_equation_init, (GTypeFlags) 0); { {{ MathEquation_private_offset
= g_type_add_instance_private (g_define_type_id, sizeof (MathEquationPrivate
)); };} } return g_define_type_id; }
;
105
106MathEquation *
107math_equation_new()
108{
109 return g_object_new(math_equation_get_type(), NULL((void*)0));
110}
111
112MathVariables *
113math_equation_get_variables(MathEquation *equation)
114{
115 return equation->priv->variables;
116}
117
118static void
119get_ans_offsets(MathEquation *equation, gint *start, gint *end)
120{
121 GtkTextIter iter;
122
123 if (!equation->priv->ans_start) {
124 *start = *end = -1;
125 return;
126 }
127
128 gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &iter, equation->priv->ans_start);
129 *start = gtk_text_iter_get_offset(&iter);
130 gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &iter, equation->priv->ans_end);
131 *end = gtk_text_iter_get_offset(&iter);
132}
133
134static void
135reformat_ans(MathEquation *equation)
136{
137 if (!equation->priv->ans_start)
138 return;
139
140 gchar *orig_ans_text;
141 gchar *ans_text;
142 GtkTextIter ans_start, ans_end;
143
144 gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &ans_start, equation->priv->ans_start);
145 gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &ans_end, equation->priv->ans_end);
146 orig_ans_text = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &ans_start, &ans_end, FALSE(0));
147 ans_text = mp_serializer_to_string(equation->priv->serializer, &equation->priv->state.ans);
148 if (strcmp(orig_ans_text, ans_text) != 0) {
149 gint start;
150
151 equation->priv->in_undo_operation = TRUE(!(0));
152 equation->priv->in_reformat = TRUE(!(0));
153
154 start = gtk_text_iter_get_offset(&ans_start);
155 gtk_text_buffer_delete(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &ans_start, &ans_end);
156 gtk_text_buffer_insert_with_tags(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &ans_end, ans_text, -1, equation->priv->ans_tag, NULL((void*)0));
157
158 /* There seems to be a bug in the marks as they alternate being the correct and incorrect ways. Reset them */
159 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &ans_start, start);
160 gtk_text_buffer_move_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), equation->priv->ans_start, &ans_start);
161 gtk_text_buffer_move_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), equation->priv->ans_end, &ans_end);
162
163 equation->priv->in_reformat = FALSE(0);
164 equation->priv->in_undo_operation = FALSE(0);
165 }
166 gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &ans_start, equation->priv->ans_start);
167 gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &ans_end, equation->priv->ans_end);
168 g_free(orig_ans_text);
169 g_free(ans_text);
170}
171
172static gint
173count_digits(MathEquation *equation, const gchar *text)
174{
175 const gchar *read_iter;
176 gint count = 0;
177
178 read_iter = text;
179 while (*read_iter != '\0') {
180 if (!g_unichar_isdigit(g_utf8_get_char(read_iter)))
181 return count;
182
183 read_iter = g_utf8_next_char(read_iter)(char *)((read_iter) + g_utf8_skip[*(const guchar *)(read_iter
)])
;
184
185 /* Allow a thousands separator between digits follow a digit */
186 if (g_utf8_get_char(read_iter) == mp_serializer_get_thousands_separator(equation->priv->serializer)) {
187 read_iter = g_utf8_next_char(read_iter)(char *)((read_iter) + g_utf8_skip[*(const guchar *)(read_iter
)])
;
188 if (!g_unichar_isdigit(g_utf8_get_char(read_iter)))
189 return count;
190 }
191
192 count++;
193 }
194
195 return count;
196}
197
198static void
199reformat_separators(MathEquation *equation)
200{
201 gchar *text, *read_iter;
202 gint ans_start, ans_end;
203 gint offset, digit_offset = 0;
204 gboolean in_number = FALSE(0), in_radix = FALSE(0), last_is_tsep = FALSE(0);
205
206 equation->priv->in_undo_operation = TRUE(!(0));
207 equation->priv->in_reformat = TRUE(!(0));
208
209 text = math_equation_get_display(equation);
210 get_ans_offsets(equation, &ans_start, &ans_end);
211 for (read_iter = text, offset = 0; *read_iter != '\0'; read_iter = g_utf8_next_char(read_iter)(char *)((read_iter) + g_utf8_skip[*(const guchar *)(read_iter
)])
, offset++) {
212 gunichar c;
213 gboolean expect_tsep;
214
215 /* See what digit this character is */
216 c = g_utf8_get_char(read_iter);
217
218 expect_tsep = math_equation_get_base(equation) == 10 &&
219 mp_serializer_get_show_thousands_separators(equation->priv->serializer) &&
220 in_number && !in_radix && !last_is_tsep &&
221 digit_offset > 0 && digit_offset % mp_serializer_get_thousands_separator_count(equation->priv->serializer) == 0;
222 last_is_tsep = FALSE(0);
223
224 /* Don't mess with ans */
225 if (offset >= ans_start && offset <= ans_end) {
226 in_number = in_radix = FALSE(0);
227 continue;
228 }
229 if (g_unichar_isdigit(c)) {
230 if (!in_number)
231 digit_offset = count_digits(equation, read_iter);
232 in_number = TRUE(!(0));
233
234 /* Expected a thousands separator between these digits - insert it */
235 if (expect_tsep) {
236 GtkTextIter iter;
237 gchar buffer[7];
238 gint len;
239
240 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &iter, offset);
241 len = g_unichar_to_utf8(mp_serializer_get_thousands_separator(equation->priv->serializer), buffer);
242 buffer[len] = '\0';
243 gtk_text_buffer_insert(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &iter, buffer, -1);
244 offset++;
245 last_is_tsep = TRUE(!(0));
246 }
247
248 digit_offset--;
249 }
250 else if (c == mp_serializer_get_radix(equation->priv->serializer)) {
251 in_number = in_radix = TRUE(!(0));
252 }
253 else if (c == mp_serializer_get_thousands_separator(equation->priv->serializer)) {
254 /* Didn't expect thousands separator - delete it */
255 if (!expect_tsep && in_number) {
256 GtkTextIter start, end;
257 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &start, offset);
258 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &end, offset + 1);
259 gtk_text_buffer_delete(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &start, &end);
260 offset--;
261 }
262 else
263 last_is_tsep = TRUE(!(0));
264 }
265 else {
266 in_number = in_radix = FALSE(0);
267 }
268 }
269
270 g_free(text);
271
272 equation->priv->in_reformat = FALSE(0);
273 equation->priv->in_undo_operation = FALSE(0);
274}
275
276static void
277reformat_display(MathEquation *equation)
278{
279 /* Change ans */
280 reformat_ans(equation);
281
282 /* Add/remove thousands separators */
283 reformat_separators(equation);
284
285 g_signal_emit_by_name(equation, "display-changed");
286}
287
288static MathEquationState *
289get_current_state(MathEquation *equation)
290{
291 MathEquationState *state;
292 gint ans_start = -1, ans_end = -1;
293
294 state = g_malloc0(sizeof(MathEquationState));
295 state->ans = mp_new();
296
297 if (equation->priv->ans_start)
298 {
299 GtkTextIter iter;
300 gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &iter, equation->priv->ans_start);
301 ans_start = gtk_text_iter_get_offset(&iter);
302 gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &iter, equation->priv->ans_end);
303 ans_end = gtk_text_iter_get_offset(&iter);
304 }
305
306 mp_set_from_mp(&equation->priv->state.ans, &state->ans);
307 state->expression = math_equation_get_display(equation);
308 state->ans_start = ans_start;
309 state->ans_end = ans_end;
310 g_object_get(G_OBJECT(equation)((((GObject*) (void *) ((equation))))), "cursor-position", &state->cursor, NULL((void*)0));
311 state->number_mode = equation->priv->number_mode;
312 state->can_super_minus = equation->priv->can_super_minus;
313 state->entered_multiply = equation->priv->state.entered_multiply;
314 state->status = g_strdup(equation->priv->state.status)g_strdup_inline (equation->priv->state.status);
315
316 return state;
317}
318
319static void
320free_state(MathEquationState *state)
321{
322 g_free(state->expression);
323 g_free(state->status);
324 g_free(state);
325}
326
327static void
328math_equation_push_undo_stack(MathEquation *equation)
329{
330 GList *link;
331 MathEquationState *state;
332
333 if (equation->priv->in_undo_operation)
334 return;
335
336 math_equation_set_status(equation, "");
337
338 /* Can't redo anymore */
339 for (link = equation->priv->redo_stack; link; link = link->next) {
340 state = link->data;
341 free_state(state);
342 }
343 g_list_free(equation->priv->redo_stack);
344 equation->priv->redo_stack = NULL((void*)0);
345
346 state = get_current_state(equation);
347 equation->priv->undo_stack = g_list_prepend(equation->priv->undo_stack, state);
348}
349
350static void
351clear_ans(MathEquation *equation, gboolean remove_tag)
352{
353 if (!equation->priv->ans_start)
354 return;
355
356 if (remove_tag) {
357 GtkTextIter start, end;
358
359 gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &start, equation->priv->ans_start);
360 gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &end, equation->priv->ans_end);
361 gtk_text_buffer_remove_tag(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), equation->priv->ans_tag, &start, &end);
362 }
363
364 gtk_text_buffer_delete_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), equation->priv->ans_start);
365 gtk_text_buffer_delete_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), equation->priv->ans_end);
366 equation->priv->ans_start = NULL((void*)0);
367 equation->priv->ans_end = NULL((void*)0);
368}
369
370static void
371apply_state(MathEquation *equation, MathEquationState *state)
372{
373 GtkTextIter cursor;
374
375 /* Disable undo detection */
376 equation->priv->in_undo_operation = TRUE(!(0));
377
378 mp_set_from_mp(&state->ans, &equation->priv->state.ans);
379
380 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), state->expression, -1);
381 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &cursor, state->cursor);
382 gtk_text_buffer_place_cursor(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &cursor);
383 clear_ans(equation, FALSE(0));
384 if (state->ans_start >= 0) {
385 GtkTextIter start, end;
386
387 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &start, state->ans_start);
388 equation->priv->ans_start = gtk_text_buffer_create_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), NULL((void*)0), &start, FALSE(0));
389 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &end, state->ans_end);
390 equation->priv->ans_end = gtk_text_buffer_create_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), NULL((void*)0), &end, TRUE(!(0)));
391 gtk_text_buffer_apply_tag(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), equation->priv->ans_tag, &start, &end);
392 }
393
394 math_equation_set_number_mode(equation, state->number_mode);
395 equation->priv->can_super_minus = state->can_super_minus;
396 equation->priv->state.entered_multiply = state->entered_multiply;
397 math_equation_set_status(equation, state->status);
398
399 equation->priv->in_undo_operation = FALSE(0);
400}
401
402void
403math_equation_copy(MathEquation *equation)
404{
405 GtkTextIter start, end;
406 gchar *text;
407
408 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_84
; if (equation != ((void*)0)) _g_boolean_var_84 = 1; else _g_boolean_var_84
= 0; _g_boolean_var_84; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
409
410 if (!gtk_text_buffer_get_selection_bounds(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &start, &end))
411 gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &start, &end);
412
413 text = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &start, &end, FALSE(0));
414 gtk_clipboard_set_text(gtk_clipboard_get(GDK_NONE((GdkAtom)((gpointer) (gulong) (0)))), g_str_to_ascii (text, "C"), -1);
415 g_free(text);
416}
417
418static void
419on_paste(GtkClipboard *clipboard, const gchar *text, gpointer data)
420{
421 MathEquation *equation = data;
422 if (text != NULL((void*)0))
423 math_equation_insert(equation, text);
424}
425
426void
427math_equation_paste(MathEquation *equation)
428{
429 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_85
; if (equation != ((void*)0)) _g_boolean_var_85 = 1; else _g_boolean_var_85
= 0; _g_boolean_var_85; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
430 gtk_clipboard_request_text(gtk_clipboard_get(GDK_NONE((GdkAtom)((gpointer) (gulong) (0)))), on_paste, equation);
431}
432
433void
434math_equation_undo(MathEquation *equation)
435{
436 GList *link;
437 MathEquationState *state;
438
439 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_86
; if (equation != ((void*)0)) _g_boolean_var_86 = 1; else _g_boolean_var_86
= 0; _g_boolean_var_86; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
440
441 if (!equation->priv->undo_stack) {
442 math_equation_set_status(equation,
443 /* Error shown when trying to undo with no undo history */
444 _("No undo history")dcgettext (((void*)0), "No undo history", 5));
445 return;
446 }
447
448 link = equation->priv->undo_stack;
449 equation->priv->undo_stack = g_list_remove_link(equation->priv->undo_stack, link);
450 state = link->data;
451 g_list_free(link);
452
453 equation->priv->redo_stack = g_list_prepend(equation->priv->redo_stack, get_current_state(equation));
454
455 apply_state(equation, state);
456 free_state(state);
457}
458
459void
460math_equation_redo(MathEquation *equation)
461{
462 GList *link;
463 MathEquationState *state;
464
465 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_87
; if (equation != ((void*)0)) _g_boolean_var_87 = 1; else _g_boolean_var_87
= 0; _g_boolean_var_87; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
466
467 if (!equation->priv->redo_stack) {
468 math_equation_set_status(equation,
469 /* Error shown when trying to redo with no redo history */
470 _("No redo history")dcgettext (((void*)0), "No redo history", 5));
471 return;
472 }
473
474 link = equation->priv->redo_stack;
475 equation->priv->redo_stack = g_list_remove_link(equation->priv->redo_stack, link);
476 state = link->data;
477 g_list_free(link);
478
479 equation->priv->undo_stack = g_list_prepend(equation->priv->undo_stack, get_current_state(equation));
480
481 apply_state(equation, state);
482 free_state(state);
483}
484
485gunichar
486math_equation_get_digit_text(MathEquation *equation, guint digit)
487{
488 g_return_val_if_fail(equation != NULL, '?')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_88
; if (equation != ((void*)0)) _g_boolean_var_88 = 1; else _g_boolean_var_88
= 0; _g_boolean_var_88; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return ('?'); } } while (0)
;
489 g_return_val_if_fail(digit < 16, '?')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_89
; if (digit < 16) _g_boolean_var_89 = 1; else _g_boolean_var_89
= 0; _g_boolean_var_89; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "digit < 16");
return ('?'); } } while (0)
;
490
491 return equation->priv->digits[digit];
492}
493
494void
495math_equation_set_accuracy(MathEquation *equation, gint accuracy)
496{
497 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_90
; if (equation != ((void*)0)) _g_boolean_var_90 = 1; else _g_boolean_var_90
= 0; _g_boolean_var_90; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
498
499 if (mp_serializer_get_trailing_digits(equation->priv->serializer) == accuracy)
500 return;
501 mp_serializer_set_trailing_digits(equation->priv->serializer, accuracy);
502 reformat_display(equation);
503 g_object_notify(G_OBJECT(equation)((((GObject*) (void *) ((equation))))), "accuracy");
504}
505
506gint
507math_equation_get_accuracy(MathEquation *equation)
508{
509 g_return_val_if_fail(equation != NULL, 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_91
; if (equation != ((void*)0)) _g_boolean_var_91 = 1; else _g_boolean_var_91
= 0; _g_boolean_var_91; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return (0); } } while (0)
;
510
511 return mp_serializer_get_trailing_digits(equation->priv->serializer);
512}
513
514void
515math_equation_set_show_thousands_separators(MathEquation *equation, gboolean visible)
516{
517 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_92
; if (equation != ((void*)0)) _g_boolean_var_92 = 1; else _g_boolean_var_92
= 0; _g_boolean_var_92; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
518
519 if (mp_serializer_get_show_thousands_separators(equation->priv->serializer) == visible)
520 return;
521
522 mp_serializer_set_show_thousands_separators(equation->priv->serializer, visible);
523 reformat_display(equation);
524 g_object_notify(G_OBJECT(equation)((((GObject*) (void *) ((equation))))), "show-thousands-separators");
525}
526
527gboolean
528math_equation_get_show_thousands_separators(MathEquation *equation)
529{
530 g_return_val_if_fail(equation != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_93
; if (equation != ((void*)0)) _g_boolean_var_93 = 1; else _g_boolean_var_93
= 0; _g_boolean_var_93; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return ((0)); } } while (0)
;
531 return mp_serializer_get_show_thousands_separators(equation->priv->serializer);
532}
533
534void
535math_equation_set_show_trailing_zeroes(MathEquation *equation, gboolean visible)
536{
537 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_94
; if (equation != ((void*)0)) _g_boolean_var_94 = 1; else _g_boolean_var_94
= 0; _g_boolean_var_94; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
538
539 if (mp_serializer_get_show_trailing_zeroes(equation->priv->serializer) == visible)
540 return;
541
542 mp_serializer_set_show_trailing_zeroes(equation->priv->serializer, visible);
543 reformat_display(equation);
544 g_object_notify(G_OBJECT(equation)((((GObject*) (void *) ((equation))))), "show-trailing-zeroes");
545}
546
547gboolean
548math_equation_get_show_trailing_zeroes(MathEquation *equation)
549{
550 g_return_val_if_fail(equation != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_95
; if (equation != ((void*)0)) _g_boolean_var_95 = 1; else _g_boolean_var_95
= 0; _g_boolean_var_95; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return ((0)); } } while (0)
;
551 return mp_serializer_get_show_trailing_zeroes(equation->priv->serializer);
552}
553
554void
555math_equation_set_number_format(MathEquation *equation, MpDisplayFormat format)
556{
557 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_96
; if (equation != ((void*)0)) _g_boolean_var_96 = 1; else _g_boolean_var_96
= 0; _g_boolean_var_96; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
558
559 if (mp_serializer_get_number_format(equation->priv->serializer) == format)
560 return;
561
562 mp_serializer_set_number_format(equation->priv->serializer, format);
563 reformat_display(equation);
564 g_object_notify(G_OBJECT(equation)((((GObject*) (void *) ((equation))))), "number-format");
565}
566
567MpDisplayFormat
568math_equation_get_number_format(MathEquation *equation)
569{
570 g_return_val_if_fail(equation != NULL, MP_DISPLAY_FORMAT_AUTOMATIC)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_97
; if (equation != ((void*)0)) _g_boolean_var_97 = 1; else _g_boolean_var_97
= 0; _g_boolean_var_97; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return (MP_DISPLAY_FORMAT_AUTOMATIC); } } while (0)
;
571 return mp_serializer_get_number_format(equation->priv->serializer);
572}
573
574void
575math_equation_set_base(MathEquation *equation, gint base)
576{
577 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_98
; if (equation != ((void*)0)) _g_boolean_var_98 = 1; else _g_boolean_var_98
= 0; _g_boolean_var_98; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
578
579 if (mp_serializer_get_base(equation->priv->serializer) == base)
580 return;
581
582 mp_serializer_set_base(equation->priv->serializer, base);
583 reformat_display(equation);
584 g_object_notify(G_OBJECT(equation)((((GObject*) (void *) ((equation))))), "base");
585}
586
587gint
588math_equation_get_base(MathEquation *equation)
589{
590 g_return_val_if_fail(equation != NULL, 10)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_99
; if (equation != ((void*)0)) _g_boolean_var_99 = 1; else _g_boolean_var_99
= 0; _g_boolean_var_99; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return (10); } } while (0)
;
591 return mp_serializer_get_base(equation->priv->serializer);
592}
593
594void
595math_equation_set_word_size(MathEquation *equation, gint word_size)
596{
597 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_100
; if (equation != ((void*)0)) _g_boolean_var_100 = 1; else _g_boolean_var_100
= 0; _g_boolean_var_100; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
598
599 if (equation->priv->word_size == word_size)
600 return;
601
602 equation->priv->word_size = word_size;
603 g_object_notify(G_OBJECT(equation)((((GObject*) (void *) ((equation))))), "word-size");
604}
605
606gint
607math_equation_get_word_size(MathEquation *equation)
608{
609 g_return_val_if_fail(equation != NULL, 64)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_101
; if (equation != ((void*)0)) _g_boolean_var_101 = 1; else _g_boolean_var_101
= 0; _g_boolean_var_101; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return (64); } } while (0)
;
610 return equation->priv->word_size;
611}
612
613void
614math_equation_set_angle_units(MathEquation *equation, MPAngleUnit angle_units)
615{
616 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_102
; if (equation != ((void*)0)) _g_boolean_var_102 = 1; else _g_boolean_var_102
= 0; _g_boolean_var_102; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
617
618 if (equation->priv->angle_units == angle_units)
619 return;
620
621 equation->priv->angle_units = angle_units;
622 g_object_notify(G_OBJECT(equation)((((GObject*) (void *) ((equation))))), "angle-units");
623}
624
625MPAngleUnit
626math_equation_get_angle_units(MathEquation *equation)
627{
628 g_return_val_if_fail(equation != NULL, MP_DEGREES)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_103
; if (equation != ((void*)0)) _g_boolean_var_103 = 1; else _g_boolean_var_103
= 0; _g_boolean_var_103; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return (MP_DEGREES); } } while (0)
;
629 return equation->priv->angle_units;
630}
631
632void
633math_equation_set_source_currency(MathEquation *equation, const gchar *currency)
634{
635 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_104
; if (equation != ((void*)0)) _g_boolean_var_104 = 1; else _g_boolean_var_104
= 0; _g_boolean_var_104; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
636 g_return_if_fail(currency != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_105
; if (currency != ((void*)0)) _g_boolean_var_105 = 1; else _g_boolean_var_105
= 0; _g_boolean_var_105; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "currency != NULL"
); return; } } while (0)
;
637
638 if (strcmp(equation->priv->source_currency, currency) == 0)
639 return;
640 g_free(equation->priv->source_currency);
641 equation->priv->source_currency = g_strdup(currency)g_strdup_inline (currency);
642 g_settings_set_string(g_settings_var, "source-currency",
643 math_equation_get_source_currency(equation));
644}
645
646const gchar *
647math_equation_get_source_currency(MathEquation *equation)
648{
649 g_return_val_if_fail(equation != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_106
; if (equation != ((void*)0)) _g_boolean_var_106 = 1; else _g_boolean_var_106
= 0; _g_boolean_var_106; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return (((void*)0)); } } while (0)
;
650 return equation->priv->source_currency;
651}
652
653void
654math_equation_set_target_currency(MathEquation *equation, const gchar *currency)
655{
656 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_107
; if (equation != ((void*)0)) _g_boolean_var_107 = 1; else _g_boolean_var_107
= 0; _g_boolean_var_107; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
657 g_return_if_fail(currency != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_108
; if (currency != ((void*)0)) _g_boolean_var_108 = 1; else _g_boolean_var_108
= 0; _g_boolean_var_108; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "currency != NULL"
); return; } } while (0)
;
658
659 if (strcmp(equation->priv->target_currency, currency) == 0)
660 return;
661 g_free(equation->priv->target_currency);
662 equation->priv->target_currency = g_strdup(currency)g_strdup_inline (currency);
663 g_settings_set_string(g_settings_var, "target-currency",
664 math_equation_get_target_currency(equation));
665}
666
667const gchar *
668math_equation_get_target_currency(MathEquation *equation)
669{
670 g_return_val_if_fail(equation != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_109
; if (equation != ((void*)0)) _g_boolean_var_109 = 1; else _g_boolean_var_109
= 0; _g_boolean_var_109; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return (((void*)0)); } } while (0)
;
671 return equation->priv->target_currency;
672}
673
674void
675math_equation_set_source_units(MathEquation *equation, const gchar *units)
676{
677 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_110
; if (equation != ((void*)0)) _g_boolean_var_110 = 1; else _g_boolean_var_110
= 0; _g_boolean_var_110; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
678 g_return_if_fail(units != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_111
; if (units != ((void*)0)) _g_boolean_var_111 = 1; else _g_boolean_var_111
= 0; _g_boolean_var_111; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "units != NULL");
return; } } while (0)
;
679
680 if (strcmp(equation->priv->source_units, units) == 0)
681 return;
682
683 g_free(equation->priv->source_units);
684 equation->priv->source_units = g_strdup(units)g_strdup_inline (units);
685 g_settings_set_string(g_settings_var, "source-units",
686 math_equation_get_source_units(equation));
687}
688
689const gchar *
690math_equation_get_source_units(MathEquation *equation)
691{
692 g_return_val_if_fail(equation != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_112
; if (equation != ((void*)0)) _g_boolean_var_112 = 1; else _g_boolean_var_112
= 0; _g_boolean_var_112; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return (((void*)0)); } } while (0)
;
693 return equation->priv->source_units;
694}
695
696void
697math_equation_set_target_units(MathEquation *equation, const gchar *units)
698{
699 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_113
; if (equation != ((void*)0)) _g_boolean_var_113 = 1; else _g_boolean_var_113
= 0; _g_boolean_var_113; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
700 g_return_if_fail(units != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_114
; if (units != ((void*)0)) _g_boolean_var_114 = 1; else _g_boolean_var_114
= 0; _g_boolean_var_114; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "units != NULL");
return; } } while (0)
;
701
702 if (strcmp(equation->priv->target_units, units) == 0)
703 return;
704
705 g_free(equation->priv->target_units);
706 equation->priv->target_units = g_strdup(units)g_strdup_inline (units);
707 g_settings_set_string(g_settings_var, "target-units",
708 math_equation_get_target_units(equation));
709}
710
711const gchar *
712math_equation_get_target_units(MathEquation *equation)
713{
714 g_return_val_if_fail(equation != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_115
; if (equation != ((void*)0)) _g_boolean_var_115 = 1; else _g_boolean_var_115
= 0; _g_boolean_var_115; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return (((void*)0)); } } while (0)
;
715 return equation->priv->target_units;
716}
717
718void
719math_equation_set_status(MathEquation *equation, const gchar *status)
720{
721 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_116
; if (equation != ((void*)0)) _g_boolean_var_116 = 1; else _g_boolean_var_116
= 0; _g_boolean_var_116; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
722 g_return_if_fail(status != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_117
; if (status != ((void*)0)) _g_boolean_var_117 = 1; else _g_boolean_var_117
= 0; _g_boolean_var_117; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "status != NULL")
; return; } } while (0)
;
723
724 if (strcmp(equation->priv->state.status, status) == 0)
725 return;
726
727 g_free(equation->priv->state.status);
728 equation->priv->state.status = g_strdup(status)g_strdup_inline (status);
729 g_object_notify(G_OBJECT(equation)((((GObject*) (void *) ((equation))))), "status");
730}
731
732const gchar *
733math_equation_get_status(MathEquation *equation)
734{
735 g_return_val_if_fail(equation != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_118
; if (equation != ((void*)0)) _g_boolean_var_118 = 1; else _g_boolean_var_118
= 0; _g_boolean_var_118; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return (((void*)0)); } } while (0)
;
736 return equation->priv->state.status;
737}
738
739gboolean
740math_equation_is_empty(MathEquation *equation)
741{
742 g_return_val_if_fail(equation != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_119
; if (equation != ((void*)0)) _g_boolean_var_119 = 1; else _g_boolean_var_119
= 0; _g_boolean_var_119; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return ((0)); } } while (0)
;
743 return gtk_text_buffer_get_char_count(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation)))))) == 0;
744}
745
746gboolean
747math_equation_is_result(MathEquation *equation)
748{
749 char *text;
750 gboolean result;
751
752 g_return_val_if_fail(equation != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_120
; if (equation != ((void*)0)) _g_boolean_var_120 = 1; else _g_boolean_var_120
= 0; _g_boolean_var_120; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return ((0)); } } while (0)
;
753
754 text = math_equation_get_equation(equation);
755 result = strcmp(text, "ans") == 0;
756 g_free(text);
757
758 return result;
759}
760
761gchar *
762math_equation_get_display(MathEquation *equation)
763{
764 GtkTextIter start, end;
765
766 g_return_val_if_fail(equation != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_121
; if (equation != ((void*)0)) _g_boolean_var_121 = 1; else _g_boolean_var_121
= 0; _g_boolean_var_121; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return (((void*)0)); } } while (0)
;
767
768 gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &start, &end);
769 return gtk_text_buffer_get_text(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &start, &end, FALSE(0));
770}
771
772gchar *
773math_equation_get_equation(MathEquation *equation)
774{
775 gchar *text;
776 GString *eq_text;
777 gint ans_start = -1, ans_end = -1, offset;
778 const gchar *read_iter;
779 gboolean last_is_digit = FALSE(0);
780
781 g_return_val_if_fail(equation != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_122
; if (equation != ((void*)0)) _g_boolean_var_122 = 1; else _g_boolean_var_122
= 0; _g_boolean_var_122; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return (((void*)0)); } } while (0)
;
782
783 text = math_equation_get_display(equation);
784 eq_text = g_string_sized_new(strlen(text));
785
786 if (equation->priv->ans_start)
787 get_ans_offsets(equation, &ans_start, &ans_end);
788
789 for (read_iter = text, offset = 0; *read_iter != '\0'; read_iter = g_utf8_next_char(read_iter)(char *)((read_iter) + g_utf8_skip[*(const guchar *)(read_iter
)])
, offset++) {
790 gunichar c;
791 gboolean is_digit, next_is_digit;
792
793 c = g_utf8_get_char(read_iter);
794 is_digit = g_unichar_isdigit(c);
795 next_is_digit = g_unichar_isdigit(g_utf8_get_char(g_utf8_next_char(read_iter)(char *)((read_iter) + g_utf8_skip[*(const guchar *)(read_iter
)])
));
796
797 /* Replace ans text with variable */
798 if (offset == ans_start) {
799 g_string_append(eq_text, "ans")(__builtin_constant_p ("ans") ? __extension__ ({ const char *
const __val = ("ans"); g_string_append_len_inline (eq_text, __val
, (__builtin_expect (__extension__ ({ int _g_boolean_var_123;
if (__val != ((void*)0)) _g_boolean_var_123 = 1; else _g_boolean_var_123
= 0; _g_boolean_var_123; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(eq_text, "ans", (gssize) -1))
;
800 read_iter = g_utf8_offset_to_pointer(read_iter, ans_end - ans_start - 1);
801 offset += ans_end - ans_start - 1;
802 is_digit = FALSE(0);
Value stored to 'is_digit' is never read
803 continue;
804 }
805
806 /* Ignore thousands separators */
807 if (c == mp_serializer_get_thousands_separator(equation->priv->serializer) && last_is_digit && next_is_digit)
808 ;
809 /* Substitute radix character */
810 else if (c == mp_serializer_get_radix(equation->priv->serializer) && (last_is_digit || next_is_digit))
811 g_string_append_unichar(eq_text, '.');
812 else
813 g_string_append_unichar(eq_text, c);
814
815 last_is_digit = is_digit;
816 }
817 g_free(text);
818
819 text = eq_text->str;
820 g_string_free(eq_text, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((eq_text
), ((0))) : g_string_free_and_steal (eq_text)) : (g_string_free
) ((eq_text), ((0))))
;
821
822 return text;
823}
824
825gboolean
826math_equation_get_number(MathEquation *equation, MPNumber *z)
827{
828 gchar *text;
829 gboolean result;
830
831 g_return_val_if_fail(equation != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_124
; if (equation != ((void*)0)) _g_boolean_var_124 = 1; else _g_boolean_var_124
= 0; _g_boolean_var_124; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return ((0)); } } while (0)
;
832 g_return_val_if_fail(z != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_125
; if (z != ((void*)0)) _g_boolean_var_125 = 1; else _g_boolean_var_125
= 0; _g_boolean_var_125; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "z != NULL"); return
((0)); } } while (0)
;
833
834 if (math_equation_is_result(equation)) {
835 mp_set_from_mp(math_equation_get_answer(equation), z);
836 return TRUE(!(0));
837 }
838 else {
839 text = math_equation_get_equation(equation);
840 result = !mp_serializer_from_string(equation->priv->serializer, text, z);
841 g_free(text);
842 return result;
843 }
844}
845
846MpSerializer *
847math_equation_get_serializer(MathEquation *equation)
848{
849 g_return_val_if_fail(equation != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_126
; if (equation != ((void*)0)) _g_boolean_var_126 = 1; else _g_boolean_var_126
= 0; _g_boolean_var_126; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return (((void*)0)); } } while (0)
;
850 return equation->priv->serializer;
851}
852
853void
854math_equation_set_number_mode(MathEquation *equation, NumberMode mode)
855{
856 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_127
; if (equation != ((void*)0)) _g_boolean_var_127 = 1; else _g_boolean_var_127
= 0; _g_boolean_var_127; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
857
858 if (equation->priv->number_mode == mode)
859 return;
860
861 equation->priv->can_super_minus = mode == SUPERSCRIPT;
862
863 equation->priv->number_mode = mode;
864 g_object_notify(G_OBJECT(equation)((((GObject*) (void *) ((equation))))), "number-mode");
865}
866
867NumberMode
868math_equation_get_number_mode(MathEquation *equation)
869{
870 g_return_val_if_fail(equation != NULL, NORMAL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_128
; if (equation != ((void*)0)) _g_boolean_var_128 = 1; else _g_boolean_var_128
= 0; _g_boolean_var_128; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return (NORMAL); } } while (0)
;
871 return equation->priv->number_mode;
872}
873
874gboolean
875math_equation_in_solve(MathEquation *equation)
876{
877 g_return_val_if_fail(equation != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_129
; if (equation != ((void*)0)) _g_boolean_var_129 = 1; else _g_boolean_var_129
= 0; _g_boolean_var_129; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return ((0)); } } while (0)
;
878 return equation->priv->in_solve;
879}
880
881const MPNumber *
882math_equation_get_answer(MathEquation *equation)
883{
884 g_return_val_if_fail(equation != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_130
; if (equation != ((void*)0)) _g_boolean_var_130 = 1; else _g_boolean_var_130
= 0; _g_boolean_var_130; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return ((0)); } } while (0)
;
885 return &equation->priv->state.ans;
886}
887
888void
889math_equation_store(MathEquation *equation, const gchar *name)
890{
891 MPNumber t = mp_new();
892
893 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_131
; if (equation != ((void*)0)) _g_boolean_var_131 = 1; else _g_boolean_var_131
= 0; _g_boolean_var_131; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
894 g_return_if_fail(name != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_132
; if (name != ((void*)0)) _g_boolean_var_132 = 1; else _g_boolean_var_132
= 0; _g_boolean_var_132; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "name != NULL"); return
; } } while (0)
;
895
896 if (!math_equation_get_number(equation, &t))
897 math_equation_set_status(equation, _("No sane value to store")dcgettext (((void*)0), "No sane value to store", 5));
898 else
899 math_variables_set(equation->priv->variables, name, &t);
900 mp_clear(&t);
901}
902
903void
904math_equation_recall(MathEquation *equation, const gchar *name)
905{
906 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_133
; if (equation != ((void*)0)) _g_boolean_var_133 = 1; else _g_boolean_var_133
= 0; _g_boolean_var_133; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
907 g_return_if_fail(name != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_134
; if (name != ((void*)0)) _g_boolean_var_134 = 1; else _g_boolean_var_134
= 0; _g_boolean_var_134; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "name != NULL"); return
; } } while (0)
;
908 math_equation_insert(equation, name);
909}
910
911void
912math_equation_set(MathEquation *equation, const gchar *text)
913{
914 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_135
; if (equation != ((void*)0)) _g_boolean_var_135 = 1; else _g_boolean_var_135
= 0; _g_boolean_var_135; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
915 g_return_if_fail(text != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_136
; if (text != ((void*)0)) _g_boolean_var_136 = 1; else _g_boolean_var_136
= 0; _g_boolean_var_136; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "text != NULL"); return
; } } while (0)
;
916 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), text, -1);
917 clear_ans(equation, FALSE(0));
918}
919
920static void
921math_equation_set_with_history(MathEquation *equation, const gchar *text)
922{
923 MathEquationState *state;
924 MPNumber x = mp_new();
925
926 math_equation_get_number(equation, &x);
927 math_equation_set(equation, text);
928
929 /* Notify history */
930 state = get_current_state(equation);
931 g_signal_emit_by_name(equation, "history", state->expression, &x);
932
933 free_state(state);
934 mp_clear(&x);
935}
936
937void
938math_equation_set_number(MathEquation *equation, const MPNumber *x)
939{
940 char *text;
941 GtkTextIter start, end;
942 MathEquationState *state;
943
944 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_137
; if (equation != ((void*)0)) _g_boolean_var_137 = 1; else _g_boolean_var_137
= 0; _g_boolean_var_137; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
945 g_return_if_fail(x != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_138
; if (x != ((void*)0)) _g_boolean_var_138 = 1; else _g_boolean_var_138
= 0; _g_boolean_var_138; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "x != NULL"); return
; } } while (0)
;
946
947 /* Notify history */
948 state = get_current_state(equation);
949 g_signal_emit_by_name(equation, "history", state->expression, x);
950
951 /* Show the number in the user chosen format */
952 text = mp_serializer_to_string(equation->priv->serializer, x);
953 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), text, -1);
954 mp_set_from_mp(x, &equation->priv->state.ans);
955
956 /* Mark this text as the answer variable */
957 gtk_text_buffer_get_bounds(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &start, &end);
958 clear_ans(equation, FALSE(0));
959 equation->priv->ans_start = gtk_text_buffer_create_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), NULL((void*)0), &start, FALSE(0));
960 equation->priv->ans_end = gtk_text_buffer_create_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), NULL((void*)0), &end, TRUE(!(0)));
961 gtk_text_buffer_apply_tag(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), equation->priv->ans_tag, &start, &end);
962
963 g_object_notify(G_OBJECT(equation)((((GObject*) (void *) ((equation))))), "display");
964
965 g_free(text);
966 free_state(state);
967}
968
969void
970math_equation_insert(MathEquation *equation, const gchar *text)
971{
972 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_139
; if (equation != ((void*)0)) _g_boolean_var_139 = 1; else _g_boolean_var_139
= 0; _g_boolean_var_139; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
973 g_return_if_fail(text != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_140
; if (text != ((void*)0)) _g_boolean_var_140 = 1; else _g_boolean_var_140
= 0; _g_boolean_var_140; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "text != NULL"); return
; } } while (0)
;
974
975 /* Replace ** with ^ (not on all keyboards) */
976 if (!gtk_text_buffer_get_has_selection(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation)))))) &&
977 strcmp(text, "×") == 0 && equation->priv->state.entered_multiply) {
978 GtkTextIter iter;
979
980 gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &iter, gtk_text_buffer_get_insert(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation)))))));
981 gtk_text_buffer_backspace(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &iter, TRUE(!(0)), TRUE(!(0)));
982 gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), "^", -1);
983 return;
984 }
985
986 /* Can't enter superscript minus after entering digits */
987 if (strstr("⁰¹²³⁴⁵⁶⁷⁸⁹", text) != NULL((void*)0) || strcmp("⁻", text) == 0)
988 equation->priv->can_super_minus = FALSE(0);
989
990 /* Disable super/subscript mode when finished entering */
991 if (strstr("⁻⁰¹²³⁴⁵⁶⁷⁸⁹₀₁₂₃₄₅₆₇₈₉", text) == NULL((void*)0))
992 math_equation_set_number_mode(equation, NORMAL);
993
994 gtk_text_buffer_delete_selection(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), FALSE(0), FALSE(0));
995 gtk_text_buffer_insert_at_cursor(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), text, -1);
996}
997
998void
999math_equation_insert_digit(MathEquation *equation, guint digit)
1000{
1001 static const char *subscript_digits[] = {"₀", "₁", "₂", "₃", "₄", "₅", "₆", "₇", "₈", "₉", NULL((void*)0)};
1002 static const char *superscript_digits[] = {"⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹", NULL((void*)0)};
1003
1004 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_141
; if (equation != ((void*)0)) _g_boolean_var_141 = 1; else _g_boolean_var_141
= 0; _g_boolean_var_141; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
1005 g_return_if_fail(digit < 16)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_142
; if (digit < 16) _g_boolean_var_142 = 1; else _g_boolean_var_142
= 0; _g_boolean_var_142; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "digit < 16");
return; } } while (0)
;
1006
1007 if (equation->priv->number_mode == NORMAL || digit >= 10) {
1008 gchar buffer[7];
1009 gint len;
1010 len = g_unichar_to_utf8(math_equation_get_digit_text(equation, digit), buffer);
1011 buffer[len] = '\0';
1012 math_equation_insert(equation, buffer);
1013 }
1014 else if (equation->priv->number_mode == SUPERSCRIPT)
1015 math_equation_insert(equation, superscript_digits[digit]);
1016 else if (equation->priv->number_mode == SUBSCRIPT)
1017 math_equation_insert(equation, subscript_digits[digit]);
1018}
1019
1020void
1021math_equation_insert_numeric_point(MathEquation *equation)
1022{
1023 gchar buffer[7];
1024 gint len;
1025
1026 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_143
; if (equation != ((void*)0)) _g_boolean_var_143 = 1; else _g_boolean_var_143
= 0; _g_boolean_var_143; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
1027
1028 len = g_unichar_to_utf8(mp_serializer_get_radix(equation->priv->serializer), buffer);
1029 buffer[len] = '\0';
1030 math_equation_insert(equation, buffer);
1031}
1032
1033void
1034math_equation_insert_number(MathEquation *equation, const MPNumber *x)
1035{
1036 char *text;
1037
1038 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_144
; if (equation != ((void*)0)) _g_boolean_var_144 = 1; else _g_boolean_var_144
= 0; _g_boolean_var_144; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
1039 g_return_if_fail(x != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_145
; if (x != ((void*)0)) _g_boolean_var_145 = 1; else _g_boolean_var_145
= 0; _g_boolean_var_145; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "x != NULL"); return
; } } while (0)
;
1040
1041 text = mp_serializer_to_string(equation->priv->serializer, x);
1042 math_equation_insert(equation, text);
1043 g_free(text);
1044}
1045
1046void
1047math_equation_insert_exponent(MathEquation *equation)
1048{
1049 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_146
; if (equation != ((void*)0)) _g_boolean_var_146 = 1; else _g_boolean_var_146
= 0; _g_boolean_var_146; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
1050 math_equation_insert(equation, "×10");
1051 math_equation_set_number_mode(equation, SUPERSCRIPT);
1052}
1053
1054void
1055math_equation_insert_subtract(MathEquation *equation)
1056{
1057 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_147
; if (equation != ((void*)0)) _g_boolean_var_147 = 1; else _g_boolean_var_147
= 0; _g_boolean_var_147; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
1058 if (equation->priv->number_mode == SUPERSCRIPT && equation->priv->can_super_minus) {
1059 math_equation_insert(equation, "⁻");
1060 equation->priv->can_super_minus = FALSE(0);
1061 }
1062 else {
1063 math_equation_insert(equation, "−");
1064 math_equation_set_number_mode(equation, NORMAL);
1065 }
1066}
1067
1068static int
1069variable_is_defined(const char *name, void *data)
1070{
1071 MathEquation *equation = data;
1072 char *c, *lower_name;
1073
1074 lower_name = strdup(name);
1075 for (c = lower_name; *c; c++)
1076 *c = tolower(*c)(__extension__ ({ int __res; if (sizeof (*c) > 1) { if (__builtin_constant_p
(*c)) { int __c = (*c); __res = __c < -128 || __c > 255
? __c : (*__ctype_tolower_loc ())[__c]; } else __res = tolower
(*c); } else __res = (*__ctype_tolower_loc ())[(int) (*c)]; __res
; }))
;
1077
1078 if (strcmp(lower_name, "rand") == 0 ||
1079 strcmp(lower_name, "ans") == 0) {
1080 g_free(lower_name);
1081 return 1;
1082 }
1083 g_free(lower_name);
1084
1085 return math_variables_get(equation->priv->variables, name) != NULL((void*)0);
1086}
1087
1088static int
1089get_variable(const char *name, MPNumber *z, void *data)
1090{
1091 char *c, *lower_name;
1092 int result = 1;
1093 MathEquation *equation = data;
1094 MPNumber *t;
1095
1096 lower_name = strdup(name);
1097 for (c = lower_name; *c; c++)
1098 *c = tolower(*c)(__extension__ ({ int __res; if (sizeof (*c) > 1) { if (__builtin_constant_p
(*c)) { int __c = (*c); __res = __c < -128 || __c > 255
? __c : (*__ctype_tolower_loc ())[__c]; } else __res = tolower
(*c); } else __res = (*__ctype_tolower_loc ())[(int) (*c)]; __res
; }))
;
1099
1100 if (strcmp(lower_name, "rand") == 0)
1101 mp_set_from_random(z);
1102 else if (strcmp(lower_name, "ans") == 0)
1103 mp_set_from_mp(&equation->priv->state.ans, z);
1104 else {
1105 t = math_variables_get(equation->priv->variables, name);
1106 if (t)
1107 mp_set_from_mp(t, z);
1108 else
1109 result = 0;
1110 }
1111 free(lower_name);
1112
1113 return result;
1114}
1115
1116static void
1117set_variable(const char *name, const MPNumber *x, void *data)
1118{
1119 MathEquation *equation = data;
1120 /* FIXME: Don't allow writing to built-in variables, e.g. ans, rand, sin, ... */
1121 math_variables_set(equation->priv->variables, name, x);
1122}
1123
1124static int
1125convert(const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z, void *data)
1126{
1127 return unit_manager_convert_by_symbol(unit_manager_get_default(), x, x_units, z_units, z);
1128}
1129
1130static int
1131parse(MathEquation *equation, const char *text, MPNumber *z, char **error_token)
1132{
1133 MPEquationOptions options;
1134
1135 memset(&options, 0, sizeof(options));
1136 options.base = mp_serializer_get_base(equation->priv->serializer);
1137 options.wordlen = equation->priv->word_size;
1138 options.angle_units = equation->priv->angle_units;
1139 options.variable_is_defined = variable_is_defined;
1140 options.get_variable = get_variable;
1141 options.set_variable = set_variable;
1142 options.convert = convert;
1143 options.callback_data = equation;
1144
1145 return mp_equation_parse(text, &options, z, error_token);
1146}
1147
1148/*
1149 * Executed in separate thread. It is thus not a good idea to write to anything
1150 * in MathEquation but the async queue from here.
1151 */
1152static gpointer
1153math_equation_solve_real(gpointer data)
1154{
1155 MathEquation *equation = MATH_EQUATION(data)((((MathEquation*) (void *) ((data)))));
1156 SolveData *solvedata = g_slice_new0(SolveData)(SolveData *) (__extension__ ({ gsize __s = sizeof (SolveData
); gpointer __p; __p = g_slice_alloc (__s); memset (__p, 0, __s
); __p; }))
;
1157
1158 gint n_brackets = 0, result;
1159 gchar *c, *text, *error_token;
1160 GString *equation_text;
1161 MPNumber z = mp_new();
1162
1163 text = math_equation_get_equation(equation);
1164 equation_text = g_string_new(text);
1165 g_free(text);
1166 /* Count the number of brackets and automatically add missing closing brackets */
1167 for (c = equation_text->str; *c; c++) {
1168 if (*c == '(')
1169 n_brackets++;
1170 else if (*c == ')')
1171 n_brackets--;
1172 }
1173 while (n_brackets > 0) {
1174 g_string_append_c(equation_text, ')')g_string_append_c_inline (equation_text, ')');
1175 n_brackets--;
1176 }
1177
1178 result = parse(equation, equation_text->str, &z, &error_token);
1179 g_string_free(equation_text, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(equation_text), ((!(0)))) : g_string_free_and_steal (equation_text
)) : (g_string_free) ((equation_text), ((!(0)))))
;
1180
1181 switch (result) {
1182 case PARSER_ERR_NONE:
1183 solvedata->number_result = g_slice_new(MPNumber)((MPNumber*) g_slice_alloc (sizeof (MPNumber)));
1184 *solvedata->number_result = mp_new();
1185 mp_set_from_mp(&z, solvedata->number_result);
1186 break;
1187
1188 case PARSER_ERR_OVERFLOW:
1189 solvedata->error = g_strdup(/* Error displayed to user when they perform a bitwise operation on numbers greater than the current word */g_strdup_inline (dcgettext (((void*)0), "Overflow. Try a bigger word size"
, 5))
1190 _("Overflow. Try a bigger word size"))g_strdup_inline (dcgettext (((void*)0), "Overflow. Try a bigger word size"
, 5))
;
1191 break;
1192
1193 case PARSER_ERR_UNKNOWN_VARIABLE:
1194 solvedata->error = g_strdup_printf(/* Error displayed to user when they an unknown variable is entered */
1195 _("Unknown variable '%s'")dcgettext (((void*)0), "Unknown variable '%s'", 5), error_token);
1196 break;
1197
1198 case PARSER_ERR_UNKNOWN_FUNCTION:
1199 solvedata->error = g_strdup_printf(/* Error displayed to user when an unknown function is entered */
1200 _("Function '%s' is not defined")dcgettext (((void*)0), "Function '%s' is not defined", 5), error_token);
1201 break;
1202
1203 case PARSER_ERR_UNKNOWN_CONVERSION:
1204 solvedata->error = g_strdup(/* Error displayed to user when an conversion with unknown units is attempted */g_strdup_inline (dcgettext (((void*)0), "Unknown conversion",
5))
1205 _("Unknown conversion"))g_strdup_inline (dcgettext (((void*)0), "Unknown conversion",
5))
;
1206 break;
1207
1208 case PARSER_ERR_MP:
1209 if (mp_get_error())
1210 solvedata->error = g_strdup(mp_get_error())g_strdup_inline (mp_get_error());
1211 else if (error_token)
1212 solvedata->error = g_strdup_printf(/* Uncategorized error. Show error token to user*/
1213 _("Malformed expression at token '%s'")dcgettext (((void*)0), "Malformed expression at token '%s'", 5
)
, error_token);
1214 else
1215 solvedata->error = g_strdup (/* Unknown error. */g_strdup_inline (dcgettext (((void*)0), "Malformed expression"
, 5))
1216 _("Malformed expression"))g_strdup_inline (dcgettext (((void*)0), "Malformed expression"
, 5))
;
1217 break;
1218
1219 default:
1220 solvedata->error = g_strdup(/* Error displayed to user when they enter an invalid calculation */g_strdup_inline (dcgettext (((void*)0), "Malformed expression"
, 5))
1221 _("Malformed expression"))g_strdup_inline (dcgettext (((void*)0), "Malformed expression"
, 5))
;
1222 break;
1223 }
1224 g_async_queue_push(equation->priv->queue, solvedata);
1225 mp_clear(&z);
1226
1227 return NULL((void*)0);
1228}
1229
1230static gboolean
1231math_equation_show_in_progress(gpointer data)
1232{
1233 MathEquation *equation = MATH_EQUATION(data)((((MathEquation*) (void *) ((data)))));
1234 if (equation->priv->in_solve)
1235 math_equation_set_status(equation, _("Calculating")dcgettext (((void*)0), "Calculating", 5));
1236 return false0;
1237}
1238
1239static gboolean
1240math_equation_look_for_answer(gpointer data)
1241{
1242 MathEquation *equation = MATH_EQUATION(data)((((MathEquation*) (void *) ((data)))));
1243 SolveData *result = g_async_queue_try_pop(equation->priv->queue);
1244
1245 if (result == NULL((void*)0))
1246 return true1;
1247
1248 equation->priv->in_solve = false0;
1249
1250 if (!result->error)
1251 math_equation_set_status(equation, "");
1252
1253 if (result->error != NULL((void*)0)) {
1254 math_equation_set_status(equation, result->error);
1255 g_free(result->error);
1256 }
1257 else if (result->number_result != NULL((void*)0)) {
1258 math_equation_set_number(equation, result->number_result);
1259 mp_clear(result->number_result);
1260 g_slice_free(MPNumber, result->number_result)do { if (1) g_slice_free1 (sizeof (MPNumber), (result->number_result
)); else (void) ((MPNumber*) 0 == (result->number_result))
; } while (0)
;
1261 }
1262 else if (result->text_result != NULL((void*)0)) {
1263 math_equation_set_with_history(equation, result->text_result);
1264 g_free(result->text_result);
1265 }
1266 g_slice_free(SolveData, result)do { if (1) g_slice_free1 (sizeof (SolveData), (result)); else
(void) ((SolveData*) 0 == (result)); } while (0)
;
1267
1268 return false0;
1269}
1270
1271void
1272math_equation_solve(MathEquation *equation)
1273{
1274 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_148
; if (equation != ((void*)0)) _g_boolean_var_148 = 1; else _g_boolean_var_148
= 0; _g_boolean_var_148; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
1275
1276 // FIXME: should replace calculation or give error message
1277 if (equation->priv->in_solve)
1278 return;
1279
1280 if (math_equation_is_empty(equation))
1281 return;
1282
1283 /* If showing a result return to the equation that caused it */
1284 // FIXME: Result may not be here due to solve (i.e. the user may have entered "ans")
1285 if (math_equation_is_result(equation)) {
1286 math_equation_undo(equation);
1287 return;
1288 }
1289
1290 equation->priv->in_solve = true1;
1291
1292 math_equation_set_number_mode(equation, NORMAL);
1293 g_thread_new("", math_equation_solve_real, equation);
1294
1295 g_timeout_add(50, math_equation_look_for_answer, equation);
1296 g_timeout_add(100, math_equation_show_in_progress, equation);
1297}
1298
1299static gpointer
1300math_equation_factorize_real(gpointer data)
1301{
1302 GString *text;
1303 GList *factors, *factor, *next_factor;
1304 MPNumber x = mp_new();
1305 MathEquation *equation = MATH_EQUATION(data)((((MathEquation*) (void *) ((data)))));
1306 SolveData *result = g_slice_new0(SolveData)(SolveData *) (__extension__ ({ gsize __s = sizeof (SolveData
); gpointer __p; __p = g_slice_alloc (__s); memset (__p, 0, __s
); __p; }))
;
1307 MpDisplayFormat format = mp_serializer_get_number_format(equation->priv->serializer);
1308
1309 mp_serializer_set_number_format(equation->priv->serializer, MP_DISPLAY_FORMAT_FIXED);
1310 math_equation_get_number(equation, &x);
1311 factors = mp_factorize(&x);
1312
1313 text = g_string_new("");
1314
1315 int e = 1;
1316 for (factor = factors; factor != NULL((void*)0); factor = factor->next)
1317 {
1318 gchar *temp;
1319 MPNumber *n;
1320
1321 n = factor->data;
1322 next_factor = factor->next;
1323 if (next_factor != NULL((void*)0) && mp_compare(n, next_factor->data) == 0)
1324 {
1325 e++;
1326 continue;
1327 }
1328 temp = mp_serializer_to_string(equation->priv->serializer, n);
1329 g_string_append(text, temp)(__builtin_constant_p (temp) ? __extension__ ({ const char * const
__val = (temp); g_string_append_len_inline (text, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_149; if (__val != ((void
*)0)) _g_boolean_var_149 = 1; else _g_boolean_var_149 = 0; _g_boolean_var_149
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (text, temp, (gssize) -
1))
;
1330
1331 if (e > 1)
1332 {
1333 g_string_append(text, "^")(__builtin_constant_p ("^") ? __extension__ ({ const char * const
__val = ("^"); g_string_append_len_inline (text, __val, (__builtin_expect
(__extension__ ({ int _g_boolean_var_150; if (__val != ((void
*)0)) _g_boolean_var_150 = 1; else _g_boolean_var_150 = 0; _g_boolean_var_150
; }), 1)) ? (gssize) strlen (((__val) + !(__val))) : (gssize)
-1); }) : g_string_append_len_inline (text, "^", (gssize) -1
))
;
1334 g_string_append_printf(text, "%d", e);
1335 }
1336 if (factor->next)
1337 g_string_append(text, " × ")(__builtin_constant_p (" × ") ? __extension__ ({ const char *
const __val = (" × "); g_string_append_len_inline (text, __val
, (__builtin_expect (__extension__ ({ int _g_boolean_var_151;
if (__val != ((void*)0)) _g_boolean_var_151 = 1; else _g_boolean_var_151
= 0; _g_boolean_var_151; }), 1)) ? (gssize) strlen (((__val)
+ !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(text, " × ", (gssize) -1))
;
1338
1339 e = 1;
1340
1341 mp_clear(n);
1342 g_slice_free(MPNumber, n)do { if (1) g_slice_free1 (sizeof (MPNumber), (n)); else (void
) ((MPNumber*) 0 == (n)); } while (0)
;
1343 g_free(temp);
1344 }
1345 g_list_free(factors);
1346
1347 result->text_result = g_strndup(text->str, text->len);
1348 g_async_queue_push(equation->priv->queue, result);
1349 g_string_free(text, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(text), ((!(0)))) : g_string_free_and_steal (text)) : (g_string_free
) ((text), ((!(0)))))
;
1350 mp_clear(&x);
1351
1352 mp_serializer_set_number_format(equation->priv->serializer, format);
1353
1354 return NULL((void*)0);
1355}
1356
1357void
1358math_equation_factorize(MathEquation *equation)
1359{
1360 MPNumber x = mp_new();
1361
1362 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_152
; if (equation != ((void*)0)) _g_boolean_var_152 = 1; else _g_boolean_var_152
= 0; _g_boolean_var_152; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
1363
1364 // FIXME: should replace calculation or give error message
1365 if (equation->priv->in_solve)
1366 return;
1367
1368 if (!math_equation_get_number(equation, &x) || !mp_is_integer(&x)) {
1369 /* Error displayed when trying to factorize a non-integer value */
1370 math_equation_set_status(equation, _("Need an integer to factorize")dcgettext (((void*)0), "Need an integer to factorize", 5));
1371 mp_clear(&x);
1372 return;
1373 }
1374 mp_clear(&x);
1375 equation->priv->in_solve = true1;
1376
1377 g_thread_new("", math_equation_factorize_real, equation);
1378
1379 g_timeout_add(50, math_equation_look_for_answer, equation);
1380 g_timeout_add(100, math_equation_show_in_progress, equation);
1381}
1382
1383void
1384math_equation_delete(MathEquation *equation)
1385{
1386 gint cursor;
1387 GtkTextIter start, end;
1388
1389 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_153
; if (equation != ((void*)0)) _g_boolean_var_153 = 1; else _g_boolean_var_153
= 0; _g_boolean_var_153; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
1390
1391 g_object_get(G_OBJECT(equation)((((GObject*) (void *) ((equation))))), "cursor-position", &cursor, NULL((void*)0));
1392 if (cursor >= gtk_text_buffer_get_char_count(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation)))))))
1393 return;
1394
1395 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &start, cursor);
1396 gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &end, cursor+1);
1397 gtk_text_buffer_delete(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &start, &end);
1398}
1399
1400void
1401math_equation_backspace(MathEquation *equation)
1402{
1403 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_154
; if (equation != ((void*)0)) _g_boolean_var_154 = 1; else _g_boolean_var_154
= 0; _g_boolean_var_154; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
1404
1405 /* Can't delete empty display */
1406 if (math_equation_is_empty(equation))
1407 return;
1408
1409 if (gtk_text_buffer_get_has_selection(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation)))))))
1410 gtk_text_buffer_delete_selection(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), FALSE(0), FALSE(0));
1411 else {
1412 GtkTextIter iter;
1413 gtk_text_buffer_get_iter_at_mark(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &iter, gtk_text_buffer_get_insert(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation)))))));
1414 gtk_text_buffer_backspace(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), &iter, TRUE(!(0)), TRUE(!(0)));
1415 }
1416}
1417
1418void
1419math_equation_clear(MathEquation *equation)
1420{
1421 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_155
; if (equation != ((void*)0)) _g_boolean_var_155 = 1; else _g_boolean_var_155
= 0; _g_boolean_var_155; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
1422
1423 math_equation_set_number_mode(equation, NORMAL);
1424 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), "", -1);
1425 clear_ans(equation, FALSE(0));
1426}
1427
1428void
1429math_equation_shift(MathEquation *equation, gint count)
1430{
1431 MPNumber z = mp_new();
1432
1433 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_156
; if (equation != ((void*)0)) _g_boolean_var_156 = 1; else _g_boolean_var_156
= 0; _g_boolean_var_156; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
1434
1435 if (!math_equation_get_number(equation, &z)) {
1436 math_equation_set_status(equation,
1437 /* This message is displayed in the status bar when a bit
1438 shift operation is performed and the display does not contain a number */
1439 _("No sane value to bitwise shift")dcgettext (((void*)0), "No sane value to bitwise shift", 5));
1440 return;
1441 }
1442
1443 mp_shift(&z, count, &z);
1444 math_equation_set_number(equation, &z);
1445 mp_clear(&z);
1446}
1447
1448void
1449math_equation_toggle_bit(MathEquation *equation, guint bit)
1450{
1451 MPNumber x = mp_new();
1452 guint64 bits;
1453 gboolean result;
1454
1455 g_return_if_fail(equation != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_157
; if (equation != ((void*)0)) _g_boolean_var_157 = 1; else _g_boolean_var_157
= 0; _g_boolean_var_157; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "equation != NULL"
); return; } } while (0)
;
1456
1457 result = math_equation_get_number(equation, &x);
1458 if (result) {
1459 MPNumber max = mp_new();
1460 mp_set_from_unsigned_integer(G_MAXUINT64(0xffffffffffffffffUL), &max);
1461 if (mp_is_negative(&x) || mp_is_greater_than(&x, &max))
1462 result = FALSE(0);
1463 else
1464 bits = mp_to_unsigned_integer(&x);
1465 mp_clear(&max);
1466 }
1467
1468 if (!result) {
1469 math_equation_set_status(equation,
1470 /* Message displayed when cannot toggle bit in display*/
1471 _("Displayed value not an integer")dcgettext (((void*)0), "Displayed value not an integer", 5));
1472 mp_clear(&x);
1473 return;
1474 }
1475
1476 bits ^= (1LL << (63 - bit));
1477
1478 mp_set_from_unsigned_integer(bits, &x);
1479
1480 // FIXME: Only do this if in ans format, otherwise set text in same format as previous number
1481 math_equation_set_number(equation, &x);
1482 mp_clear(&x);
1483}
1484
1485static void
1486math_equation_set_property(GObject *object,
1487 guint prop_id,
1488 const GValue *value,
1489 GParamSpec *pspec)
1490{
1491 MathEquation *self;
1492
1493 self = MATH_EQUATION(object)((((MathEquation*) (void *) ((object)))));
1494
1495 switch (prop_id) {
1496 case PROP_STATUS:
1497 math_equation_set_status(self, g_value_get_string(value));
1498 break;
1499 case PROP_DISPLAY:
1500 math_equation_set(self, g_value_get_string(value));
1501 break;
1502 case PROP_NUMBER_MODE:
1503 math_equation_set_number_mode(self, g_value_get_int(value));
1504 break;
1505 case PROP_ACCURACY:
1506 math_equation_set_accuracy(self, g_value_get_int(value));
1507 break;
1508 case PROP_SHOW_THOUSANDS_SEPARATORS:
1509 math_equation_set_show_thousands_separators(self, g_value_get_boolean(value));
1510 break;
1511 case PROP_SHOW_TRAILING_ZEROES:
1512 math_equation_set_show_trailing_zeroes(self, g_value_get_boolean(value));
1513 break;
1514 case PROP_NUMBER_FORMAT:
1515 math_equation_set_number_format(self, g_value_get_int(value));
1516 break;
1517 case PROP_BASE:
1518 math_equation_set_base(self, g_value_get_int(value));
1519 break;
1520 case PROP_WORD_SIZE:
1521 math_equation_set_word_size(self, g_value_get_int(value));
1522 break;
1523 case PROP_ANGLE_UNITS:
1524 math_equation_set_angle_units(self, g_value_get_int(value));
1525 break;
1526 case PROP_SOURCE_CURRENCY:
1527 math_equation_set_source_currency(self, g_value_get_string(value));
1528 break;
1529 case PROP_TARGET_CURRENCY:
1530 math_equation_set_target_currency(self, g_value_get_string(value));
1531 break;
1532 case PROP_SOURCE_UNITS:
1533 math_equation_set_source_units(self, g_value_get_string(value));
1534 break;
1535 case PROP_TARGET_UNITS:
1536 math_equation_set_target_units(self, g_value_get_string(value));
1537 break;
1538 default:
1539 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "math-equation.c", 1539, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
1540 break;
1541 }
1542}
1543
1544static void
1545math_equation_get_property(GObject *object,
1546 guint prop_id,
1547 GValue *value,
1548 GParamSpec *pspec)
1549{
1550 MathEquation *self;
1551 gchar *text;
1552
1553 self = MATH_EQUATION(object)((((MathEquation*) (void *) ((object)))));
1554
1555 switch (prop_id) {
1556 case PROP_STATUS:
1557 g_value_set_string(value, self->priv->state.status);
1558 break;
1559 case PROP_DISPLAY:
1560 text = math_equation_get_display(self);
1561 g_value_set_string(value, text);
1562 g_free(text);
1563 break;
1564 case PROP_EQUATION:
1565 text = math_equation_get_equation(self);
1566 g_value_set_string(value, text);
1567 g_free(text);
1568 break;
1569 case PROP_NUMBER_MODE:
1570 g_value_set_enum(value, self->priv->number_mode);
1571 break;
1572 case PROP_ACCURACY:
1573 g_value_set_int(value, mp_serializer_get_trailing_digits(self->priv->serializer));
1574 break;
1575 case PROP_SHOW_THOUSANDS_SEPARATORS:
1576 g_value_set_boolean(value, mp_serializer_get_show_thousands_separators(self->priv->serializer));
1577 break;
1578 case PROP_SHOW_TRAILING_ZEROES:
1579 g_value_set_boolean(value, mp_serializer_get_show_trailing_zeroes(self->priv->serializer));
1580 break;
1581 case PROP_NUMBER_FORMAT:
1582 g_value_set_enum(value, mp_serializer_get_number_format(self->priv->serializer));
1583 break;
1584 case PROP_BASE:
1585 g_value_set_int(value, math_equation_get_base(self));
1586 break;
1587 case PROP_WORD_SIZE:
1588 g_value_set_int(value, self->priv->word_size);
1589 break;
1590 case PROP_ANGLE_UNITS:
1591 g_value_set_enum(value, self->priv->angle_units);
1592 break;
1593 case PROP_SOURCE_CURRENCY:
1594 g_value_set_string(value, self->priv->source_currency);
1595 break;
1596 case PROP_TARGET_CURRENCY:
1597 g_value_set_string(value, self->priv->target_currency);
1598 break;
1599 case PROP_SOURCE_UNITS:
1600 g_value_set_string(value, self->priv->source_units);
1601 break;
1602 case PROP_TARGET_UNITS:
1603 g_value_set_string(value, self->priv->target_units);
1604 break;
1605 case PROP_SERIALIZER:
1606 g_value_set_object(value, self->priv->serializer);
1607 break;
1608 default:
1609 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "math-equation.c", 1609, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
1610 break;
1611 }
1612}
1613
1614static void
1615math_equation_constructed(GObject *object)
1616{
1617 GtkTextBuffer *parent_class;
1618 parent_class = g_type_class_peek_parent(MATH_EQUATION_GET_CLASS(object)((((MathEquationClass*) (((GTypeInstance*) ((object)))->g_class
))))
);
1619 if (G_OBJECT_CLASS(parent_class)((((GObjectClass*) (void *) ((parent_class)))))->constructed)
1620 G_OBJECT_CLASS(parent_class)((((GObjectClass*) (void *) ((parent_class)))))->constructed(object);
1621
1622 MATH_EQUATION(object)((((MathEquation*) (void *) ((object)))))->priv->ans_tag = gtk_text_buffer_create_tag(GTK_TEXT_BUFFER(object)((((GtkTextBuffer*) (void *) ((object))))), NULL((void*)0), "weight", PANGO_WEIGHT_BOLD, NULL((void*)0));
1623}
1624
1625static void
1626math_equation_class_init(MathEquationClass *klass)
1627{
1628 static GEnumValue number_mode_values[] =
1629 {
1630 {NORMAL, "normal", "normal"},
1631 {SUPERSCRIPT, "superscript", "superscript"},
1632 {SUBSCRIPT, "subscript", "subscript"},
1633 {0, NULL((void*)0), NULL((void*)0)}
1634 };
1635 static GEnumValue angle_unit_values[] =
1636 {
1637 {MP_RADIANS, "radians", "radians"},
1638 {MP_DEGREES, "degrees", "degrees"},
1639 {MP_GRADIANS, "gradians", "gradians"},
1640 {0, NULL((void*)0), NULL((void*)0)}
1641 };
1642 GObjectClass *object_class = G_OBJECT_CLASS(klass)((((GObjectClass*) (void *) ((klass)))));
1643
1644 object_class->get_property = math_equation_get_property;
1645 object_class->set_property = math_equation_set_property;
1646 object_class->constructed = math_equation_constructed;
1647
1648 number_mode_type = g_enum_register_static("NumberMode", number_mode_values);
1649 number_format_type = math_mp_display_format_get_type();
1650 angle_unit_type = g_enum_register_static("AngleUnit", angle_unit_values);
1651
1652 g_object_class_install_property(object_class,
1653 PROP_STATUS,
1654 g_param_spec_string("status",
1655 "status",
1656 "Equation status",
1657 "",
1658 G_PARAM_READWRITE));
1659 g_object_class_install_property(object_class,
1660 PROP_DISPLAY,
1661 g_param_spec_string("display",
1662 "display",
1663 "Displayed equation text",
1664 "",
1665 G_PARAM_READWRITE));
1666 g_object_class_install_property(object_class,
1667 PROP_EQUATION,
1668 g_param_spec_string("equation",
1669 "equation",
1670 "Equation text",
1671 "",
1672 G_PARAM_READABLE));
1673 g_object_class_install_property(object_class,
1674 PROP_NUMBER_MODE,
1675 g_param_spec_enum("number-mode",
1676 "number-mode",
1677 "Input number mode",
1678 number_mode_type,
1679 NORMAL,
1680 G_PARAM_READWRITE));
1681 g_object_class_install_property(object_class,
1682 PROP_ACCURACY,
1683 g_param_spec_int("accuracy",
1684 "accuracy",
1685 "Display accuracy",
1686 0, 20, 9,
1687 G_PARAM_READWRITE));
1688 g_object_class_install_property(object_class,
1689 PROP_SHOW_THOUSANDS_SEPARATORS,
1690 g_param_spec_boolean("show-thousands-separators",
1691 "show-thousands-separators",
1692 "Show thousands separators",
1693 TRUE(!(0)),
1694 G_PARAM_READWRITE));
1695 g_object_class_install_property(object_class,
1696 PROP_SHOW_TRAILING_ZEROES,
1697 g_param_spec_boolean("show-trailing-zeroes",
1698 "show-trailing-zeroes",
1699 "Show trailing zeroes",
1700 FALSE(0),
1701 G_PARAM_READWRITE));
1702 g_object_class_install_property(object_class,
1703 PROP_NUMBER_FORMAT,
1704 g_param_spec_enum("number-format",
1705 "number-format",
1706 "Display format",
1707 number_format_type,
1708 MP_DISPLAY_FORMAT_FIXED,
1709 G_PARAM_READWRITE));
1710 g_object_class_install_property(object_class,
1711 PROP_BASE,
1712 g_param_spec_int("base",
1713 "base",
1714 "Default number base (derived from number-format)",
1715 2, 16, 10,
1716 G_PARAM_READWRITE));
1717 g_object_class_install_property(object_class,
1718 PROP_WORD_SIZE,
1719 g_param_spec_int("word-size",
1720 "word-size",
1721 "Word size in bits",
1722 8, 64, 64,
1723 G_PARAM_READWRITE));
1724 g_object_class_install_property(object_class,
1725 PROP_ANGLE_UNITS,
1726 g_param_spec_enum("angle-units",
1727 "angle-units",
1728 "Angle units",
1729 angle_unit_type,
1730 MP_DEGREES,
1731 G_PARAM_READWRITE));
1732 g_object_class_install_property(object_class,
1733 PROP_SOURCE_CURRENCY,
1734 g_param_spec_string("source-currency",
1735 "source-currency",
1736 "Source Currency",
1737 "",
1738 G_PARAM_READWRITE));
1739 g_object_class_install_property(object_class,
1740 PROP_TARGET_CURRENCY,
1741 g_param_spec_string("target-currency",
1742 "target-currency",
1743 "target Currency",
1744 "",
1745 G_PARAM_READWRITE));
1746 g_object_class_install_property(object_class,
1747 PROP_SOURCE_UNITS,
1748 g_param_spec_string("source-units",
1749 "source-units",
1750 "Source Units",
1751 "",
1752 G_PARAM_READWRITE));
1753 g_object_class_install_property(object_class,
1754 PROP_TARGET_UNITS,
1755 g_param_spec_string("target-units",
1756 "target-units",
1757 "target Units",
1758 "",
1759 G_PARAM_READWRITE));
1760 g_object_class_install_property(object_class,
1761 PROP_SERIALIZER,
1762 g_param_spec_object("serializer",
1763 "serializer",
1764 "Serializer",
1765 MP_TYPE_SERIALIZER(mp_serializer_get_type()),
1766 G_PARAM_READABLE));
1767
1768 GType param_types[2] = {G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_POINTER((GType) ((17) << (2)))};
1769 g_signal_newv("history",
1770 G_TYPE_FROM_CLASS(klass)(((GTypeClass*) (klass))->g_type),
1771 G_SIGNAL_RUN_LAST,
1772 0,
1773 NULL((void*)0),
1774 NULL((void*)0),
1775 NULL((void*)0),
1776 G_TYPE_NONE((GType) ((1) << (2))),
1777 2,
1778 param_types);
1779
1780 g_signal_new ("display-changed",
1781 G_TYPE_FROM_CLASS(klass)(((GTypeClass*) (klass))->g_type),
1782 G_SIGNAL_RUN_LAST,
1783 0,
1784 NULL((void*)0),
1785 NULL((void*)0),
1786 NULL((void*)0),
1787 G_TYPE_NONE((GType) ((1) << (2))),
1788 0,
1789 NULL((void*)0));
1790}
1791
1792static void
1793pre_insert_text_cb(MathEquation *equation,
1794 GtkTextIter *location,
1795 gchar *text,
1796 gint len,
1797 gpointer user_data)
1798{
1799 gunichar c;
1800 gint cursor;
1801
1802 if (equation->priv->in_reformat)
1803 return;
1804
1805 /* If following a delete then have already pushed undo stack (GtkTextBuffer
1806 doesn't indicate replace operations so we have to infer them) */
1807 if (!equation->priv->in_delete)
1808 math_equation_push_undo_stack(equation);
1809
1810 /* Clear result on next digit entered if cursor at end of line */
1811 c = g_utf8_get_char(text);
1812 g_object_get(G_OBJECT(equation)((((GObject*) (void *) ((equation))))), "cursor-position", &cursor, NULL((void*)0));
1813 if ((g_unichar_isdigit(c) || c == mp_serializer_get_radix(equation->priv->serializer)) &&
1814 math_equation_is_result(equation) &&
1815 cursor >= gtk_text_buffer_get_char_count(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))))) {
1816 gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), "", -1);
1817 clear_ans(equation, FALSE(0));
1818 gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(equation)((((GtkTextBuffer*) (void *) ((equation))))), location);
1819 }
1820
1821 if (equation->priv->ans_start) {
1822 gint ans_start, ans_end;
1823 gint offset;
1824
1825 offset = gtk_text_iter_get_offset(location);
1826 get_ans_offsets(equation, &ans_start, &ans_end);
1827
1828 /* Inserted inside or right before ans */
1829 if (offset >= ans_start && offset < ans_end)
1830 clear_ans(equation, TRUE(!(0)));
1831 }
1832}
1833
1834static gboolean
1835on_delete(MathEquation *equation)
1836{
1837 equation->priv->in_delete = FALSE(0);
1838 return FALSE(0);
1839}
1840
1841static void
1842pre_delete_range_cb(MathEquation *equation,
1843 GtkTextIter *start,
1844 GtkTextIter *end,
1845 gpointer user_data)
1846{
1847 if (equation->priv->in_reformat)
1848 return;
1849
1850 math_equation_push_undo_stack(equation);
1851
1852 equation->priv->in_delete = TRUE(!(0));
1853 g_idle_add((GSourceFunc)on_delete, equation);
1854
1855 if (equation->priv->ans_start) {
1856 gint ans_start, ans_end;
1857 gint start_offset, end_offset;
1858
1859 start_offset = gtk_text_iter_get_offset(start);
1860 end_offset = gtk_text_iter_get_offset(end);
1861 get_ans_offsets(equation, &ans_start, &ans_end);
1862
1863 /* Deleted part of ans */
1864 if (start_offset < ans_end && end_offset > ans_start)
1865 clear_ans(equation, TRUE(!(0)));
1866 }
1867}
1868
1869static void
1870insert_text_cb(MathEquation *equation,
1871 GtkTextIter *location,
1872 gchar *text,
1873 gint len,
1874 gpointer user_data)
1875{
1876 if (equation->priv->in_reformat)
1877 return;
1878
1879 equation->priv->state.entered_multiply = strcmp(text, "×") == 0;
1880
1881 /* Update thousands separators */
1882 reformat_separators(equation);
1883
1884 g_object_notify(G_OBJECT(equation)((((GObject*) (void *) ((equation))))), "display");
1885}
1886
1887static void
1888delete_range_cb(MathEquation *equation,
1889 GtkTextIter *start,
1890 GtkTextIter *end,
1891 gpointer user_data)
1892{
1893 if (equation->priv->in_reformat)
1894 return;
1895
1896 equation->priv->state.entered_multiply = FALSE(0);
1897
1898 /* Update thousands separators */
1899 reformat_separators(equation);
1900
1901 // FIXME: A replace will emit this both for delete-range and insert-text, can it be avoided?
1902 g_object_notify(G_OBJECT(equation)((((GObject*) (void *) ((equation))))), "display");
1903}
1904
1905static void
1906math_equation_init(MathEquation *equation)
1907{
1908 /* Digits localized for the given language */
1909 const char *digit_values = _("0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F")dcgettext (((void*)0), "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F", 5);
1910 const char *default_digits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
1911 gchar **digits;
1912 /* Default to using untranslated digits, this is because it doesn't make sense in most languages and we need to make this optional.
1913 * See https://bugzilla.gnome.org/show_bug.cgi?id=632661 */
1914 gboolean use_default_digits = TRUE(!(0));
1915 int i;
1916
1917 equation->priv = math_equation_get_instance_private (equation);
1918
1919 g_signal_connect(equation, "insert-text", G_CALLBACK(pre_insert_text_cb), equation)g_signal_connect_data ((equation), ("insert-text"), (((GCallback
) (pre_insert_text_cb))), (equation), ((void*)0), (GConnectFlags
) 0)
;
1920 g_signal_connect(equation, "delete-range", G_CALLBACK(pre_delete_range_cb), equation)g_signal_connect_data ((equation), ("delete-range"), (((GCallback
) (pre_delete_range_cb))), (equation), ((void*)0), (GConnectFlags
) 0)
;
1921 g_signal_connect_after(equation, "insert-text", G_CALLBACK(insert_text_cb), equation)g_signal_connect_data ((equation), ("insert-text"), (((GCallback
) (insert_text_cb))), (equation), ((void*)0), G_CONNECT_AFTER
)
;
1922 g_signal_connect_after(equation, "delete-range", G_CALLBACK(delete_range_cb), equation)g_signal_connect_data ((equation), ("delete-range"), (((GCallback
) (delete_range_cb))), (equation), ((void*)0), G_CONNECT_AFTER
)
;
1923
1924 digits = g_strsplit(digit_values, ",", -1);
1925 for (i = 0; i < 16; i++) {
1926 if (use_default_digits || digits[i] == NULL((void*)0)) {
1927 use_default_digits = TRUE(!(0));
1928 equation->priv->digits[i] = g_utf8_get_char(default_digits[i]);
1929 }
1930 else
1931 equation->priv->digits[i] = g_utf8_get_char(digits[i]);
1932 }
1933 g_strfreev(digits);
1934
1935 equation->priv->variables = math_variables_new();
1936
1937 equation->priv->state.ans = mp_new();
1938 equation->priv->state.status = g_strdup("")g_strdup_inline ("");
1939 equation->priv->word_size = 32;
1940 equation->priv->angle_units = MP_DEGREES;
1941 // FIXME: Pick based on locale
1942 equation->priv->source_currency = g_strdup("")g_strdup_inline ("");
1943 equation->priv->target_currency = g_strdup("")g_strdup_inline ("");
1944 equation->priv->source_units = g_strdup("")g_strdup_inline ("");
1945 equation->priv->target_units = g_strdup("")g_strdup_inline ("");
1946 equation->priv->serializer = mp_serializer_new(MP_DISPLAY_FORMAT_AUTOMATIC, 10, 9);
1947 equation->priv->queue = g_async_queue_new();
1948
1949 mp_set_from_integer(0, &equation->priv->state.ans);
1950}
diff --git a/2024-07-10-100902-3667-1@fe495df3ec39_master/report-b1189a.html b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-b1189a.html new file mode 100644 index 0000000..8c370c3 --- /dev/null +++ b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-b1189a.html @@ -0,0 +1,1270 @@ + + + +lexer.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:lexer.c
Warning:line 125, column 13
Although the value stored to 'type' is used in the enclosing expression, the value is never actually read from 'type'
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name lexer.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D LOCALE_DIR="/usr/local/share/locale" -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/atk-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/gio-unix-2.0 -D WITH_GZFILEOP -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-07-10-100902-3667-1 -x c lexer.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1#include <stdlib.h>
2#include <assert.h>
3#include <string.h>
4
5#include "lexer.h"
6#include "parserfunc.h"
7#include "mp-equation.h"
8
9static gboolean
10l_check_if_function(LexerState* state)
11{
12 gchar* name = pl_get_marked_substring(state->prelexer);
13 if(!state->parent->function_is_defined)
14 {
15 free(name);
16 return FALSE(0);
17 }
18 if ((*(state->parent->function_is_defined))(state->parent, name))
19 {
20 free(name);
21 return TRUE(!(0));
22 }
23 else
24 {
25 free(name);
26 return FALSE(0);
27 }
28}
29
30static gboolean
31l_check_if_number(LexerState* state)
32{
33 MPNumber tmp = mp_new();
34 int count = 0;
35 gchar* text = pl_get_marked_substring(state->prelexer);
36 if(mp_set_from_string(text, state->parent->options->base, &tmp) == 0)
37 {
38 free(text);
39 mp_clear(&tmp);
40 return TRUE(!(0));
41 }
42 else
43 {
44 /* Try to rollback several characters to see, if that yeilds any number. */
45 while(strlen (text) > 0)
46 {
47 if(mp_set_from_string(text, state->parent->options->base, &tmp) == 0)
48 {
49 free(text);
50 mp_clear(&tmp);
51 return TRUE(!(0));
52 }
53 free(text);
54 count++;
55 pl_roll_back(state->prelexer);
56 text = pl_get_marked_substring(state->prelexer);
57 }
58 /* Undo all rollbacks. */
59 while(count--)
60 pl_get_next_token (state->prelexer);
61 free(text);
62 mp_clear(&tmp);
63 return FALSE(0);
64 }
65}
66
67/* Insert generated token to the LexerState structure. */
68static LexerToken*
69l_insert_token(LexerState* state, const LexerTokenType type)
70{
71 state->tokens = (LexerToken *) realloc(state->tokens, (state->token_count + 1) * sizeof(LexerToken));
72 assert(state->tokens != NULL)((void) sizeof ((state->tokens != ((void*)0)) ? 1 : 0), __extension__
({ if (state->tokens != ((void*)0)) ; else __assert_fail (
"state->tokens != NULL", "lexer.c", 72, __extension__ __PRETTY_FUNCTION__
); }))
;
73 state->tokens[state->token_count].string = pl_get_marked_substring(state->prelexer);
74 state->tokens[state->token_count].start_index = state->prelexer->mark_index;
75 state->tokens[state->token_count].end_index = state->prelexer->next_index;
76 state->tokens[state->token_count].token_type = type;
77 state->token_count++;
78 return &state->tokens[state->token_count - 1];
79}
80
81/* Generates next token from pre-lexer stream and call l_insert_token() to insert it at the end. */
82static LexerToken*
83l_insert_next_token(LexerState* lstate)
84{
85 PreLexerState* state = lstate->prelexer;
86 LexerTokenType type;
87 gchar* tmp;
88 pl_set_marker(state);
89 /* Ignore all blank spaces. :) */
90 while((type = pl_get_next_token(state)) == PL_SKIP)
91 /* Set marker. Beginning of new token. */
92 pl_set_marker(state);
93 if(type == T_AND
94 ||type == T_OR
95 ||type == T_XOR
96 ||type == T_NOT
97 ||type == T_ADD
98 ||type == T_SUBTRACT
99 ||type == T_MULTIPLY
100 ||type == T_DIV
101 ||type == T_L_FLOOR
102 ||type == T_R_FLOOR
103 ||type == T_L_CEILING
104 ||type == T_R_CEILING
105 ||type == T_ROOT
106 ||type == T_ROOT_3
107 ||type == T_ROOT_4
108 ||type == T_ASSIGN
109 ||type == T_L_R_BRACKET
110 ||type == T_R_R_BRACKET
111 ||type == T_L_S_BRACKET
112 ||type == T_R_S_BRACKET
113 ||type == T_L_C_BRACKET
114 ||type == T_R_C_BRACKET
115 ||type == T_ABS
116 ||type == T_POWER
117 ||type == T_FACTORIAL
118 ||type == T_PERCENTAGE)
119 {
120 return l_insert_token(lstate, type);
121 }
122 /* [PL_SUPER_MINUS][PL_SUPER_DIGIT]+ */
123 if(type == PL_SUPER_MINUS)
124 {
125 if((type = pl_get_next_token(state)) != PL_SUPER_DIGIT)
Although the value stored to 'type' is used in the enclosing expression, the value is never actually read from 'type'
126 {
127 /* ERROR: expected PL_SUP_DIGIT */
128 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring (state));
129 free(tmp);
130 return l_insert_token(lstate, T_UNKNOWN);
131 }
132 /* Get all PL_SUPER_DIGITs. */
133 while (pl_get_next_token(state) == PL_SUPER_DIGIT);
134 pl_roll_back(state);
135 return l_insert_token(lstate, T_NSUP_NUMBER);
136 }
137 /* [PL_SUPER_DIGIT]+ */
138 if(type == PL_SUPER_DIGIT)
139 {
140 while(pl_get_next_token(state) == PL_SUPER_DIGIT);
141 pl_roll_back(state);
142 return l_insert_token(lstate, T_SUP_NUMBER);
143 }
144 /* [PL_SUB_DIGIT]+ */
145 if(type == PL_SUB_DIGIT)
146 {
147 while(pl_get_next_token(state) == PL_SUB_DIGIT);
148 pl_roll_back(state);
149 return l_insert_token(lstate, T_SUB_NUMBER);
150 }
151 /* [PL_FRACTION] */
152 if(type == PL_FRACTION)
153 {
154 return l_insert_token(lstate, T_NUMBER);
155 }
156 if(type == PL_DIGIT)
157 {
158 while((type = pl_get_next_token(state)) == PL_DIGIT);
159 if(type == PL_FRACTION)
160 {
161 return l_insert_token(lstate, T_NUMBER);
162 }
163 else if(type == PL_SUB_DIGIT)
164 {
165 while(pl_get_next_token(state) == PL_SUB_DIGIT);
166 pl_roll_back(state);
167 return l_insert_token(lstate, T_NUMBER);
168 }
169 else if(type == PL_DEGREE)
170 {
171 type = pl_get_next_token(state);
172 if(type == PL_DIGIT)
173 {
174 while((type = pl_get_next_token(state)) == PL_DIGIT);
175 if(type == PL_DECIMAL)
176 {
177 goto ANGLE_NUM_DM_STATE;
178 }
179 else if(type == PL_MINUTE)
180 {
181 type = pl_get_next_token(state);
182 if(type == PL_DIGIT)
183 {
184 while((type = pl_get_next_token(state)) == PL_DIGIT);
185 if(type == PL_DECIMAL)
186 {
187 goto ANGLE_NUM_DMS_STATE;
188 }
189 else if(type == PL_SECOND)
190 {
191 return l_insert_token(lstate, T_NUMBER);
192 }
193 else
194 {
195 /* ERROR: expected PL_SECOND */
196 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring (state));
197 free(tmp);
198 return l_insert_token(lstate, T_UNKNOWN);
199 }
200 }
201 else if(type == PL_DECIMAL)
202 {
203ANGLE_NUM_DMS_STATE:
204 if((type = pl_get_next_token (state)) != PL_DIGIT)
205 {
206 /* ERROR: expected PL_DIGIT */
207 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
208 free(tmp);
209 return l_insert_token(lstate, T_UNKNOWN);
210 }
211 while((type = pl_get_next_token(state)) == PL_DIGIT);
212 if(type == PL_SECOND)
213 {
214 return l_insert_token(lstate, T_NUMBER);
215 }
216 else
217 {
218 /* ERROR: expected PL_SECOND */
219 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
220 free(tmp);
221 return l_insert_token(lstate, T_UNKNOWN);
222 }
223 }
224 else
225 {
226 pl_roll_back(state);
227 return l_insert_token(lstate, T_NUMBER);
228 }
229 }
230 else
231 {
232 /* ERROR: expected PL_MINUTE | PL_DIGIT */
233 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
234 free(tmp);
235 return l_insert_token(lstate, T_UNKNOWN);
236 }
237 }
238 else if(type == PL_DECIMAL)
239 {
240ANGLE_NUM_DM_STATE:
241 if((type = pl_get_next_token(state)) != PL_DIGIT)
242 {
243 /* ERROR: expected PL_DIGIT */
244 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
245 free(tmp);
246 return l_insert_token(lstate, T_UNKNOWN);
247 }
248 while((type = pl_get_next_token(state)) == PL_DIGIT);
249 if(type == PL_MINUTE)
250 {
251 return l_insert_token(lstate, T_NUMBER);
252 }
253 else
254 {
255 /* ERROR: expected PL_MINUTE */
256 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
257 free(tmp);
258 return l_insert_token(lstate, T_UNKNOWN);
259 }
260 }
261 else
262 {
263 return l_insert_token(lstate, T_NUMBER);
264 }
265 }
266 else if(type == PL_DECIMAL)
267 {
268 goto DECIMAL_STATE;
269 }
270 else if(type == PL_HEX)
271 {
272 goto HEX_DEC_STATE;
273 }
274 else
275 {
276 pl_roll_back(state);
277 return l_insert_token(lstate, T_NUMBER);
278 }
279 }
280 if(type == PL_DECIMAL)
281 {
282DECIMAL_STATE:
283 type = pl_get_next_token(state);
284 if(type == PL_DIGIT)
285 {
286 while((type = pl_get_next_token(state)) == PL_DIGIT);
287 if(type == PL_DEGREE)
288 {
289 return l_insert_token(lstate, T_NUMBER);
290 }
291 else if(type == PL_HEX)
292 {
293 goto DECIMAL_HEX_STATE;
294 }
295 else if(type == PL_SUB_DIGIT)
296 {
297 while(pl_get_next_token(state) == PL_SUB_DIGIT);
298 pl_roll_back(state);
299 return l_insert_token(lstate, T_NUMBER);
300 }
301 else
302 {
303 pl_roll_back(state);
304 return l_insert_token(lstate, T_NUMBER);
305 }
306 }
307 else if(type == PL_HEX)
308 {
309 goto DECIMAL_HEX_STATE;
310 }
311 else
312 {
313 /* ERROR: expected PL_DIGIT | PL_HEX */
314 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
315 free(tmp);
316 return l_insert_token(lstate, T_UNKNOWN);
317 }
318 }
319 if(type == PL_HEX)
320 {
321 while((type = pl_get_next_token(state)) == PL_HEX);
322 if(type == PL_DIGIT)
323 {
324HEX_DEC_STATE:
325 while(1)
326 {
327 type = pl_get_next_token(state);
328 if(type == PL_DIGIT || type == PL_HEX)
329 {
330 continue;
331 }
332 else if(type == PL_DECIMAL)
333 {
334 goto DECIMAL_HEX_STATE;
335 }
336 else if(type == PL_SUB_DIGIT)
337 {
338 while(pl_get_next_token(state) == PL_SUB_DIGIT);
339 pl_roll_back(state);
340 return l_insert_token(lstate, T_NUMBER);
341 }
342 else
343 {
344 if(l_check_if_number(lstate))
345 return l_insert_token(lstate, T_NUMBER);
346 /* ERROR: expected PL_DECIMAL | PL_DIGIT | PL_HEX */
347 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
348 free(tmp);
349 return l_insert_token(lstate, T_UNKNOWN);
350 }
351 }
352 }
353 else if(type == PL_DECIMAL)
354 {
355DECIMAL_HEX_STATE:
356 type = pl_get_next_token(state);
357 if(!(type == PL_DIGIT || type == PL_HEX))
358 {
359 /* ERROR: expected PL_DIGIT | PL_HEX */
360 set_error(lstate->parent, PARSER_ERR_MP, tmp = pl_get_marked_substring(state));
361 free(tmp);
362 return l_insert_token(lstate, T_UNKNOWN);
363 }
364 while(1)
365 {
366 type = pl_get_next_token(state);
367 if(type == PL_DIGIT || type == PL_HEX)
368 {
369 continue;
370 }
371 else if(type == PL_SUB_DIGIT)
372 {
373 while(pl_get_next_token(state) == PL_SUB_DIGIT);
374 pl_roll_back(state);
375 return l_insert_token(lstate, T_NUMBER);
376 }
377 else
378 {
379 pl_roll_back(state);
380 return l_insert_token(lstate, T_NUMBER);
381 }
382 }
383 }
384 else if(type == PL_SUB_DIGIT)
385 {
386 while(pl_get_next_token(state) == PL_SUB_DIGIT);
387 pl_roll_back(state);
388 if(l_check_if_number(lstate))
389 {
390 /* NUMBER */
391 return l_insert_token(lstate, T_NUMBER);
392 }
393 else
394 {
395 /* VARIABLE */
396 if(l_check_if_function(lstate))
397 {
398 return l_insert_token(lstate, T_FUNCTION);
399 }
400 else
401 {
402 return l_insert_token(lstate, T_VARIABLE);
403 }
404 }
405 }
406 else if(type == PL_LETTER)
407 {
408 goto LETTER_STATE;
409 }
410 else
411 {
412 pl_roll_back(state);
413 if(l_check_if_number(lstate))
414 {
415 /* NUMBER */
416 return l_insert_token(lstate, T_NUMBER);
417 }
418 else
419 {
420 /* VARIABLE */
421 if(l_check_if_function(lstate))
422 {
423 return l_insert_token(lstate, T_FUNCTION);
424 }
425 else
426 {
427 return l_insert_token(lstate, T_VARIABLE);
428 }
429 }
430 }
431 }
432 if(type == PL_LETTER)
433 {
434LETTER_STATE:
435 while(1)
436 {
437 type = pl_get_next_token(state);
438 if(type == PL_LETTER || type == PL_HEX)
439 {
440 continue;
441 }
442 else if(type == PL_SUB_DIGIT)
443 {
444 while(pl_get_next_token(state) == PL_SUB_DIGIT);
445 pl_roll_back(state);
446 tmp = g_ascii_strdown(pl_get_marked_substring(state), -1);
447 if(g_strcmp0(tmp, "mod") == 0)
448 {
449 return l_insert_token(lstate, T_MOD);
450 }
451 if(g_strcmp0(tmp, "and") == 0)
452 {
453 return l_insert_token(lstate, T_AND);
454 }
455 if(g_strcmp0(tmp, "or") == 0)
456 {
457 return l_insert_token(lstate, T_OR);
458 }
459 if(g_strcmp0(tmp, "xor") == 0)
460 {
461 return l_insert_token(lstate, T_XOR);
462 }
463 if(g_strcmp0(tmp, "not") == 0)
464 {
465 return l_insert_token(lstate, T_NOT);
466 }
467 if(g_strcmp0(tmp, "in") == 0)
468 {
469 return l_insert_token(lstate, T_IN);
470 }
471 if(l_check_if_function(lstate))
472 {
473 return l_insert_token(lstate, T_FUNCTION);
474 }
475 else
476 {
477 return l_insert_token(lstate, T_VARIABLE);
478 }
479 }
480 else
481 {
482 pl_roll_back(state);
483 tmp = g_ascii_strdown(pl_get_marked_substring(state), -1);
484 if(g_strcmp0(tmp, "mod") == 0)
485 {
486 return l_insert_token(lstate, T_MOD);
487 }
488 if(g_strcmp0(tmp, "and") == 0)
489 {
490 return l_insert_token(lstate, T_AND);
491 }
492 if(g_strcmp0(tmp, "or") == 0)
493 {
494 return l_insert_token(lstate, T_OR);
495 }
496 if(g_strcmp0(tmp, "xor") == 0)
497 {
498 return l_insert_token(lstate, T_XOR);
499 }
500 if(g_strcmp0(tmp, "not") == 0)
501 {
502 return l_insert_token(lstate, T_NOT);
503 }
504 if(g_strcmp0(tmp, "in") == 0)
505 {
506 return l_insert_token(lstate, T_IN);
507 }
508 if(l_check_if_function(lstate))
509 {
510 return l_insert_token(lstate, T_FUNCTION);
511 }
512 else
513 {
514 return l_insert_token(lstate, T_VARIABLE);
515 }
516 }
517 }
518 }
519 if(type == PL_EOS)
520 {
521 return l_insert_token(lstate, PL_EOS);
522 }
523 /* ERROR: Unexpected token.. X( */
524 set_error(lstate->parent, PARSER_ERR_INVALID, tmp = pl_get_marked_substring(state));
525 free(tmp);
526 return l_insert_token(lstate, T_UNKNOWN);
527}
528
529/* Call l_insert_next_token() as many times as needed to completely tokenize the string. */
530void
531l_insert_all_tokens(LexerState* state)
532{
533 LexerToken* token;
534 while(1)
535 {
536 token = l_insert_next_token(state);
537 assert(token != NULL)((void) sizeof ((token != ((void*)0)) ? 1 : 0), __extension__
({ if (token != ((void*)0)) ; else __assert_fail ("token != NULL"
, "lexer.c", 537, __extension__ __PRETTY_FUNCTION__); }))
;
538 if(token->token_type == PL_EOS)
539 {
540 break;
541 }
542 }
543}
544
545/* Create a lexer state from given input string. This will take care of pre-lexer state. */
546LexerState*
547l_create_lexer(const gchar* input, struct parser_state* parent)
548{
549 LexerState* ret;
550 ret = (LexerState *) malloc(sizeof(LexerState));
551 assert(ret != NULL)((void) sizeof ((ret != ((void*)0)) ? 1 : 0), __extension__ (
{ if (ret != ((void*)0)) ; else __assert_fail ("ret != NULL",
"lexer.c", 551, __extension__ __PRETTY_FUNCTION__); }))
;
552 ret->prelexer = pl_create_scanner(input);
553 ret->tokens = NULL((void*)0);
554 ret->token_count = 0;
555 ret->next_token = 0;
556 ret->parent = parent;
557 return ret;
558}
559
560/* Destroy lexer state and free memory. */
561void
562l_destroy_lexer(LexerState* state)
563{
564 int l;
565 pl_destroy_scanner(state->prelexer);
566 for(l = 0; l < state->token_count; l++)
567 {
568 free(state->tokens[l].string);
569 }
570 free(state->tokens);
571 free(state);
572}
573
574/* Get next token interface. Will be called by parser to get pointer to next token in token stream. */
575LexerToken*
576l_get_next_token(LexerState* state)
577{
578 /* Return PL_EOS token after token stream reaches to its end. */
579 if(state->next_token >= state->token_count)
580 return &state->tokens[state->token_count - 1];
581 return &state->tokens[state->next_token++];
582}
583
584/* Roll back one lexer token. */
585void
586l_roll_back(LexerState* state)
587{
588 if(state->next_token > 0)
589 state->next_token--;
590}
diff --git a/2024-07-10-100902-3667-1@fe495df3ec39_master/report-c223fe.html b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-c223fe.html new file mode 100644 index 0000000..4457e8d --- /dev/null +++ b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-c223fe.html @@ -0,0 +1,1651 @@ + + + +parserfunc.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:parserfunc.c
Warning:line 366, column 5
Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name parserfunc.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D LOCALE_DIR="/usr/local/share/locale" -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/atk-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/gio-unix-2.0 -D WITH_GZFILEOP -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-07-10-100902-3667-1 -x c parserfunc.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1#include <glib.h>
2#include <string.h>
3#include <stdlib.h>
4#include <stdio.h>
5
6#include "parser.h"
7#include "parserfunc.h"
8
9/* Register error variables in ParserState structure. */
10void
11set_error(ParserState* state, gint errorno, const gchar *token)
12{
13 state->error = errorno;
14 if(token)
15 state->error_token = strdup(token);
16}
17
18/* Unused function pointer. This won't be called anytime. */
19void*
20pf_none(ParseNode* self)
21{
22 return NULL((void*)0);
23}
24
25/* Set variable. */
26void*
27pf_set_var(ParseNode* self)
28{
29 MPNumber* val;
30 val = (MPNumber *) (*(self->right->evaluate))(self->right);
31 if(!val || !(self->state->set_variable))
32 {
33 if(val)
34 mp_free(val);
35 return NULL((void*)0);
36 }
37 (*(self->state->set_variable))(self->state, self->left->token->string, val);
38 return val;
39}
40
41/* Converts Number from one unit to other. */
42void*
43pf_convert_number(ParseNode* self)
44{
45 gchar* from;
46 gchar* to;
47 gint free_from = 0;
48 gint free_to = 0;
49 MPNumber tmp = mp_new();
50 MPNumber* ans = mp_new_ptr();
51 if(self->left->value)
52 {
53 from = (gchar*) self->left->value;
54 free_from = 1;
55 }
56 else
57 from = self->left->token->string;
58 if(self->right->value)
59 {
60 to = (gchar*) self->right->value;
61 free_to = 1;
62 }
63 else
64 to = self->right->token->string;
65
66 if(mp_set_from_string(self->left->left->token->string, self->state->options->base, &tmp) != 0)
67 {
68 mp_free(ans);
69 ans = NULL((void*)0);
70 goto END_PF_CONVERT_NUMBER;
71 }
72 if(!(self->state->convert))
73 {
74 mp_free(ans);
75 ans = NULL((void*)0);
76 goto END_PF_CONVERT_NUMBER;
77 }
78 if(!(*(self->state->convert))(self->state, &tmp, from, to, ans))
79 {
80 set_error(self->state, PARSER_ERR_UNKNOWN_CONVERSION, NULL((void*)0));
81 mp_free(ans);
82 ans = NULL((void*)0);
83 }
84END_PF_CONVERT_NUMBER:
85 if(free_from)
86 {
87 g_free(self->left->value);
88 self->left->value = NULL((void*)0);
89 }
90 if(free_to)
91 {
92 g_free(self->right->value);
93 self->right->value = NULL((void*)0);
94 }
95 mp_clear(&tmp);
96 return ans;
97}
98
99/* Conversion rate. */
100void*
101pf_convert_1(ParseNode* self )
102{
103 gchar* from;
104 gchar* to;
105 gint free_from = 0;
106 gint free_to = 0;
107 MPNumber tmp = mp_new();
108 MPNumber* ans = mp_new_ptr();
109 if(self->left->value)
110 {
111 from = (gchar*) self->left->value;
112 free_from = 1;
113 }
114 else
115 from = self->left->token->string;
116 if(self->right->value)
117 {
118 to = (gchar*) self->right->value;
119 free_to = 1;
120 }
121 else
122 to = self->right->token->string;
123 mp_set_from_integer(1, &tmp);
124 if(!(self->state->convert))
125 {
126 mp_free(ans);
127 return NULL((void*)0);
128 }
129 if(!(*(self->state->convert))(self->state, &tmp, from, to, ans))
130 {
131 set_error(self->state, PARSER_ERR_UNKNOWN_CONVERSION, NULL((void*)0));
132 mp_free(ans);
133 ans = NULL((void*)0);
134 }
135 if(free_from)
136 {
137 g_free(self->left->value);
138 self->left->value = NULL((void*)0);
139 }
140 if(free_to)
141 {
142 g_free(self->right->value);
143 self->right->value = NULL((void*)0);
144 }
145 mp_clear(&tmp);
146 return ans;
147}
148
149/* Join source unit and power. */
150gchar*
151pf_make_unit(gchar* source, gchar* power)
152{
153 return g_strjoin(NULL((void*)0), source, power, NULL((void*)0));
154}
155
156static gchar *
157utf8_next_char(const gchar *c)
158{
159 c++;
160 while((*c & 0xC0) == 0x80)
161 c++;
162 return(gchar *) c;
163}
164
165/* Get value of variable. */
166void*
167pf_get_variable(ParseNode* self)
168{
169 gint result = 0;
170
171 const gchar *c, *next;
172 gchar *buffer;
173 MPNumber value = mp_new();
174
175 MPNumber t = mp_new();
176 MPNumber* ans = mp_new_ptr();
177
178 if(!(self->state->get_variable))
179 {
180 free(ans);
181 return NULL((void*)0);
182 }
183
184 /* If defined, then get the variable */
185 if((*(self->state->get_variable))(self->state, self->token->string, ans))
186 {
187 return ans;
188 }
189
190 /* If has more than one character then assume a multiplication of variables */
191 if(utf8_next_char(self->token->string)[0] != '\0')
192 {
193 result = 1;
194 buffer = (gchar*) malloc(sizeof(gchar) * strlen(self->token->string));
195 mp_set_from_integer(1, &value);
196 for(c = self->token->string; *c != '\0'; c = next)
197 {
198 next = utf8_next_char(c);
199 snprintf(buffer, next - c + 1, "%s", c);
200 if(!(*(self->state->get_variable))(self->state, buffer, &t))
201 {
202 result = 0;
203 break;
204 }
205 mp_multiply(&value, &t, &value);
206 }
207 free(buffer);
208 if(result)
209 mp_set_from_mp(&value, ans);
210 }
211 if(!result)
212 {
213 free (ans);
214 ans = NULL((void*)0);
215 set_error(self->state, PARSER_ERR_UNKNOWN_VARIABLE, self->token->string);
216 }
217 return ans;
218}
219
220/* Get value of variable with power. */
221void*
222pf_get_variable_with_power(ParseNode* self)
223{
224 gint result = 0;
225 gint pow;
226
227 const gchar *c, *next;
228 gchar *buffer;
229 MPNumber value = mp_new();
230
231 MPNumber t = mp_new();
232 MPNumber* ans = mp_new_ptr();
233 pow = super_atoi(((LexerToken*) self->value)->string);
234
235 /* No need to free the memory. It is allocated and freed somewhere else. */
236 self->value = NULL((void*)0);
237
238 if(!(self->state->get_variable))
239 {
240 free(ans);
241 return NULL((void*)0);
242 }
243
244 /* If defined, then get the variable */
245 if((*(self->state->get_variable))(self->state, self->token->string, ans))
246 {
247 mp_xpowy_integer(ans, pow, ans);
248 return ans;
249 }
250
251 /* If has more than one character then assume a multiplication of variables */
252 if(utf8_next_char(self->token->string)[0] != '\0')
253 {
254 result = 1;
255 buffer = (gchar*) malloc(sizeof(gchar) * strlen(self->token->string));
256 mp_set_from_integer(1, &value);
257 for(c = self->token->string; *c != '\0'; c = next)
258 {
259 next = utf8_next_char(c);
260 snprintf(buffer, next - c + 1, "%s", c);
261 if(!(*(self->state->get_variable))(self->state, buffer, &t))
262 {
263 result = 0;
264 break;
265 }
266
267 /* If last term do power */
268 if(*next == '\0')
269 mp_xpowy_integer(&t, pow, &t);
270 mp_multiply(&value, &t, &value);
271 }
272 free(buffer);
273 if(result)
274 mp_set_from_mp(&value, ans);
275 }
276 if(!result)
277 {
278 free(ans);
279 ans = NULL((void*)0);
280 set_error(self->state, PARSER_ERR_UNKNOWN_VARIABLE, self->token->string);
281 }
282 return ans;
283}
284
285/* Apply function on child. */
286void*
287pf_apply_func(ParseNode* self)
288{
289 MPNumber* val;
290 MPNumber* ans = mp_new_ptr();
291 val = (MPNumber*) (*(self->right->evaluate))(self->right);
292 if(!(self->state->get_function))
293 {
294 free(val);
295 free(ans);
296 return NULL((void*)0);
297 }
298 if(!val)
299 {
300 free(ans);
301 return NULL((void*)0);
302 }
303 if(!(*(self->state->get_function))(self->state, self->token->string, val, ans))
304 {
305 free(val);
306 free(ans);
307 set_error(self->state, PARSER_ERR_UNKNOWN_FUNCTION, self->token->string);
308 return NULL((void*)0);
309 }
310 free(val);
311 return ans;
312}
313
314/* Apply function with +ve power. */
315void*
316pf_apply_func_with_power(ParseNode* self)
317{
318 MPNumber* val;
319 MPNumber* tmp = mp_new_ptr();
320 MPNumber* ans = mp_new_ptr();
321 gint pow;
322 val = (MPNumber*) (*(self->right->evaluate))(self->right);
323 if(!(self->state->get_function))
324 {
325 mp_free(tmp);
326 mp_free(ans);
327 mp_free(val);
328 self->value = NULL((void*)0);
329 return NULL((void*)0);
330 }
331 if(!val)
332 {
333 mp_free(tmp);
334 mp_free(ans);
335 self->value = NULL((void*)0);
336 return NULL((void*)0);
337 }
338 if(!(*(self->state->get_function))(self->state, self->token->string, val, tmp))
339 {
340 mp_free(tmp);
341 mp_free(ans);
342 mp_free(val);
343 self->value = NULL((void*)0);
344 set_error(self->state, PARSER_ERR_UNKNOWN_FUNCTION, self->token->string);
345 return NULL((void*)0);
346 }
347 pow = super_atoi(((LexerToken*) self->value)->string);
348 mp_xpowy_integer(tmp, pow, ans);
349 mp_free(val);
350 mp_free(tmp);
351 self->value = NULL((void*)0);
352 return ans;
353}
354
355/* Apply function with -ve power. */
356void*
357pf_apply_func_with_npower(ParseNode* self)
358{
359 MPNumber* val;
360 MPNumber* tmp = mp_new_ptr();
361 MPNumber* ans = mp_new_ptr();
362 gint pow;
363 gchar* inv_name;
364 inv_name = (gchar*) malloc(sizeof(gchar) * strlen(self->token->string) + strlen("⁻¹") + 1);
365 strcpy(inv_name, self->token->string);
366 strcat(inv_name, "⁻¹");
Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119
367 val = (MPNumber*) (*(self->right->evaluate))(self->right);
368 if(!val)
369 {
370 mp_free(tmp);
371 free(inv_name);
372 mp_free(ans);
373 self->value = NULL((void*)0);
374 return NULL((void*)0);
375 }
376 if(!(self->state->get_function))
377 {
378 mp_free(tmp);
379 mp_free(ans);
380 free(inv_name);
381 self->value = NULL((void*)0);
382 return NULL((void*)0);
383 }
384 if(!(*(self->state->get_function))(self->state, inv_name, val, tmp))
385 {
386 mp_free(tmp);
387 mp_free(ans);
388 mp_free(val);
389 free(inv_name);
390 self->value = NULL((void*)0);
391 set_error(self->state, PARSER_ERR_UNKNOWN_FUNCTION, self->token->string);
392 return NULL((void*)0);
393 }
394 pow = super_atoi(((LexerToken*) self->value)->string);
395 mp_xpowy_integer(tmp, -pow, ans);
396 mp_free(val);
397 mp_free(tmp);
398 free(inv_name);
399 self->value = NULL((void*)0);
400 return ans;
401}
402
403/* Find nth root of child. */
404void*
405pf_do_nth_root(ParseNode* self)
406{
407 MPNumber* val;
408 gint pow;
409 MPNumber* ans = mp_new_ptr();
410 pow = sub_atoi(((LexerToken*) self->value)->string);
411 self->value = NULL((void*)0);
412 val = (MPNumber*) (*(self->right->evaluate))(self->right);
413 if(!val)
414 {
415 mp_free(ans);
416 return NULL((void*)0);
417 }
418 mp_root(val, pow, ans);
419 mp_free(val);
420 return ans;
421}
422
423/* Find sqrt of child. */
424void*
425pf_do_sqrt(ParseNode* self)
426{
427 MPNumber* val;
428 MPNumber* ans = mp_new_ptr();
429 val = (MPNumber*) (*(self->right->evaluate))(self->right);
430 if(!val)
431 {
432 free(ans);
433 return NULL((void*)0);
434 }
435 mp_sqrt(val, ans);
436 free(val);
437 return ans;
438}
439
440/* Find 3rd root of child. */
441void*
442pf_do_root_3(ParseNode* self)
443{
444 MPNumber* val;
445 MPNumber* ans = mp_new_ptr();
446 val = (MPNumber*) (*(self->right->evaluate))(self->right);
447 if(!val)
448 {
449 mp_free(ans);
450 return NULL((void*)0);
451 }
452 mp_root(val, 3, ans);
453 mp_free(val);
454 return ans;
455}
456
457/* Find 4th root of child. */
458void*
459pf_do_root_4(ParseNode* self)
460{
461 MPNumber* val;
462 MPNumber* ans = mp_new_ptr();
463 val = (MPNumber*) (*(self->right->evaluate))(self->right);
464 if(!val)
465 {
466 mp_free(ans);
467 return NULL((void*)0);
468 }
469 mp_root(val, 4, ans);
470 mp_free(val);
471 return ans;
472}
473
474/* Apply floor function. */
475void*
476pf_do_floor(ParseNode* self)
477{
478 MPNumber* val;
479 MPNumber* ans = mp_new_ptr();
480 val = (MPNumber*) (*(self->right->evaluate))(self->right);
481 if(!val)
482 {
483 mp_free(ans);
484 return NULL((void*)0);
485 }
486 mp_floor(val, ans);
487 mp_free(val);
488 return ans;
489}
490
491/* Apply ceiling function. */
492void* pf_do_ceiling (ParseNode* self)
493{
494 MPNumber* val;
495 MPNumber* ans = mp_new_ptr();
496 val = (MPNumber*) (*(self->right->evaluate))(self->right);
497 if(!val)
498 {
499 mp_free(ans);
500 return NULL((void*)0);
501 }
502 mp_ceiling(val, ans);
503 mp_free(val);
504 return ans;
505}
506
507/* Round off. */
508void*
509pf_do_round(ParseNode* self)
510{
511 MPNumber* val;
512 MPNumber* ans = mp_new_ptr();
513 val = (MPNumber*) (*(self->right->evaluate))(self->right);
514 if(!val)
515 {
516 mp_free(ans);
517 return NULL((void*)0);
518 }
519 mp_round(val, ans);
520 mp_free(val);
521 return ans;
522}
523
524/* Fraction. */
525void*
526pf_do_fraction(ParseNode* self)
527{
528 MPNumber* val;
529 MPNumber* ans = mp_new_ptr();
530 val = (MPNumber*) (*(self->right->evaluate))(self->right);
531 if(!val)
532 {
533 mp_free(ans);
534 return NULL((void*)0);
535 }
536 mp_fractional_part(val, ans);
537 mp_free(val);
538 return ans;
539}
540
541/* Absolute value. */
542void*
543pf_do_abs(ParseNode* self)
544{
545 MPNumber* val;
546 MPNumber* ans = mp_new_ptr();
547 val = (MPNumber*) (*(self->right->evaluate))(self->right);
548 if(!val)
549 {
550 mp_free(ans);
551 return NULL((void*)0);
552 }
553 mp_abs(val, ans);
554 mp_free(val);
555 return ans;
556}
557
558/* Find x^y for x and y being MPNumber. */
559void*
560pf_do_x_pow_y(ParseNode* self)
561{
562 MPNumber* val;
563 MPNumber* pow;
564 MPNumber* ans = mp_new_ptr();
565 val = (MPNumber*) (*(self->left->evaluate))(self->left);
566 pow = (MPNumber*) (*(self->right->evaluate))(self->right);
567 if(!val || !pow)
568 {
569 if(val)
570 mp_free(val);
571 if(pow)
572 mp_free(pow);
573 mp_free(ans);
574 return NULL((void*)0);
575 }
576 mp_xpowy(val, pow, ans);
577 mp_free(val);
578 mp_free(pow);
579 return ans;
580}
581
582/* Find x^y for MPNumber x and integer y. */
583void*
584pf_do_x_pow_y_int(ParseNode* self)
585{
586 MPNumber* val;
587 long pow;
588 MPNumber* ans = mp_new_ptr();
589 val = (MPNumber*) (*(self->left->evaluate))(self->left);
590
591 if(!val)
592 {
593 val = mp_new_ptr();
594 mp_set_from_integer(super_atoi(self->left->token->string), val);
595 }
596
597 if (self->right->token != NULL((void*)0))
598 {
599 pow = super_atoi(self->right->token->string);
600 }
601 else
602 {
603 MPNumber* aux = (MPNumber*) (*(self->right->evaluate))(self->right);
604 pow = mp_to_integer(aux);
605 mp_free(aux);
606 }
607
608 if(!val)
609 {
610 mp_free(ans);
611 return NULL((void*)0);
612 }
613 mp_xpowy_integer(val, pow, ans);
614 mp_free(val);
615 return ans;
616}
617
618/* Find factorial. */
619void*
620pf_do_factorial(ParseNode* self)
621{
622 MPNumber* val;
623 MPNumber* ans = mp_new_ptr();
624 val = (MPNumber*) (*(self->right->evaluate))(self->right);
625 if(!val)
626 {
627 mp_free(ans);
628 return NULL((void*)0);
629 }
630 mp_factorial(val, ans);
631 mp_free(val);
632 return ans;
633}
634
635/* Apply unary minus. */
636void*
637pf_unary_minus(ParseNode* self)
638{
639 MPNumber* val;
640 MPNumber* ans = mp_new_ptr();
641 val = (MPNumber*) (*(self->right->evaluate))(self->right);
642 if(!val)
643 {
644 mp_free(ans);
645 return NULL((void*)0);
646 }
647 mp_invert_sign(val, ans);
648 mp_free(val);
649 return ans;
650}
651
652/* Divide. */
653void*
654pf_do_divide(ParseNode* self)
655{
656 MPNumber* left;
657 MPNumber* right;
658 MPNumber* ans = mp_new_ptr();
659 left = (MPNumber*) (*(self->left->evaluate))(self->left);
660 right = (MPNumber*) (*(self->right->evaluate))(self->right);
661 if(!left || !right)
662 {
663 if(left)
664 mp_free(left);
665 if(right)
666 mp_free(right);
667 mp_free(ans);
668 return NULL((void*)0);
669 }
670 mp_divide(left, right, ans);
671 mp_free(left);
672 mp_free(right);
673 return ans;
674}
675
676/* Modulus. */
677void*
678pf_do_mod(ParseNode* self)
679{
680 MPNumber* left;
681 MPNumber* right;
682 MPNumber* ans = mp_new_ptr();
683 left = (MPNumber*) (*(self->left->evaluate))(self->left);
684 right = (MPNumber*) (*(self->right->evaluate))(self->right);
685 if(!left || !right)
686 {
687 if(left)
688 mp_free(left);
689 if(right)
690 mp_free(right);
691 mp_free(ans);
692 return NULL((void*)0);
693 }
694 if (self->left->evaluate == pf_do_x_pow_y)
695 {
696 MPNumber* base_value = (MPNumber*) (*(self->left->left->evaluate))(self->left->left);
697 MPNumber* exponent = (MPNumber*) (*(self->left->right->evaluate))(self->left->right);
698 if(!base_value || !exponent)
699 {
700 if(base_value)
701 mp_free(base_value);
702 if(exponent)
703 mp_free(exponent);
704 mp_free(ans);
705 return NULL((void*)0);
706 }
707 mp_modular_exponentiation(base_value, exponent, right, ans);
708 mp_free(base_value);
709 mp_free(exponent);
710 }
711 else
712 mp_modulus_divide(left, right, ans);
713
714 mp_free(left);
715 mp_free(right);
716 return ans;
717}
718
719/* Multiply two numbers. */
720void*
721pf_do_multiply(ParseNode* self)
722{
723 MPNumber* left;
724 MPNumber* right;
725 MPNumber* ans = mp_new_ptr();
726 left = (MPNumber*) (*(self->left->evaluate))(self->left);
727 right = (MPNumber*) (*(self->right->evaluate))(self->right);
728 if(!left || !right)
729 {
730 if(left)
731 mp_free(left);
732 if(right)
733 mp_free(right);
734 mp_free(ans);
735 return NULL((void*)0);
736 }
737 mp_multiply(left, right, ans);
738 mp_free(left);
739 mp_free(right);
740 return ans;
741}
742
743/* Subtract two numbers. */
744void*
745pf_do_subtract(ParseNode* self)
746{
747 MPNumber* left;
748 MPNumber* right;
749 MPNumber* ans = mp_new_ptr();
750 left = (MPNumber*) (*(self->left->evaluate))(self->left);
751 right = (MPNumber*) (*(self->right->evaluate))(self->right);
752 if(!left || !right)
753 {
754 if(left)
755 mp_free(left);
756 if(right)
757 mp_free(right);
758 free(ans);
759 return NULL((void*)0);
760 }
761 mp_subtract(left, right, ans);
762 mp_free(left);
763 mp_free(right);
764 return ans;
765}
766
767/* Add two numbers. */
768void*
769pf_do_add(ParseNode* self)
770{
771 MPNumber* left;
772 MPNumber* right;
773 MPNumber* ans = mp_new_ptr();
774 left = (MPNumber*) (*(self->left->evaluate))(self->left);
775 right = (MPNumber*) (*(self->right->evaluate))(self->right);
776 if(!left || !right)
777 {
778 if(left)
779 mp_free(left);
780 if(right)
781 mp_free(right);
782 free(ans);
783 return NULL((void*)0);
784 }
785 mp_add(left, right, ans);
786 mp_free(left);
787 mp_free(right);
788 return ans;
789}
790
791/* Add (x) Percentage to value. */
792void*
793pf_do_add_percent(ParseNode* self)
794{
795 MPNumber* ans = mp_new_ptr();
796 MPNumber* val;
797 MPNumber* per;
798 val = (MPNumber*) (*(self->left->evaluate))(self->left);
799 per = (MPNumber*) (*(self->right->evaluate))(self->right);
800 if(!val || !per)
801 {
802 if(val)
803 mp_free(val);
804 if(per)
805 mp_free(per);
806 mp_free(ans);
807 return NULL((void*)0);
808 }
809 mp_add_integer(per, 100, per);
810 mp_divide_integer(per, 100, per);
811 mp_multiply(val, per, ans);
812 mp_free(val);
813 mp_free(per);
814 return ans;
815}
816
817/* Subtract (x) Percentage to value. */
818void*
819pf_do_subtract_percent(ParseNode* self)
820{
821 MPNumber* ans = mp_new_ptr();
822 MPNumber* val;
823 MPNumber* per;
824 val = (MPNumber*) (*(self->left->evaluate))(self->left);
825 per = (MPNumber*) (*(self->right->evaluate))(self->right);
826 if(!val || !per)
827 {
828 if(val)
829 mp_free(val);
830 if(per)
831 mp_free(per);
832 free(ans);
833 return NULL((void*)0);
834 }
835 mp_add_integer(per, -100, per);
836 mp_divide_integer(per, -100, per);
837 mp_multiply(val, per, ans);
838 mp_free(val);
839 mp_free(per);
840 return ans;
841}
842
843/* Converts a constant into percentage. */
844void*
845pf_do_percent(ParseNode* self)
846{
847 MPNumber* val;
848 MPNumber* ans = mp_new_ptr();
849 val = (MPNumber*) (*(self->right->evaluate))(self->right);
850 if(!val)
851 {
852 mp_free(ans);
853 return NULL((void*)0);
854 }
855 mp_divide_integer(val, 100, ans);
856 mp_free(val);
857 return ans;
858}
859
860/* NOT. */
861void*
862pf_do_not(ParseNode* self)
863{
864 MPNumber* val;
865 MPNumber* ans = mp_new_ptr();
866 val = (MPNumber*) (*(self->right->evaluate))(self->right);
867 if(!val)
868 {
869 mp_free(ans);
870 return NULL((void*)0);
871 }
872 if(!mp_is_overflow(val, self->state->options->wordlen))
873 {
874 set_error(self->state, PARSER_ERR_OVERFLOW, NULL((void*)0));
875 mp_free(ans);
876 mp_free(val);
877 return NULL((void*)0);
878 }
879 mp_not(val, self->state->options->wordlen, ans);
880 mp_free(val);
881 return ans;
882}
883
884/* AND. */
885void*
886pf_do_and(ParseNode* self)
887{
888 MPNumber* left;
889 MPNumber* right;
890 MPNumber* ans = mp_new_ptr();
891 left = (MPNumber*) (*(self->left->evaluate))(self->left);
892 right = (MPNumber*) (*(self->right->evaluate))(self->right);
893 if(!left || !right)
894 {
895 if(left)
896 mp_free(left);
897 if(right)
898 mp_free(right);
899 mp_free(ans);
900 return NULL((void*)0);
901 }
902 mp_and(left, right, ans);
903 mp_free(left);
904 mp_free(right);
905 return ans;
906}
907
908/* OR. */
909void*
910pf_do_or(ParseNode* self)
911{
912 MPNumber* left;
913 MPNumber* right;
914 MPNumber* ans = mp_new_ptr();
915 left = (MPNumber*) (*(self->left->evaluate))(self->left);
916 right = (MPNumber*) (*(self->right->evaluate))(self->right);
917 if(!left || !right)
918 {
919 if(left)
920 mp_free(left);
921 if(right)
922 mp_free(right);
923 mp_free(ans);
924 return NULL((void*)0);
925 }
926 mp_or(left, right, ans);
927 mp_free(left);
928 mp_free(right);
929 return ans;
930}
931
932/* XOR. */
933void*
934pf_do_xor(ParseNode* self)
935{
936 MPNumber* left;
937 MPNumber* right;
938 MPNumber* ans = mp_new_ptr();
939 left = (MPNumber*) (*(self->left->evaluate))(self->left);
940 right = (MPNumber*) (*(self->right->evaluate))(self->right);
941 if(!left || !right)
942 {
943 if(left)
944 mp_free(left);
945 if(right)
946 mp_free(right);
947 free(ans);
948 return NULL((void*)0);
949 }
950 mp_xor(left, right, ans);
951 mp_free(left);
952 mp_free(right);
953 return ans;
954}
955
956/* Constant value. Convert into MPNumber and return. */
957void*
958pf_constant(ParseNode* self)
959{
960 MPNumber* ans = mp_new_ptr();
961 if(mp_set_from_string(self->token->string, self->state->options->base, ans) != 0)
962 {
963 /* This should never happen, as l_check_if_number() has already passed the string once. */
964 /* If the code reaches this point, something is really wrong. X( */
965 mp_free(ans);
966 set_error(self->state, PARSER_ERR_INVALID, self->token->string);
967 return NULL((void*)0);
968 }
969 return ans;
970}
971
diff --git a/2024-07-10-100902-3667-1@fe495df3ec39_master/report-c8cbaf.html b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-c8cbaf.html new file mode 100644 index 0000000..dc49713 --- /dev/null +++ b/2024-07-10-100902-3667-1@fe495df3ec39_master/report-c8cbaf.html @@ -0,0 +1,1062 @@ + + + +math-preferences.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:math-preferences.c
Warning:line 150, column 9
Value stored to 'valid' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name math-preferences.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/src -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/18 -D HAVE_CONFIG_H -I . -I .. -D LOCALE_DIR="/usr/local/share/locale" -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cairo -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/atk-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/webp -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/cloudproviders -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/gio-unix-2.0 -D WITH_GZFILEOP -internal-isystem /usr/bin/../lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-07-10-100902-3667-1 -x c math-preferences.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright (C) 2008-2011 Robert Ancell
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License as published by the Free Software
6 * Foundation, either version 2 of the License, or (at your option) any later
7 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
8 * license.
9 */
10
11#include <glib/gi18n.h>
12#include <gtk/gtk.h>
13
14#include "math-preferences.h"
15#include "utility.h"
16
17enum {
18 PROP_0,
19 PROP_EQUATION
20};
21
22struct MathPreferencesDialogPrivate
23{
24 MathEquation *equation;
25 GtkBuilder *ui;
26};
27
28G_DEFINE_TYPE_WITH_PRIVATE (MathPreferencesDialog, math_preferences, GTK_TYPE_DIALOG)static void math_preferences_init (MathPreferencesDialog *self
); static void math_preferences_class_init (MathPreferencesDialogClass
*klass); static GType math_preferences_get_type_once (void);
static gpointer math_preferences_parent_class = ((void*)0); static
gint MathPreferencesDialog_private_offset; static void math_preferences_class_intern_init
(gpointer klass) { math_preferences_parent_class = g_type_class_peek_parent
(klass); if (MathPreferencesDialog_private_offset != 0) g_type_class_adjust_private_offset
(klass, &MathPreferencesDialog_private_offset); math_preferences_class_init
((MathPreferencesDialogClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer math_preferences_get_instance_private
(MathPreferencesDialog *self) { return (((gpointer) ((guint8
*) (self) + (glong) (MathPreferencesDialog_private_offset))))
; } GType math_preferences_get_type (void) { static GType static_g_define_type_id
= 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) * (&static_g_define_type_id) : ((void*)
0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= math_preferences_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType math_preferences_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
((gtk_dialog_get_type ()), g_intern_static_string ("MathPreferencesDialog"
), sizeof (MathPreferencesDialogClass), (GClassInitFunc)(void
(*)(void)) math_preferences_class_intern_init, sizeof (MathPreferencesDialog
), (GInstanceInitFunc)(void (*)(void)) math_preferences_init,
(GTypeFlags) 0); { {{ MathPreferencesDialog_private_offset =
g_type_add_instance_private (g_define_type_id, sizeof (MathPreferencesDialogPrivate
)); };} } return g_define_type_id; }
;
29
30#define UI_DIALOGS_RESOURCE_PATH"/org/mate/calculator/ui/preferences.ui" "/org/mate/calculator/ui/preferences.ui"
31#define GET_WIDGET(ui, name)((((GtkWidget*) (void *) ((gtk_builder_get_object(ui, name)))
)))
\
32 GTK_WIDGET(gtk_builder_get_object(ui, name))((((GtkWidget*) (void *) ((gtk_builder_get_object(ui, name)))
)))
33
34MathPreferencesDialog *
35math_preferences_dialog_new(MathEquation *equation)
36{
37 return g_object_new(math_preferences_get_type(), "equation", equation, NULL((void*)0));
38}
39
40static void
41preferences_response_cb(GtkWidget *widget, gint id)
42{
43 gtk_widget_hide(widget);
44}
45
46static gboolean
47preferences_dialog_delete_cb(GtkWidget *widget, GdkEvent *event)
48{
49 preferences_response_cb(widget, 0);
50 return TRUE(!(0));
51}
52
53void number_format_combobox_changed_cb(GtkWidget *combo, MathPreferencesDialog *dialog);
54G_MODULE_EXPORT__attribute__((visibility("default")))
55void
56number_format_combobox_changed_cb(GtkWidget *combo, MathPreferencesDialog *dialog)
57{
58 MpDisplayFormat value;
59 GtkTreeModel *model;
60 GtkTreeIter iter;
61
62 model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))));
63 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))), &iter);
64 gtk_tree_model_get(model, &iter, 1, &value, -1);
65 math_equation_set_number_format(dialog->priv->equation, value);
66}
67
68void angle_unit_combobox_changed_cb(GtkWidget *combo, MathPreferencesDialog *dialog);
69G_MODULE_EXPORT__attribute__((visibility("default")))
70void
71angle_unit_combobox_changed_cb(GtkWidget *combo, MathPreferencesDialog *dialog)
72{
73 MPAngleUnit value;
74 GtkTreeModel *model;
75 GtkTreeIter iter;
76
77 model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))));
78 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))), &iter);
79 gtk_tree_model_get(model, &iter, 1, &value, -1);
80 math_equation_set_angle_units(dialog->priv->equation, value);
81}
82
83void word_size_combobox_changed_cb(GtkWidget *combo, MathPreferencesDialog *dialog);
84G_MODULE_EXPORT__attribute__((visibility("default")))
85void
86word_size_combobox_changed_cb(GtkWidget *combo, MathPreferencesDialog *dialog)
87{
88 gint value;
89 GtkTreeModel *model;
90 GtkTreeIter iter;
91
92 model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))));
93 gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))), &iter);
94 gtk_tree_model_get(model, &iter, 1, &value, -1);
95 math_equation_set_word_size(dialog->priv->equation, value);
96}
97
98void decimal_places_spin_change_value_cb(GtkWidget *spin, MathPreferencesDialog *dialog);
99G_MODULE_EXPORT__attribute__((visibility("default")))
100void
101decimal_places_spin_change_value_cb(GtkWidget *spin, MathPreferencesDialog *dialog)
102{
103 gint value = 0;
104
105 value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin)((((GtkSpinButton*) (void *) ((spin))))));
106 math_equation_set_accuracy(dialog->priv->equation, value);
107}
108
109void thousands_separator_check_toggled_cb(GtkWidget *check, MathPreferencesDialog *dialog);
110G_MODULE_EXPORT__attribute__((visibility("default")))
111void
112thousands_separator_check_toggled_cb(GtkWidget *check, MathPreferencesDialog *dialog)
113{
114 gboolean value;
115
116 value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check)((((GtkToggleButton*) (void *) ((check))))));
117 math_equation_set_show_thousands_separators(dialog->priv->equation, value);
118}
119
120void trailing_zeroes_check_toggled_cb(GtkWidget *check, MathPreferencesDialog *dialog);
121G_MODULE_EXPORT__attribute__((visibility("default")))
122void
123trailing_zeroes_check_toggled_cb(GtkWidget *check, MathPreferencesDialog *dialog)
124{
125 gboolean value;
126
127 value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check)((((GtkToggleButton*) (void *) ((check))))));
128 math_equation_set_show_trailing_zeroes(dialog->priv->equation, value);
129}
130
131static void
132set_combo_box_from_int(GtkWidget *combo, int value)
133{
134 GtkTreeModel *model;
135 GtkTreeIter iter;
136 gboolean valid;
137
138 model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))));
139 valid = gtk_tree_model_get_iter_first(model, &iter);
140
141 while (valid) {
142 gint v;
143
144 gtk_tree_model_get(model, &iter, 1, &v, -1);
145 if (v == value)
146 break;
147 valid = gtk_tree_model_iter_next(model, &iter);
148 }
149 if (!valid)
150 valid = gtk_tree_model_get_iter_first(model, &iter);
Value stored to 'valid' is never read
151
152 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo)((((GtkComboBox*) (void *) ((combo))))), &iter);
153}
154
155static void
156accuracy_cb(MathEquation *equation, GParamSpec *spec, MathPreferencesDialog *dialog)
157{
158 gtk_spin_button_set_value(GTK_SPIN_BUTTON(gtk_builder_get_object(dialog->priv->ui, "decimal_places_spin"))((((GtkSpinButton*) (void *) ((gtk_builder_get_object(dialog->
priv->ui, "decimal_places_spin"))))))
,
159 math_equation_get_accuracy(equation));
160 g_settings_set_int(g_settings_var, "accuracy", math_equation_get_accuracy(equation));
161}
162
163static void
164show_thousands_separators_cb(MathEquation *equation, GParamSpec *spec, MathPreferencesDialog *dialog)
165{
166 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(dialog->priv->ui, "thousands_separator_check"))((((GtkToggleButton*) (void *) ((gtk_builder_get_object(dialog
->priv->ui, "thousands_separator_check"))))))
,
167 math_equation_get_show_thousands_separators(equation));
168 g_settings_set_boolean(g_settings_var, "show-thousands", math_equation_get_show_thousands_separators(equation));
169}
170
171static void
172show_trailing_zeroes_cb(MathEquation *equation, GParamSpec *spec, MathPreferencesDialog *dialog)
173{
174 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(dialog->priv->ui, "trailing_zeroes_check"))((((GtkToggleButton*) (void *) ((gtk_builder_get_object(dialog
->priv->ui, "trailing_zeroes_check"))))))
,
175 math_equation_get_show_trailing_zeroes(equation));
176 g_settings_set_boolean(g_settings_var, "show-zeroes", math_equation_get_show_trailing_zeroes(equation));
177}
178
179static void
180number_format_cb(MathEquation *equation, GParamSpec *spec, MathPreferencesDialog *dialog)
181{
182 set_combo_box_from_int(GET_WIDGET(dialog->priv->ui, "number_format_combobox")((((GtkWidget*) (void *) ((gtk_builder_get_object(dialog->
priv->ui, "number_format_combobox"))))))
, math_equation_get_number_format(equation));
183 g_settings_set_enum(g_settings_var, "number-format", math_equation_get_number_format(equation));
184}
185
186static void
187word_size_cb(MathEquation *equation, GParamSpec *spec, MathPreferencesDialog *dialog)
188{
189 set_combo_box_from_int(GET_WIDGET(dialog->priv->ui, "word_size_combobox")((((GtkWidget*) (void *) ((gtk_builder_get_object(dialog->
priv->ui, "word_size_combobox"))))))
, math_equation_get_word_size(equation));
190 g_settings_set_int(g_settings_var, "word-size", math_equation_get_word_size(equation));
191}
192
193static void
194angle_unit_cb(MathEquation *equation, GParamSpec *spec, MathPreferencesDialog *dialog)
195{
196 set_combo_box_from_int(GET_WIDGET(dialog->priv->ui, "angle_unit_combobox")((((GtkWidget*) (void *) ((gtk_builder_get_object(dialog->
priv->ui, "angle_unit_combobox"))))))
, math_equation_get_angle_units(equation));
197 g_settings_set_enum(g_settings_var, "angle-units", math_equation_get_angle_units(equation));
198}
199
200static void
201create_gui(MathPreferencesDialog *dialog)
202{
203 GtkWidget *widget;
204 GtkTreeModel *model;
205 GtkTreeIter iter;
206 GtkCellRenderer *renderer;
207 gchar *string, **tokens;
208 GError *error = NULL((void*)0);
209 static gchar *objects[] = { "preferences_table", "angle_unit_model", "number_format_model",
210 "word_size_model", "decimal_places_adjustment", "number_base_model", NULL((void*)0) };
211
212 // FIXME: Handle errors
213 dialog->priv->ui = gtk_builder_new();
214 gtk_builder_add_objects_from_resource(dialog->priv->ui, UI_DIALOGS_RESOURCE_PATH"/org/mate/calculator/ui/preferences.ui", objects, &error);
215 if (error)
216 g_warning("Error loading preferences UI: %s", error->message);
217 g_clear_error(&error);
218
219 gtk_window_set_title(GTK_WINDOW(dialog)((((GtkWindow*) (void *) ((dialog))))),
220 /* Title of preferences dialog */
221 _("Preferences")dcgettext (((void*)0), "Preferences", 5));
222 gtk_container_set_border_width(GTK_CONTAINER(dialog)((((GtkContainer*) (void *) ((dialog))))), 8);
223 gtk_dialog_add_button(GTK_DIALOG(dialog)((((GtkDialog*) (void *) ((dialog))))),
224 /* Icon name on close button in preferences dialog */
225 "gtk-close", GTK_RESPONSE_CLOSE);
226
227 gtk_window_set_icon_name (GTK_WINDOW(dialog)((((GtkWindow*) (void *) ((dialog))))), "accessories-calculator");
228
229 g_signal_connect(dialog, "response", G_CALLBACK(preferences_response_cb), NULL)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
preferences_response_cb))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
230 g_signal_connect(dialog, "delete-event", G_CALLBACK(preferences_dialog_delete_cb), NULL)g_signal_connect_data ((dialog), ("delete-event"), (((GCallback
) (preferences_dialog_delete_cb))), (((void*)0)), ((void*)0),
(GConnectFlags) 0)
;
231 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog)))((((GtkBox*) (void *) ((gtk_dialog_get_content_area(((((GtkDialog
*) (void *) ((dialog)))))))))))
, GET_WIDGET(dialog->priv->ui, "preferences_table")((((GtkWidget*) (void *) ((gtk_builder_get_object(dialog->
priv->ui, "preferences_table"))))))
, TRUE(!(0)), TRUE(!(0)), 0);
232
233 widget = GET_WIDGET(dialog->priv->ui, "angle_unit_combobox")((((GtkWidget*) (void *) ((gtk_builder_get_object(dialog->
priv->ui, "angle_unit_combobox"))))))
;
234 model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget)((((GtkComboBox*) (void *) ((widget))))));
235 gtk_list_store_append(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter);
236 gtk_list_store_set(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter, 0,
237 /* Preferences dialog: Angle unit combo box: Use degrees for trigonometric calculations */
238 _("Degrees")dcgettext (((void*)0), "Degrees", 5), 1, MP_DEGREES, -1);
239 gtk_list_store_append(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter);
240 gtk_list_store_set(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter, 0,
241 /* Preferences dialog: Angle unit combo box: Use radians for trigonometric calculations */
242 _("Radians")dcgettext (((void*)0), "Radians", 5), 1, MP_RADIANS, -1);
243 gtk_list_store_append(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter);
244 gtk_list_store_set(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter, 0,
245 /* Preferences dialog: Angle unit combo box: Use gradians for trigonometric calculations */
246 _("Gradians")dcgettext (((void*)0), "Gradians", 5), 1, MP_GRADIANS, -1);
247 renderer = gtk_cell_renderer_text_new();
248 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget)((((GtkCellLayout*) (void *) ((widget))))), renderer, TRUE(!(0)));
249 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget)((((GtkCellLayout*) (void *) ((widget))))), renderer, "text", 0);
250
251 widget = GET_WIDGET(dialog->priv->ui, "number_format_combobox")((((GtkWidget*) (void *) ((gtk_builder_get_object(dialog->
priv->ui, "number_format_combobox"))))))
;
252 model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget)((((GtkComboBox*) (void *) ((widget))))));
253 gtk_list_store_append(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter);
254 gtk_list_store_set(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter, 0,
255 /* Number display mode combo: Automatic, e.g. 1234 (or scientific for large number 1.234×10^99) */
256 _("Automatic")dcgettext (((void*)0), "Automatic", 5), 1, MP_DISPLAY_FORMAT_AUTOMATIC, -1);
257 gtk_list_store_append(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter);
258 gtk_list_store_set(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter, 0,
259 /* Number display mode combo: Fixed, e.g. 1234 */
260 _("Fixed")dcgettext (((void*)0), "Fixed", 5), 1, MP_DISPLAY_FORMAT_FIXED, -1);
261 gtk_list_store_append(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter);
262 gtk_list_store_set(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter, 0,
263 /* Number display mode combo: Scientific, e.g. 1.234×10^3 */
264 _("Scientific")dcgettext (((void*)0), "Scientific", 5), 1, MP_DISPLAY_FORMAT_SCIENTIFIC, -1);
265 gtk_list_store_append(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter);
266 gtk_list_store_set(GTK_LIST_STORE(model)((((GtkListStore*) (void *) ((model))))), &iter, 0,
267 /* Number display mode combo: Engineering, e.g. 1.234k */
268 _("Engineering")dcgettext (((void*)0), "Engineering", 5), 1, MP_DISPLAY_FORMAT_ENGINEERING, -1);
269 renderer = gtk_cell_renderer_text_new();
270 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget)((((GtkCellLayout*) (void *) ((widget))))), renderer, TRUE(!(0)));
271 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget)((((GtkCellLayout*) (void *) ((widget))))), renderer, "text", 0);
272
273 widget = GET_WIDGET(dialog->priv->ui, "word_size_combobox")((((GtkWidget*) (void *) ((gtk_builder_get_object(dialog->
priv->ui, "word_size_combobox"))))))
;
274 renderer = gtk_cell_renderer_text_new();
275 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget)((((GtkCellLayout*) (void *) ((widget))))), renderer, TRUE(!(0)));
276 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget)((((GtkCellLayout*) (void *) ((widget))))), renderer, "text", 0);
277
278 /* Label used in preferences dialog. The %d is replaced by a spinbutton */
279 string = _("Show %d decimal _places")dcgettext (((void*)0), "Show %d decimal _places", 5);
280 tokens = g_strsplit(string, "%d", 2);
281 widget = GET_WIDGET(dialog->priv->ui, "decimal_places_label1")((((GtkWidget*) (void *) ((gtk_builder_get_object(dialog->
priv->ui, "decimal_places_label1"))))))
;
282 if (tokens[0])
283 string = g_strstrip(tokens[0])g_strchomp (g_strchug (tokens[0]));
284 else
285 string = "";
286 if (string[0] != '\0')
287 gtk_label_set_text_with_mnemonic(GTK_LABEL(widget)((((GtkLabel*) (void *) ((widget))))), string);
288 else
289 gtk_widget_hide(widget);
290
291 widget = GET_WIDGET(dialog->priv->ui, "decimal_places_label2")((((GtkWidget*) (void *) ((gtk_builder_get_object(dialog->
priv->ui, "decimal_places_label2"))))))
;
292 if (tokens[0] && tokens[1])
293 string = g_strstrip(tokens[1])g_strchomp (g_strchug (tokens[1]));
294 else
295 string = "";
296 if (string[0] != '\0')
297 gtk_label_set_text_with_mnemonic(GTK_LABEL(widget)((((GtkLabel*) (void *) ((widget))))), string);
298 else
299 gtk_widget_hide(widget);
300
301 g_strfreev(tokens);
302
303 gtk_builder_connect_signals(dialog->priv->ui, dialog);
304
305 g_signal_connect(dialog->priv->equation, "notify::accuracy", G_CALLBACK(accuracy_cb), dialog)g_signal_connect_data ((dialog->priv->equation), ("notify::accuracy"
), (((GCallback) (accuracy_cb))), (dialog), ((void*)0), (GConnectFlags
) 0)
;
306 g_signal_connect(dialog->priv->equation, "notify::show-thousands-separators", G_CALLBACK(show_thousands_separators_cb), dialog)g_signal_connect_data ((dialog->priv->equation), ("notify::show-thousands-separators"
), (((GCallback) (show_thousands_separators_cb))), (dialog), (
(void*)0), (GConnectFlags) 0)
;
307 g_signal_connect(dialog->priv->equation, "notify::show-trailing_zeroes", G_CALLBACK(show_trailing_zeroes_cb), dialog)g_signal_connect_data ((dialog->priv->equation), ("notify::show-trailing_zeroes"
), (((GCallback) (show_trailing_zeroes_cb))), (dialog), ((void
*)0), (GConnectFlags) 0)
;
308 g_signal_connect(dialog->priv->equation, "notify::number-format", G_CALLBACK(number_format_cb), dialog)g_signal_connect_data ((dialog->priv->equation), ("notify::number-format"
), (((GCallback) (number_format_cb))), (dialog), ((void*)0), (
GConnectFlags) 0)
;
309 g_signal_connect(dialog->priv->equation, "notify::word-size", G_CALLBACK(word_size_cb), dialog)g_signal_connect_data ((dialog->priv->equation), ("notify::word-size"
), (((GCallback) (word_size_cb))), (dialog), ((void*)0), (GConnectFlags
) 0)
;
310 g_signal_connect(dialog->priv->equation, "notify::angle-units", G_CALLBACK(angle_unit_cb), dialog)g_signal_connect_data ((dialog->priv->equation), ("notify::angle-units"
), (((GCallback) (angle_unit_cb))), (dialog), ((void*)0), (GConnectFlags
) 0)
;
311
312 accuracy_cb(dialog->priv->equation, NULL((void*)0), dialog);
313 show_thousands_separators_cb(dialog->priv->equation, NULL((void*)0), dialog);
314 show_trailing_zeroes_cb(dialog->priv->equation, NULL((void*)0), dialog);
315 number_format_cb(dialog->priv->equation, NULL((void*)0), dialog);
316 word_size_cb(dialog->priv->equation, NULL((void*)0), dialog);
317 angle_unit_cb(dialog->priv->equation, NULL((void*)0), dialog);
318}
319
320static void
321math_preferences_set_property(GObject *object,
322 guint prop_id,
323 const GValue *value,
324 GParamSpec *pspec)
325{
326 MathPreferencesDialog *self;
327
328 self = MATH_PREFERENCES(object)((((MathPreferencesDialog*) (void *) ((object)))));
329
330 switch (prop_id) {
331 case PROP_EQUATION:
332 self->priv->equation = g_value_get_object(value);
333 create_gui(self);
334 break;
335 default:
336 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "math-preferences.c", 336, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
337 break;
338 }
339}
340
341static void
342math_preferences_get_property(GObject *object,
343 guint prop_id,
344 GValue *value,
345 GParamSpec *pspec)
346{
347 MathPreferencesDialog *self;
348
349 self = MATH_PREFERENCES(object)((((MathPreferencesDialog*) (void *) ((object)))));
350
351 switch (prop_id) {
352 case PROP_EQUATION:
353 g_value_set_object(value, self->priv->equation);
354 break;
355 default:
356 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "math-preferences.c", 356, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
357 break;
358 }
359}
360
361static void
362math_preferences_class_init(MathPreferencesDialogClass *klass)
363{
364 GObjectClass *object_class = G_OBJECT_CLASS(klass)((((GObjectClass*) (void *) ((klass)))));
365
366 object_class->get_property = math_preferences_get_property;
367 object_class->set_property = math_preferences_set_property;
368
369 g_object_class_install_property(object_class,
370 PROP_EQUATION,
371 g_param_spec_object("equation",
372 "equation",
373 "Equation being configured",
374 math_equation_get_type(),
375 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
376}
377
378static void
379math_preferences_init(MathPreferencesDialog *dialog)
380{
381 dialog->priv = math_preferences_get_instance_private (dialog);
382}
diff --git a/2024-07-10-100902-3667-1@fe495df3ec39_master/scanview.css b/2024-07-10-100902-3667-1@fe495df3ec39_master/scanview.css new file mode 100644 index 0000000..cf8a5a6 --- /dev/null +++ b/2024-07-10-100902-3667-1@fe495df3ec39_master/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2024-07-10-100902-3667-1@fe495df3ec39_master/sorttable.js b/2024-07-10-100902-3667-1@fe495df3ec39_master/sorttable.js new file mode 100644 index 0000000..32faa07 --- /dev/null +++ b/2024-07-10-100902-3667-1@fe495df3ec39_master/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write("