@@ -147,7 +147,7 @@ static const char *intern_variable_name(const char *name, size_t len)
147147
148148 existing = hashmap_get (
149149 interned_variable_names ,
150- & (struct interned_name ) { .name = name }
150+ & (struct interned_name ) { .name = name , . name_length = len }
151151 );
152152
153153 if (existing ) {
@@ -170,7 +170,7 @@ static const char *intern_variable_name(const char *name, size_t len)
170170
171171 existing = hashmap_get (
172172 interned_variable_names ,
173- & (struct interned_name ) { .name = name }
173+ & (struct interned_name ) { .name = name , . name_length = len }
174174 );
175175
176176 return existing ? existing -> name : copy ;
@@ -267,46 +267,33 @@ void build_keyword_prefix_offsets(void)
267267 keyword_prefix_ready = true;
268268}
269269
270- static int singlechar (struct basic_ctx * ctx )
271- {
272- switch (* ctx -> ptr ) {
273- case '\n' :
274- return NEWLINE ;
275- case ',' :
276- return COMMA ;
277- case ';' :
278- return SEMICOLON ;
279- case '+' :
280- return PLUS ;
281- case '-' :
282- return MINUS ;
283- case '*' :
284- return ASTERISK ;
285- case '/' :
286- return SLASH ;
287- case '%' :
288- return MOD ;
289- case '(' :
290- return OPENBRACKET ;
291- case ')' :
292- return CLOSEBRACKET ;
293- case '<' :
294- return LESSTHAN ;
295- case '>' :
296- return GREATERTHAN ;
297- case '=' :
298- return EQUALS ;
299- case '~' :
300- return TILDE ;
301- case ' ' :
302- case '\t' :
303- return SPACE ;
304- }
305- return 0 ;
270+ static const enum token_t singlechar_tokens [256 ] = {
271+ ['\n' ] = NEWLINE ,
272+ [',' ] = COMMA ,
273+ [';' ] = SEMICOLON ,
274+ ['+' ] = PLUS ,
275+ ['-' ] = MINUS ,
276+ ['*' ] = ASTERISK ,
277+ ['/' ] = SLASH ,
278+ ['%' ] = MOD ,
279+ ['(' ] = OPENBRACKET ,
280+ [')' ] = CLOSEBRACKET ,
281+ ['<' ] = LESSTHAN ,
282+ ['>' ] = GREATERTHAN ,
283+ ['=' ] = EQUALS ,
284+ ['~' ] = TILDE ,
285+ [' ' ] = SPACE ,
286+ ['\t' ] = SPACE ,
287+ };
288+
289+ static inline __attribute__((always_inline )) enum token_t singlechar (const char * p ) {
290+ return singlechar_tokens [(unsigned char )* p ];
306291}
307292
308293int get_next_token (struct basic_ctx * ctx )
309294{
295+ enum token_t tok ;
296+
310297 if (* ctx -> ptr == 0 ) {
311298 return ENDOFINPUT ;
312299 }
@@ -324,10 +311,6 @@ int get_next_token(struct basic_ctx* ctx)
324311 return NO_TOKEN ;
325312 }
326313 }
327- if (!isxdigit (ctx -> ptr [i ])) {
328- tokenizer_error_print (ctx , "Malformed hexadecimal number" );
329- return NO_TOKEN ;
330- }
331314 }
332315 } else {
333316 /* Scan forwards up to MAX_NUMLEN characters */
@@ -342,17 +325,13 @@ int get_next_token(struct basic_ctx* ctx)
342325 return NO_TOKEN ;
343326 }
344327 }
345- if (!isdigit (ctx -> ptr [i ]) && ctx -> ptr [i ] != '.' ) {
346- tokenizer_error_print (ctx , "Malformed number" );
347- return NO_TOKEN ;
348- }
349328 }
350329 }
351330 tokenizer_error_print (ctx , "Number too long" );
352331 return NO_TOKEN ;
353- } else if (singlechar (ctx ) ) {
332+ } else if (( tok = singlechar (ctx -> ptr )) != NO_TOKEN ) {
354333 ctx -> nextptr = ctx -> ptr + 1 ;
355- return singlechar ( ctx ) ;
334+ return tok ;
356335 } else if (* ctx -> ptr == '"' ) {
357336 ctx -> nextptr = ctx -> ptr ;
358337 int strl = 0 ;
@@ -376,7 +355,7 @@ int get_next_token(struct basic_ctx* ctx)
376355 int start = keyword_prefix_offsets [key ];
377356 int end = keyword_prefix_offsets [key + 1 ];
378357 for (int kt = start ; kt < end ; ++ kt ) {
379- int tok = keywords [kt ];
358+ tok = keywords [kt ];
380359 size_t len = token_name_lengths [tok ];
381360 /* First two characters already matched by prefix16 bucket.
382361 * Compare from byte 2 onwards; <=2 length is already a full match.
@@ -479,35 +458,6 @@ void tokenizer_fnum(struct basic_ctx* ctx, enum token_t token, double* f)
479458 atof (ctx -> ptr , f );
480459}
481460
482- bool tokenizer_string (char * dest , int len , struct basic_ctx * ctx )
483- {
484- char * string_end ;
485- int string_len ;
486-
487- if (tokenizer_token (ctx ) != STRING ) {
488- return true;
489- }
490- string_end = strchr (ctx -> ptr + 1 , '"' );
491- if (string_end == NULL ) {
492- tokenizer_error_print (ctx , "Unterminated \"" );
493- * dest = 0 ;
494- return false;
495- }
496- string_len = string_end - ctx -> ptr - 1 ;
497- if (len < string_len ) {
498- string_len = len ;
499- }
500- if (ctx -> ptr == ctx -> program_ptr ) {
501- tokenizer_error_print (ctx , "Unterminated \"" );
502- * dest = 0 ;
503- return false;
504- }
505- memcpy (dest , ctx -> ptr + 1 , string_len );
506- dest [string_len ] = 0 ;
507- return true;
508- }
509-
510-
511461void tokenizer_error_printf (struct basic_ctx * ctx , const char * fmt , ...)
512462{
513463 char error [MAX_STRINGLEN ];
@@ -518,7 +468,6 @@ void tokenizer_error_printf(struct basic_ctx* ctx, const char* fmt, ...)
518468 tokenizer_error_print (ctx , error );
519469}
520470
521-
522471void tokenizer_error_print (struct basic_ctx * ctx , const char * error )
523472{
524473 dprintf ("tokenizer_error_print: %s\n" , error );
@@ -612,8 +561,6 @@ bool tokenizer_finished(struct basic_ctx* ctx)
612561const char * tokenizer_variable_name (struct basic_ctx * ctx , size_t * count )
613562{
614563 char varname [MAX_VARNAME ];
615- const char * interned ;
616-
617564 * count = 0 ;
618565
619566 while (* count < MAX_VARNAME && * ctx -> ptr != 0 ) {
@@ -648,7 +595,7 @@ const char* tokenizer_variable_name(struct basic_ctx* ctx, size_t* count)
648595
649596 varname [* count ] = 0 ;
650597
651- interned = intern_variable_name (varname , * count );
598+ const char * interned = intern_variable_name (varname , * count );
652599 if (!interned ) {
653600 tokenizer_error_printf (ctx , "Out of memory interning variable name '%s'" , varname );
654601 * count = 0 ;
0 commit comments