GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/joels/Current/lispbm/src/extensions.c Lines: 68 92 73.9 %
Date: 2025-04-09 11:39:30 Branches: 30 46 65.2 %

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
void lbm_extensions_set_next(lbm_uint i) {
35
  next_extension_ix = i;
36
}
37
38
lbm_value lbm_extensions_default(lbm_value *args, lbm_uint argn) {
39
  (void)args;
40
  (void)argn;
41
  return ENC_SYM_EERROR;
42
}
43
44
21924
int lbm_extensions_init(lbm_extension_t *extension_storage, lbm_uint extension_storage_size) {
45

21924
  if (extension_storage == NULL || extension_storage_size == 0) return 0;
46
47
21924
  extension_table = extension_storage;
48
21924
  memset(extension_table, 0, sizeof(lbm_extension_t) * extension_storage_size);
49
50
4406724
  for (lbm_uint i = 0; i < extension_storage_size; i ++) {
51
4384800
    extension_storage[i].fptr = lbm_extensions_default;
52
  }
53
54
21924
  next_extension_ix = 0;
55
21924
  ext_max = (lbm_uint)extension_storage_size;
56
57
21924
  return 1;
58
}
59
60
689884832
lbm_uint lbm_get_max_extensions(void) {
61
689884832
  return ext_max;
62
}
63
64
21924
lbm_uint lbm_get_num_extensions(void) {
65
21924
  return next_extension_ix;
66
}
67
68
14
extension_fptr lbm_get_extension(lbm_uint sym) {
69
14
  lbm_uint ext_next = sym - EXTENSION_SYMBOLS_START;
70
14
  if (ext_next >= ext_max) {
71
    return NULL;
72
  }
73
14
  return extension_table[ext_next].fptr;
74
}
75
76
bool lbm_clr_extension(lbm_uint sym_id) {
77
  lbm_uint ext_id = SYMBOL_IX(sym_id);
78
  if (ext_id >= ext_max) {
79
    return false;
80
  }
81
  extension_table[ext_id].name = NULL;
82
  extension_table[ext_id].fptr = lbm_extensions_default;
83
  return true;
84
}
85
86
14
bool lbm_lookup_extension_id(char *sym_str, lbm_uint *ix) {
87
1484
  for (lbm_uint i = 0; i < ext_max; i ++) {
88
1484
    if(extension_table[i].name) {
89
1484
      if (str_eq(extension_table[i].name, sym_str)) {
90
14
        *ix = i + EXTENSION_SYMBOLS_START;
91
14
        return true;
92
      }
93
    }
94
  }
95
  return false;
96
}
97
98
2302062
bool lbm_add_extension(char *sym_str, extension_fptr ext) {
99
  lbm_value symbol;
100
101
  // symbol_by_name loops through all symbols. It may be enough
102
  // to search only the extension table, but unsure what the effect will
103
  // be if adding an extension with same str-name as a built-in or special
104
  // form. The extension may override built-in...
105
  //
106
  // Check if symbol already exists.
107
2302062
  if (lbm_get_symbol_by_name(sym_str, &symbol)) {
108
14
    if (lbm_is_extension(lbm_enc_sym(symbol))) {
109
      // update the extension entry.
110
14
      extension_table[SYMBOL_IX(symbol)].fptr = ext;
111
14
      return true;
112
    }
113
    return false;
114
  }
115
116
2302048
  if (next_extension_ix < ext_max) {
117
2302048
    lbm_uint sym_ix = next_extension_ix ++;
118
2302048
    extension_table[sym_ix].name = sym_str;
119
2302048
    extension_table[sym_ix].fptr = ext;
120
2302048
    return true;
121
  }
122
  return false;
123
}
124
125
// Helpers for extension developers:
126
127
3164
static bool lbm_is_number_all(lbm_value *args, lbm_uint argn) {
128
9940
  for (lbm_uint i = 0;i < argn;i++) {
129
6776
    if (!lbm_is_number(args[i])) {
130
      return false;
131
    }
132
  }
133
3164
  return true;
134
}
135
136
bool lbm_check_true_false(lbm_value v) {
137
  bool res = lbm_is_symbol_true(v) || lbm_is_symbol_nil(v);
138
  lbm_set_error_reason((char*)lbm_error_str_not_a_boolean);
139
  return res;
140
}
141
142
2212
bool lbm_check_number_all(lbm_value *args, lbm_uint argn) {
143
2212
  if (!lbm_is_number_all(args, argn)) {
144
    lbm_set_error_reason((char*)lbm_error_str_no_number);
145
    return false;
146
  }
147
2212
  return true;
148
}
149
150
84
bool lbm_check_argn(lbm_uint argn, lbm_uint n) {
151
84
  if (argn != n) {
152
28
    lbm_set_error_reason((char*)lbm_error_str_num_args);
153
28
    return false;
154
  } else {
155
56
    return true;
156
  }
157
}
158
159
952
bool lbm_check_argn_number(lbm_value *args, lbm_uint argn, lbm_uint n) {
160
952
  if (!lbm_is_number_all(args, argn)) {
161
    lbm_set_error_reason((char*)lbm_error_str_no_number);
162
    return false;
163
952
  } else if (argn != n) {
164
420
    lbm_set_error_reason((char*)lbm_error_str_num_args);
165
420
    return false;
166
  } else {
167
532
    return true;
168
  }
169
}
170
171
10316
lbm_value make_list(int num, ...) {
172
  va_list arguments;
173
10316
  va_start (arguments, num);
174
10316
  lbm_value res = ENC_SYM_NIL;
175
36304
  for (int i = 0; i < num; i++) {
176
25988
    res = lbm_cons(va_arg(arguments, lbm_value), res);
177
  }
178
10316
  va_end (arguments);
179
10316
  return lbm_list_destructive_reverse(res);
180
}
181
182
13068
bool strmatch(const char *str1, const char *str2) {
183
13068
  size_t len = strlen(str1);
184
185
13068
  if (str2[len] != ' ') {
186
10074
    return false;
187
  }
188
189
2994
  bool same = true;
190
13872
  for (unsigned int i = 0;i < len;i++) {
191
12922
    if (str1[i] != str2[i]) {
192
2044
      same = false;
193
2044
      break;
194
    }
195
  }
196
197
2994
  return same;
198
}