mruby/c VM Source Code master (2026/08/06)
Loading...
Searching...
No Matches
symbol.c
Go to the documentation of this file.
1
14
15/***** Feature test switches ************************************************/
16/***** System headers *******************************************************/
17//@cond
18#include "vm_config.h"
19#include <stdint.h>
20#include <string.h>
21#include <limits.h>
22#include <assert.h>
23//@endcond
24
25/***** Local headers ********************************************************/
26#define MRBC_DEFINE_SYMBOL_TABLE
27#include "_autogen_builtin_symbol.h"
28#undef MRBC_DEFINE_SYMBOL_TABLE
29#include "mrubyc.h"
30
31/***** Constant values ******************************************************/
32#if !defined(MRBC_SYMBOL_SEARCH_LINEAR) && !defined(MRBC_SYMBOL_SEARCH_BTREE)
33#define MRBC_SYMBOL_SEARCH_BTREE
34#endif
35
36#define OFFSET_BUILTIN_SYMBOL 512
37#if OFFSET_BUILTIN_SYMBOL <= MRBC_BUILTIN_SYMBOL_MAX
38# error OFFSET_BUILTIN_SYMBOL overflow. Please increase the value.
39#endif
40
41
42/***** Macros ***************************************************************/
43/***** Typedefs *************************************************************/
44struct SYM_INDEX {
45 uint16_t hash;
46#ifdef MRBC_SYMBOL_SEARCH_BTREE
47#if MAX_SYMBOLS_COUNT <= UCHAR_MAX
48 uint8_t left, right;
49#else
50 uint16_t left, right;
51#endif
52#endif
53 const char *cstr;
54};
55
56
57/***** Function prototypes **************************************************/
58/***** Local variables ******************************************************/
60static int sym_index_pos; // point to the last(free) sym_index array.
61
62
63/***** Global variables *****************************************************/
64/***** Signal catching functions ********************************************/
65/***** Local functions ******************************************************/
66
67//================================================================
73static inline uint16_t calc_hash(const char *str)
74{
75 uint16_t h = 0;
76
77 while( *str != '\0' ) {
78 h = h * 17 + *str++;
79 }
80 return h;
81}
82
83
84//================================================================
90static int search_builtin_symbol( const char *str )
91{
92 int left = 1;
93 int right = sizeof(builtin_symbols) / sizeof(builtin_symbols[0]);
94
95 while( left < right ) {
96 int mid = (left + right) / 2;
97 const unsigned char *p1 = (const unsigned char *)builtin_symbols[mid];
98 const unsigned char *p2 = (const unsigned char *)str;
99
100 while( 1 ) { // string compare, same order as cruby.
101 if( *p1 < *p2 ) {
102 left = mid + 1;
103 break;
104 }
105 if( *p1 > *p2 ) {
106 right = mid;
107 break;
108 }
109 if( *p1 == 0 ) {
110 return mid;
111 }
112
113 p1++;
114 p2++;
115 }
116 }
117
118 return -1;
119}
120
121
122//================================================================
129static int search_index( uint16_t hash, const char *str )
130{
131#ifdef MRBC_SYMBOL_SEARCH_LINEAR
132 for( int i = 0; i < sym_index_pos; i++ ) {
133 if( sym_index[i].hash == hash && strcmp(str, sym_index[i].cstr) == 0 ) {
134 return i;
135 }
136 }
137 return -1;
138#endif
139
140#ifdef MRBC_SYMBOL_SEARCH_BTREE
141 int i = 0;
142 do {
143 if( sym_index[i].hash == hash && strcmp(str, sym_index[i].cstr) == 0 ) {
144 return i;
145 }
146 if( hash < sym_index[i].hash ) {
147 i = sym_index[i].left;
148 } else {
149 i = sym_index[i].right;
150 }
151 } while( i != 0 );
152 return -1;
153#endif
154}
155
156
157//================================================================
164static int add_index( uint16_t hash, const char *str )
165{
166 if( sym_index_pos >= MAX_SYMBOLS_COUNT ) return -1; // check overflow.
167
168 int idx = sym_index_pos++;
169
170 // append table.
171 sym_index[idx].hash = hash;
172 sym_index[idx].cstr = str;
173
174#ifdef MRBC_SYMBOL_SEARCH_BTREE
175 int i = 0;
176
177 while( 1 ) {
178 if( hash < sym_index[i].hash ) {
179 // left side
180 if( sym_index[i].left == 0 ) { // left is empty?
181 sym_index[i].left = idx;
182 break;
183 }
184 i = sym_index[i].left;
185 } else {
186 // right side
187 if( sym_index[i].right == 0 ) { // right is empty?
188 sym_index[i].right = idx;
189 break;
190 }
191 i = sym_index[i].right;
192 }
193 }
194#endif
195
196 return idx;
197}
198
199
200/***** Global functions *****************************************************/
201
202//================================================================
206{
207 memset(sym_index, 0, sizeof(sym_index));
208 sym_index_pos = 0;
209}
210
211
212//================================================================
219{
220 mrbc_sym sym_id = search_builtin_symbol(str);
221 if( sym_id >= 0 ) return sym_id;
222
223 uint16_t h = calc_hash(str);
224 sym_id = search_index(h, str);
225 if( sym_id < 0 ) sym_id = add_index( h, str );
226 if( sym_id < 0 ) return sym_id;
227
228 return sym_id + OFFSET_BUILTIN_SYMBOL;
229}
230
231
232//================================================================
239const char * mrbc_symid_to_str(mrbc_sym sym_id)
240{
241 if( sym_id < OFFSET_BUILTIN_SYMBOL ) {
242 return builtin_symbols[sym_id];
243 }
244
245 sym_id -= OFFSET_BUILTIN_SYMBOL;
246 if( sym_id < 0 ) return "";
247 if( sym_id >= sym_index_pos ) return "";
248
249 return sym_index[sym_id].cstr;
250}
251
252
253//================================================================
259mrbc_sym mrbc_search_symid( const char *str )
260{
261 mrbc_sym sym_id = search_builtin_symbol(str);
262 if( sym_id >= 0 ) return sym_id;
263
264 uint16_t h = calc_hash(str);
265 sym_id = search_index(h, str);
266 if( sym_id < 0 ) return sym_id;
267
268 return sym_id + OFFSET_BUILTIN_SYMBOL;
269}
270
271
272//================================================================
279void mrbc_make_nested_symbol_s( char *buf, mrbc_sym id1, mrbc_sym id2 )
280{
281 /*
282 index: 0 1 2 3 4 5 6 7 8 9
283 format: "\x01 id1(ascii 4bytes) id2(ascii 4bytes) \x00"
284 */
285 assert( sizeof(mrbc_sym) == 2 );
286
287 uint8_t *p = (uint8_t*)buf + 9;
288
289 *p-- = 0;
290
291 for( int i = 0; i < 4; i++ ) {
292 *p-- = '0' + (id2 & 0x0f);
293 id2 >>= 4;
294 }
295 for( int i = 0; i < 4; i++ ) {
296 *p-- = '0' + (id1 & 0x0f);
297 id1 >>= 4;
298 }
299
300 *p = 0x01;
301}
302
303
304//================================================================
313{
314 assert( mrbc_is_nested_symid( sym_id ));
315
316 const char *p = mrbc_symid_to_str(sym_id);
317
318 *id1 = *id2 = 0;
319 for( int i = 0; i < 4; i++ ) {
320 *id1 = (*id1 << 4) + (*++p - '0');
321 }
322 for( int i = 0; i < 4; i++ ) {
323 *id2 = (*id2 << 4) + (*++p - '0');
324 }
325}
326
327
328//================================================================
335mrbc_value mrbc_symbol_new(struct VM *vm, const char *str)
336{
337 mrbc_sym sym_id = mrbc_search_symid( str );
338 if( sym_id >= 0 ) goto DONE;
339
340 // create symbol object dynamically.
341 int size = strlen(str) + 1;
342 char *buf = mrbc_raw_alloc_no_free(size);
343
344 memcpy(buf, str, size);
345 sym_id = add_index( calc_hash(buf), buf );
346 if( sym_id < 0 ) {
347 mrbc_raisef(vm, MRBC_CLASS(Exception),
348 "Overflow MAX_SYMBOLS_COUNT for '%s'", str );
349 return mrbc_nil_value();
350 }
351
352 sym_id += OFFSET_BUILTIN_SYMBOL;
353
354 DONE:
355 return mrbc_symbol_value( sym_id );
356}
357
358
359/***** mruby/c methods ******************************************************/
360
361//================================================================
364static void c_symbol_all_symbols(struct VM *vm, mrbc_value v[], int argc)
365{
367
368 for( int i = 0; i < sizeof(builtin_symbols) / sizeof(builtin_symbols[0]); i++ ) {
370 }
371
372 for( int i = 0; i < sym_index_pos; i++ ) {
374 }
375 SET_RETURN(ret);
376}
377
378
379#if MRBC_USE_STRING
380//================================================================
383static void c_symbol_inspect(struct VM *vm, mrbc_value v[], int argc)
384{
385 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
386 mrbc_object_inspect(vm, v, argc);
387 return;
388 }
389
390 const char *s = mrbc_symid_to_str( mrbc_symbol(v[0]) );
391
392 if( strchr(s, ':') ) {
393 v[0] = mrbc_string_new_cstr(vm, ":\"");
394 mrbc_string_append_cstr(&v[0], s);
395 mrbc_string_append_cstr(&v[0], "\"");
396 } else {
397 v[0] = mrbc_string_new_cstr(vm, ":");
398 mrbc_string_append_cstr(&v[0], s);
399 }
400}
401
402
403//================================================================
406static void c_symbol_to_s(struct VM *vm, mrbc_value v[], int argc)
407{
408 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
409 mrbc_object_inspect(vm, v, argc);
410 return;
411 }
412
414}
415#endif
416
417
418/* MRBC_AUTOGEN_METHOD_TABLE
419
420 CLASS("Symbol")
421 FILE("_autogen_class_symbol.h")
422
423 METHOD( "all_symbols", c_symbol_all_symbols )
424#if MRBC_USE_STRING
425 METHOD( "inspect", c_symbol_inspect )
426 METHOD( "to_s", c_symbol_to_s )
427 METHOD( "id2name", c_symbol_to_s )
428#endif
429 METHOD( "to_sym", c_ineffect )
430*/
431#include "_autogen_class_symbol.h"
432
433
434
435#if defined(MRBC_DEBUG)
436//================================================================
442void mrbc_debug_dump_symbol(void)
443{
444 mrbc_printf("<< Symbol table dump >>\n");
445
446 for( int i = 0; i < sym_index_pos; i++ ) {
447 mrbc_sym sym_id = i + OFFSET_BUILTIN_SYMBOL;
448 mrbc_printf(" %04x: %s", sym_id, sym_index[i].cstr );
449 if( mrbc_is_nested_symid(sym_id) ) {
450 mrbc_printf(" as ");
451 mrbc_print_symbol(sym_id);
452 }
453 mrbc_printf("\n");
454 }
455
456 mrbc_printf("\n");
457}
458
459
460//================================================================
469void mrbc_symbol_statistics( int *total_used )
470{
471 *total_used = sym_index_pos;
472}
473#endif
void * mrbc_raw_alloc_no_free(unsigned int size)
Definition alloc.c:631
#define mrbc_symbol(o)
Definition boxing_no.h:62
#define mrbc_nil_value()
Definition boxing_no.h:70
#define mrbc_symbol_value(n)
Definition boxing_no.h:74
#define mrbc_type(o)
Definition boxing_no.h:57
struct RObject mrbc_value
Value object. Default version.
int mrbc_array_push(mrbc_value *ary, mrbc_value *set_val)
Definition c_array.c:243
mrbc_value mrbc_array_new(mrbc_vm *vm, int size)
Definition c_array.c:83
void mrbc_object_inspect(mrbc_vm *vm, mrbc_value v[], int argc)
Definition c_object.c:91
static int mrbc_string_append_cstr(mrbc_value *s1, const char *s2)
Definition c_string.h:134
static mrbc_value mrbc_string_new_cstr(mrbc_vm *vm, const char *src)
Definition c_string.h:91
#define MRBC_CLASS(cls)
Definition class.h:55
void mrbc_printf(const char *fstr,...)
Definition console.c:205
void mrbc_print_symbol(mrbc_sym sym_id)
Definition console.c:152
void mrbc_raisef(struct VM *vm, struct RClass *exc_cls, const char *fstr,...)
Definition error.c:168
Include at once the necessary header files.
uint16_t hash
hash value, returned by calc_hash().
Definition symbol.c:45
uint8_t left
Definition symbol.c:48
uint8_t right
Definition symbol.c:48
const char * cstr
point to the symbol string.
Definition symbol.c:53
Virtual Machine.
Definition vm.h:150
mrbc_sym mrbc_search_symid(const char *str)
Definition symbol.c:259
static int sym_index_pos
Definition symbol.c:60
mrbc_value mrbc_symbol_new(struct VM *vm, const char *str)
Definition symbol.c:335
mrbc_sym mrbc_str_to_symid(const char *str)
Definition symbol.c:218
static int search_index(uint16_t hash, const char *str)
Definition symbol.c:129
static int add_index(uint16_t hash, const char *str)
Definition symbol.c:164
void mrbc_make_nested_symbol_s(char *buf, mrbc_sym id1, mrbc_sym id2)
Definition symbol.c:279
void mrbc_separate_nested_symid(mrbc_sym sym_id, mrbc_sym *id1, mrbc_sym *id2)
Definition symbol.c:312
void mrbc_cleanup_symbol(void)
Definition symbol.c:205
static uint16_t calc_hash(const char *str)
Definition symbol.c:73
const char * mrbc_symid_to_str(mrbc_sym sym_id)
Definition symbol.c:239
#define OFFSET_BUILTIN_SYMBOL
Definition symbol.c:36
static struct SYM_INDEX sym_index[MAX_SYMBOLS_COUNT]
Definition symbol.c:59
static int search_builtin_symbol(const char *str)
Definition symbol.c:90
static int mrbc_is_nested_symid(mrbc_sym sym_id)
Definition symbol.h:74
int16_t mrbc_sym
mruby/c symbol ID
Definition value.h:62
@ MRBC_TT_CLASS
Class.
Definition value.h:90
#define SET_RETURN(n)
Definition value.h:221
Global configuration of mruby/c VM's.
#define MAX_SYMBOLS_COUNT
Definition vm_config.h:30