GCC Code Coverage Report


Directory: ../src/
File: /home/joels/Current/lispbm/src/extensions.c
Date: 2025-10-28 15:15:18
Exec Total Coverage
Lines: 90 90 100.0%
Functions: 15 15 100.0%
Branches: 42 42 100.0%

Line Branch Exec Source
1 /*
2 Copyright 2019, 2021, 2022, 2024 Joel Svensson svenssonjoel@yahoo.se
3 2022 Benjamin Vedder
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <lbm_memory.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stdbool.h>
23 #include <string.h>
24 #include <eval_cps.h>
25
26 #include "extensions.h"
27 #include "lbm_utils.h"
28
29 static lbm_uint ext_max = 0;
30 static lbm_uint next_extension_ix = 0;
31
32 lbm_extension_t *extension_table = NULL;
33
34 75 void lbm_extensions_set_next(lbm_uint i) {
35 75 next_extension_ix = i;
36 75 }
37
38 1 lbm_value lbm_extensions_default(lbm_value *args, lbm_uint argn) {
39 (void)args;
40 (void)argn;
41 1 return ENC_SYM_EERROR;
42 }
43
44 66577 bool lbm_extensions_init(lbm_extension_t *extension_storage, lbm_uint extension_storage_size) {
45
4/4
✓ Branch 0 taken 66576 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 66575 times.
66577 if (extension_storage == NULL || extension_storage_size == 0) return false;
46
47 66575 extension_table = extension_storage;
48 66575 memset(extension_table, 0, sizeof(lbm_extension_t) * extension_storage_size);
49
50
2/2
✓ Branch 0 taken 14793522 times.
✓ Branch 1 taken 66575 times.
14860097 for (lbm_uint i = 0; i < extension_storage_size; i ++) {
51 14793522 extension_storage[i].fptr = lbm_extensions_default;
52 }
53
54 66575 next_extension_ix = 0;
55 66575 ext_max = (lbm_uint)extension_storage_size;
56
57 66575 return true;
58 }
59
60 3103333583 lbm_uint lbm_get_max_extensions(void) {
61 3103333583 return ext_max;
62 }
63
64 76369 lbm_uint lbm_get_num_extensions(void) {
65 76369 return next_extension_ix;
66 }
67
68 3 extension_fptr lbm_get_extension(lbm_uint sym) {
69 3 lbm_uint ext_id = sym - EXTENSION_SYMBOLS_START;
70 3 extension_fptr res = lbm_extensions_default;
71
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (ext_id < ext_max) {
72 2 res = extension_table[ext_id].fptr;
73 }
74 3 return res;
75 }
76
77 2 bool lbm_clr_extension(lbm_uint sym_id) {
78 2 lbm_uint ext_id = SYMBOL_IX(sym_id);
79
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (ext_id >= ext_max) {
80 1 return false;
81 }
82 1 extension_table[ext_id].name = NULL;
83 1 extension_table[ext_id].fptr = lbm_extensions_default;
84 1 return true;
85 }
86
87 44 bool lbm_lookup_extension_id(char *sym_str, lbm_uint *ix) {
88
2/2
✓ Branch 0 taken 4505 times.
✓ Branch 1 taken 1 times.
4506 for (lbm_uint i = 0; i < ext_max; i ++) {
89
2/2
✓ Branch 0 taken 4496 times.
✓ Branch 1 taken 9 times.
4505 if(extension_table[i].name) {
90
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 4453 times.
4496 if (str_eq(extension_table[i].name, sym_str)) {
91 43 *ix = i + EXTENSION_SYMBOLS_START;
92 43 return true;
93 }
94 }
95 }
96 1 return false;
97 }
98
99 7063435 bool lbm_add_extension(char *sym_str, extension_fptr ext) {
100 lbm_value symbol;
101
102 // symbol_by_name loops through all symbols. It may be enough
103 // to search only the extension table, but unsure what the effect will
104 // be if adding an extension with same str-name as a built-in or special
105 // form. The extension may override built-in...
106 //
107 // Check if symbol already exists.
108
2/2
✓ Branch 0 taken 9538 times.
✓ Branch 1 taken 7053897 times.
7063435 if (lbm_get_symbol_by_name(sym_str, &symbol)) {
109
2/2
✓ Branch 0 taken 9535 times.
✓ Branch 1 taken 3 times.
9538 if (lbm_is_extension(lbm_enc_sym(symbol))) {
110 // update the extension entry.
111 9535 extension_table[SYMBOL_IX(symbol)].fptr = ext;
112 9535 return true;
113 }
114 3 return false;
115 }
116
117
2/2
✓ Branch 0 taken 7053896 times.
✓ Branch 1 taken 1 times.
7053897 if (next_extension_ix < ext_max) {
118 7053896 lbm_uint sym_ix = next_extension_ix ++;
119 7053896 extension_table[sym_ix].name = sym_str;
120 7053896 extension_table[sym_ix].fptr = ext;
121 7053896 return true;
122 }
123 1 return false;
124 }
125
126 // Helpers for extension developers:
127
128 9586 static bool lbm_is_number_all(lbm_value *args, lbm_uint argn) {
129
2/2
✓ Branch 0 taken 20437 times.
✓ Branch 1 taken 9557 times.
29994 for (lbm_uint i = 0;i < argn;i++) {
130
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 20408 times.
20437 if (!lbm_is_number(args[i])) {
131 29 return false;
132 }
133 }
134 9557 return true;
135 }
136
137 6650 bool lbm_check_number_all(lbm_value *args, lbm_uint argn) {
138
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6646 times.
6650 if (!lbm_is_number_all(args, argn)) {
139 4 lbm_set_error_reason((char*)lbm_error_str_no_number);
140 4 return false;
141 }
142 6646 return true;
143 }
144
145 268 bool lbm_check_argn(lbm_uint argn, lbm_uint n) {
146
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 182 times.
268 if (argn != n) {
147 86 lbm_set_error_reason((char*)lbm_error_str_num_args);
148 86 return false;
149 } else {
150 182 return true;
151 }
152 }
153
154 2936 bool lbm_check_argn_number(lbm_value *args, lbm_uint argn, lbm_uint n) {
155
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 2911 times.
2936 if (!lbm_is_number_all(args, argn)) {
156 25 lbm_set_error_reason((char*)lbm_error_str_no_number);
157 25 return false;
158
2/2
✓ Branch 0 taken 1264 times.
✓ Branch 1 taken 1647 times.
2911 } else if (argn != n) {
159 1264 lbm_set_error_reason((char*)lbm_error_str_num_args);
160 1264 return false;
161 } else {
162 1647 return true;
163 }
164 }
165
166 31838 lbm_value make_list(int num, ...) {
167 va_list arguments;
168 31838 va_start (arguments, num);
169 31838 lbm_value res = ENC_SYM_NIL;
170
2/2
✓ Branch 0 taken 80406 times.
✓ Branch 1 taken 31838 times.
112244 for (int i = 0; i < num; i++) {
171 80406 res = lbm_cons(va_arg(arguments, lbm_value), res);
172 }
173 31838 va_end (arguments);
174 31838 return lbm_list_destructive_reverse(res);
175 }
176
177 39499 bool strmatch(const char *str1, const char *str2) {
178 39499 size_t len = strlen(str1);
179
180
2/2
✓ Branch 0 taken 31064 times.
✓ Branch 1 taken 8435 times.
39499 if (str2[len] != ' ') {
181 31064 return false;
182 }
183
184 8435 bool same = true;
185
2/2
✓ Branch 0 taken 39918 times.
✓ Branch 1 taken 3131 times.
43049 for (unsigned int i = 0;i < len;i++) {
186
2/2
✓ Branch 0 taken 5304 times.
✓ Branch 1 taken 34614 times.
39918 if (str1[i] != str2[i]) {
187 5304 same = false;
188 5304 break;
189 }
190 }
191
192 8435 return same;
193 }
194