GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/joels/Current/lispbm/src/extensions.c Lines: 54 76 71.1 %
Date: 2024-12-05 14:36:58 Branches: 23 40 57.5 %

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 ext_num    = 0;
31
static lbm_uint next_extension_ix = 0;
32
33
lbm_extension_t *extension_table = NULL;
34
35
lbm_value lbm_extensions_default(lbm_value *args, lbm_uint argn) {
36
  (void)args;
37
  (void)argn;
38
  return ENC_SYM_EERROR;
39
}
40
41
21672
int lbm_extensions_init(lbm_extension_t *extension_storage, lbm_uint extension_storage_size) {
42

21672
  if (extension_storage == NULL || extension_storage_size == 0) return 0;
43
44
21672
  extension_table = extension_storage;
45
21672
  memset(extension_table, 0, sizeof(lbm_extension_t) * extension_storage_size);
46
47
4356072
  for (lbm_uint i = 0; i < extension_storage_size; i ++) {
48
4334400
    extension_storage[i].fptr = lbm_extensions_default;
49
  }
50
51
21672
  ext_num = 0;
52
21672
  next_extension_ix = 0;
53
21672
  ext_max = (lbm_uint)extension_storage_size;
54
55
21672
  return 1;
56
}
57
58
665630540
lbm_uint lbm_get_max_extensions(void) {
59
665630540
  return ext_max;
60
}
61
62
21672
lbm_uint lbm_get_num_extensions(void) {
63
21672
  return ext_num;
64
}
65
66
14
extension_fptr lbm_get_extension(lbm_uint sym) {
67
14
  lbm_uint ext_next = sym - EXTENSION_SYMBOLS_START;
68
14
  if (ext_next >= ext_max) {
69
    return NULL;
70
  }
71
14
  return extension_table[ext_next].fptr;
72
}
73
74
bool lbm_clr_extension(lbm_uint sym_id) {
75
  lbm_uint ext_id = SYMBOL_IX(sym_id);
76
  if (ext_id >= ext_max) {
77
    return false;
78
  }
79
  extension_table[ext_id].name = NULL;
80
  extension_table[ext_id].fptr = lbm_extensions_default;
81
  return true;
82
}
83
84
14
bool lbm_lookup_extension_id(char *sym_str, lbm_uint *ix) {
85
1498
  for (lbm_uint i = 0; i < ext_max; i ++) {
86
1498
    if(extension_table[i].name) {
87
1498
      if (str_eq(extension_table[i].name, sym_str)) {
88
14
        *ix = i + EXTENSION_SYMBOLS_START;
89
14
        return true;
90
      }
91
    }
92
  }
93
  return false;
94
}
95
96
2297274
bool lbm_add_extension(char *sym_str, extension_fptr ext) {
97
  lbm_value symbol;
98
99
  // Check if symbol already exists.
100
2297274
  if (lbm_get_symbol_by_name(sym_str, &symbol)) {
101
14
    if (lbm_is_extension(lbm_enc_sym(symbol))) {
102
      // update the extension entry.
103
14
      if (str_eq(extension_table[SYMBOL_IX(symbol)].name, sym_str)) {
104
        // Do not replace name ptr.
105
14
        extension_table[SYMBOL_IX(symbol)].fptr = ext;
106
14
        return true;
107
      }
108
    }
109
    return false;
110
  }
111
112
2297260
  if (next_extension_ix < ext_max) {
113
2297260
    lbm_uint sym_ix = next_extension_ix ++;
114
2297260
    extension_table[sym_ix].name = sym_str;
115
2297260
    extension_table[sym_ix].fptr = ext;
116
2297260
    ext_num ++;
117
2297260
    return true;
118
  }
119
  return false;
120
}
121
122
// Helpers for extension developers:
123
124
3360
static bool lbm_is_number_all(lbm_value *args, lbm_uint argn) {
125
10836
  for (lbm_uint i = 0;i < argn;i++) {
126
7476
    if (!lbm_is_number(args[i])) {
127
      return false;
128
    }
129
  }
130
3360
  return true;
131
}
132
133
bool lbm_check_true_false(lbm_value v) {
134
  bool res = lbm_is_symbol_true(v) || lbm_is_symbol_nil(v);
135
  lbm_set_error_reason((char*)lbm_error_str_not_a_boolean);
136
  return res;
137
}
138
139
2408
bool lbm_check_number_all(lbm_value *args, lbm_uint argn) {
140
2408
  if (!lbm_is_number_all(args, argn)) {
141
    lbm_set_error_reason((char*)lbm_error_str_no_number);
142
    return false;
143
  }
144
2408
  return true;
145
}
146
147
84
bool lbm_check_argn(lbm_uint argn, lbm_uint n) {
148
84
  if (argn != n) {
149
28
    lbm_set_error_reason((char*)lbm_error_str_num_args);
150
28
    return false;
151
  } else {
152
56
    return true;
153
  }
154
}
155
156
952
bool lbm_check_argn_number(lbm_value *args, lbm_uint argn, lbm_uint n) {
157
952
  if (!lbm_is_number_all(args, argn)) {
158
    lbm_set_error_reason((char*)lbm_error_str_no_number);
159
    return false;
160
952
  } else if (argn != n) {
161
420
    lbm_set_error_reason((char*)lbm_error_str_num_args);
162
420
    return false;
163
  } else {
164
532
    return true;
165
  }
166
}