Bug Summary

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