diff options
| author | Mike Pall <mike> | 2012-08-25 23:02:29 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2012-08-25 23:02:29 +0200 |
| commit | 4c882fe71406a923f07c8e9a0b9189036e0ba386 (patch) | |
| tree | 22aa3995b5bdc2fce05ba17488799e67abc635ba /src | |
| parent | 653facd0d5c1a4f7eae43eefbf8148f57e28e606 (diff) | |
| download | luajit-4c882fe71406a923f07c8e9a0b9189036e0ba386.tar.gz luajit-4c882fe71406a923f07c8e9a0b9189036e0ba386.tar.bz2 luajit-4c882fe71406a923f07c8e9a0b9189036e0ba386.zip | |
Replace strtod() with builtin string to number conversion.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 4 | ||||
| -rw-r--r-- | src/Makefile.dep | 56 | ||||
| -rw-r--r-- | src/lib_base.c | 3 | ||||
| -rw-r--r-- | src/lj_api.c | 15 | ||||
| -rw-r--r-- | src/lj_asm_arm.h | 2 | ||||
| -rw-r--r-- | src/lj_asm_mips.h | 2 | ||||
| -rw-r--r-- | src/lj_asm_ppc.h | 2 | ||||
| -rw-r--r-- | src/lj_asm_x86.h | 2 | ||||
| -rw-r--r-- | src/lj_char.h | 2 | ||||
| -rw-r--r-- | src/lj_cparse.c | 67 | ||||
| -rw-r--r-- | src/lj_ffrecord.c | 5 | ||||
| -rw-r--r-- | src/lj_ir.c | 1 | ||||
| -rw-r--r-- | src/lj_ircall.h | 2 | ||||
| -rw-r--r-- | src/lj_lex.c | 110 | ||||
| -rw-r--r-- | src/lj_lib.c | 12 | ||||
| -rw-r--r-- | src/lj_meta.c | 12 | ||||
| -rw-r--r-- | src/lj_opt_fold.c | 3 | ||||
| -rw-r--r-- | src/lj_opt_narrow.c | 12 | ||||
| -rw-r--r-- | src/lj_str.c | 79 | ||||
| -rw-r--r-- | src/lj_str.h | 3 | ||||
| -rw-r--r-- | src/lj_strscan.c | 497 | ||||
| -rw-r--r-- | src/lj_strscan.h | 39 | ||||
| -rw-r--r-- | src/ljamalg.c | 1 | ||||
| -rw-r--r-- | src/luaconf.h | 1 |
24 files changed, 660 insertions, 272 deletions
diff --git a/src/Makefile b/src/Makefile index 748a4ed7..bb617516 100644 --- a/src/Makefile +++ b/src/Makefile | |||
| @@ -446,8 +446,8 @@ LJLIB_C= $(LJLIB_O:.o=.c) | |||
| 446 | 446 | ||
| 447 | LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o \ | 447 | LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o \ |
| 448 | lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \ | 448 | lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \ |
| 449 | lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o lj_api.o \ | 449 | lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o lj_strscan.o \ |
| 450 | lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o \ | 450 | lj_api.o lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o \ |
| 451 | lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \ | 451 | lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \ |
| 452 | lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \ | 452 | lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \ |
| 453 | lj_mcode.o lj_snap.o lj_record.o lj_crecord.o lj_ffrecord.o \ | 453 | lj_mcode.o lj_snap.o lj_record.o lj_crecord.o lj_ffrecord.o \ |
diff --git a/src/Makefile.dep b/src/Makefile.dep index f9e658e1..9b130deb 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep | |||
| @@ -3,7 +3,8 @@ lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ | |||
| 3 | lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ | 3 | lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ |
| 4 | lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h \ | 4 | lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h \ |
| 5 | lj_tab.h lj_meta.h lj_state.h lj_ctype.h lj_cconv.h lj_bc.h lj_ff.h \ | 5 | lj_tab.h lj_meta.h lj_state.h lj_ctype.h lj_cconv.h lj_bc.h lj_ff.h \ |
| 6 | lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h lj_lib.h lj_libdef.h | 6 | lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h lj_strscan.h \ |
| 7 | lj_lib.h lj_libdef.h | ||
| 7 | lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ | 8 | lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ |
| 8 | lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_lib.h lj_libdef.h | 9 | lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_lib.h lj_libdef.h |
| 9 | lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ | 10 | lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ |
| @@ -39,7 +40,8 @@ lj_alloc.o: lj_alloc.c lj_def.h lua.h luaconf.h lj_arch.h lj_alloc.h | |||
| 39 | lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 40 | lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
| 40 | lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_func.h lj_udata.h \ | 41 | lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_func.h lj_udata.h \ |
| 41 | lj_meta.h lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h \ | 42 | lj_meta.h lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h \ |
| 42 | lj_dispatch.h lj_traceerr.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h | 43 | lj_dispatch.h lj_traceerr.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h \ |
| 44 | lj_strscan.h | ||
| 43 | lj_asm.o: lj_asm.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 45 | lj_asm.o: lj_asm.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
| 44 | lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h lj_ir.h lj_jit.h \ | 46 | lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h lj_ir.h lj_jit.h \ |
| 45 | lj_ircall.h lj_iropt.h lj_mcode.h lj_trace.h lj_dispatch.h lj_traceerr.h \ | 47 | lj_ircall.h lj_iropt.h lj_mcode.h lj_trace.h lj_dispatch.h lj_traceerr.h \ |
| @@ -77,7 +79,7 @@ lj_clib.o: lj_clib.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | |||
| 77 | lj_cdata.h lj_clib.h | 79 | lj_cdata.h lj_clib.h |
| 78 | lj_cparse.o: lj_cparse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 80 | lj_cparse.o: lj_cparse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 79 | lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cparse.h lj_frame.h \ | 81 | lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cparse.h lj_frame.h \ |
| 80 | lj_bc.h lj_vm.h lj_char.h | 82 | lj_bc.h lj_vm.h lj_char.h lj_strscan.h |
| 81 | lj_crecord.o: lj_crecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 83 | lj_crecord.o: lj_crecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 82 | lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h \ | 84 | lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h \ |
| 83 | lj_gc.h lj_cdata.h lj_cparse.h lj_cconv.h lj_clib.h lj_ccall.h lj_ir.h \ | 85 | lj_gc.h lj_cdata.h lj_cparse.h lj_cconv.h lj_clib.h lj_ccall.h lj_ir.h \ |
| @@ -101,7 +103,7 @@ lj_ffrecord.o: lj_ffrecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | |||
| 101 | lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ff.h \ | 103 | lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ff.h \ |
| 102 | lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \ | 104 | lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \ |
| 103 | lj_dispatch.h lj_traceerr.h lj_record.h lj_ffrecord.h lj_crecord.h \ | 105 | lj_dispatch.h lj_traceerr.h lj_record.h lj_ffrecord.h lj_crecord.h \ |
| 104 | lj_vm.h lj_recdef.h | 106 | lj_vm.h lj_strscan.h lj_recdef.h |
| 105 | lj_func.o: lj_func.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 107 | lj_func.o: lj_func.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
| 106 | lj_func.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \ | 108 | lj_func.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \ |
| 107 | lj_traceerr.h lj_vm.h | 109 | lj_traceerr.h lj_vm.h |
| @@ -115,34 +117,34 @@ lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | |||
| 115 | lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 117 | lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
| 116 | lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \ | 118 | lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \ |
| 117 | lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h lj_carith.h \ | 119 | lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h lj_carith.h \ |
| 118 | lj_vm.h lj_lib.h | 120 | lj_vm.h lj_strscan.h lj_lib.h |
| 119 | lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 121 | lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
| 120 | lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h lualib.h \ | 122 | lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h lualib.h \ |
| 121 | lj_state.h lj_lex.h lj_parse.h lj_char.h | 123 | lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h |
| 122 | lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \ | 124 | lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \ |
| 123 | lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_bc.h \ | 125 | lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_bc.h \ |
| 124 | lj_dispatch.h lj_jit.h lj_ir.h lj_vm.h lj_lib.h | 126 | lj_dispatch.h lj_jit.h lj_ir.h lj_vm.h lj_strscan.h lj_lib.h |
| 125 | lj_mcode.o: lj_mcode.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 127 | lj_mcode.o: lj_mcode.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 126 | lj_gc.h lj_jit.h lj_ir.h lj_mcode.h lj_trace.h lj_dispatch.h lj_bc.h \ | 128 | lj_gc.h lj_jit.h lj_ir.h lj_mcode.h lj_trace.h lj_dispatch.h lj_bc.h \ |
| 127 | lj_traceerr.h lj_vm.h | 129 | lj_traceerr.h lj_vm.h |
| 128 | lj_meta.o: lj_meta.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 130 | lj_meta.o: lj_meta.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
| 129 | lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \ | 131 | lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \ |
| 130 | lj_vm.h | 132 | lj_vm.h lj_strscan.h |
| 131 | lj_obj.o: lj_obj.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h | 133 | lj_obj.o: lj_obj.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h |
| 132 | lj_opt_dce.o: lj_opt_dce.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 134 | lj_opt_dce.o: lj_opt_dce.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 133 | lj_ir.h lj_jit.h lj_iropt.h | 135 | lj_ir.h lj_jit.h lj_iropt.h |
| 134 | lj_opt_fold.o: lj_opt_fold.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 136 | lj_opt_fold.o: lj_opt_fold.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 135 | lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h lj_dispatch.h \ | 137 | lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h lj_dispatch.h \ |
| 136 | lj_bc.h lj_traceerr.h lj_ctype.h lj_gc.h lj_carith.h lj_vm.h \ | 138 | lj_bc.h lj_traceerr.h lj_ctype.h lj_gc.h lj_carith.h lj_vm.h \ |
| 137 | lj_folddef.h | 139 | lj_strscan.h lj_folddef.h |
| 138 | lj_opt_loop.o: lj_opt_loop.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 140 | lj_opt_loop.o: lj_opt_loop.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 139 | lj_err.h lj_errmsg.h lj_str.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h \ | 141 | lj_err.h lj_errmsg.h lj_str.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h \ |
| 140 | lj_dispatch.h lj_bc.h lj_traceerr.h lj_snap.h lj_vm.h | 142 | lj_dispatch.h lj_bc.h lj_traceerr.h lj_snap.h lj_vm.h |
| 141 | lj_opt_mem.o: lj_opt_mem.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 143 | lj_opt_mem.o: lj_opt_mem.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 142 | lj_tab.h lj_ir.h lj_jit.h lj_iropt.h | 144 | lj_tab.h lj_ir.h lj_jit.h lj_iropt.h |
| 143 | lj_opt_narrow.o: lj_opt_narrow.c lj_obj.h lua.h luaconf.h lj_def.h \ | 145 | lj_opt_narrow.o: lj_opt_narrow.c lj_obj.h lua.h luaconf.h lj_def.h \ |
| 144 | lj_arch.h lj_str.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h \ | 146 | lj_arch.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h lj_dispatch.h \ |
| 145 | lj_dispatch.h lj_traceerr.h lj_vm.h | 147 | lj_traceerr.h lj_vm.h lj_strscan.h |
| 146 | lj_opt_sink.o: lj_opt_sink.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 148 | lj_opt_sink.o: lj_opt_sink.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 147 | lj_ir.h lj_jit.h lj_iropt.h lj_target.h lj_target_*.h | 149 | lj_ir.h lj_jit.h lj_iropt.h lj_target.h lj_target_*.h |
| 148 | lj_opt_split.o: lj_opt_split.c lj_obj.h lua.h luaconf.h lj_def.h \ | 150 | lj_opt_split.o: lj_opt_split.c lj_obj.h lua.h luaconf.h lj_def.h \ |
| @@ -165,6 +167,8 @@ lj_state.o: lj_state.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | |||
| 165 | lj_dispatch.h lj_traceerr.h lj_vm.h lj_lex.h lj_alloc.h | 167 | lj_dispatch.h lj_traceerr.h lj_vm.h lj_lex.h lj_alloc.h |
| 166 | lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 168 | lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
| 167 | lj_err.h lj_errmsg.h lj_str.h lj_state.h lj_char.h | 169 | lj_err.h lj_errmsg.h lj_str.h lj_state.h lj_char.h |
| 170 | lj_strscan.o: lj_strscan.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | ||
| 171 | lj_char.h lj_strscan.h | ||
| 168 | lj_tab.o: lj_tab.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 172 | lj_tab.o: lj_tab.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
| 169 | lj_err.h lj_errmsg.h lj_tab.h | 173 | lj_err.h lj_errmsg.h lj_tab.h |
| 170 | lj_trace.o: lj_trace.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 174 | lj_trace.o: lj_trace.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| @@ -184,21 +188,21 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_gc.c lj_obj.h lj_def.h \ | |||
| 184 | lj_udata.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cdata.h \ | 188 | lj_udata.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cdata.h \ |
| 185 | lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_err.c \ | 189 | lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_err.c \ |
| 186 | lj_debug.h lj_ff.h lj_ffdef.h lj_char.c lj_char.h lj_bc.c lj_bcdef.h \ | 190 | lj_debug.h lj_ff.h lj_ffdef.h lj_char.c lj_char.h lj_bc.c lj_bcdef.h \ |
| 187 | lj_obj.c lj_str.c lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_debug.c \ | 191 | lj_obj.c lj_str.c lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h \ |
| 188 | lj_state.c lj_lex.h lj_alloc.h lj_dispatch.c lj_ccallback.h luajit.h \ | 192 | lj_debug.c lj_state.c lj_lex.h lj_alloc.h lj_dispatch.c lj_ccallback.h \ |
| 189 | lj_vmevent.c lj_vmevent.h lj_vmmath.c lj_api.c lj_bcdump.h lj_parse.h \ | 193 | luajit.h lj_vmevent.c lj_vmevent.h lj_vmmath.c lj_strscan.c lj_api.c \ |
| 190 | lj_lex.c lualib.h lj_parse.c lj_bcread.c lj_bcwrite.c lj_ctype.c \ | 194 | lj_bcdump.h lj_parse.h lj_lex.c lualib.h lj_parse.c lj_bcread.c \ |
| 191 | lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c \ | 195 | lj_bcwrite.c lj_ctype.c lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c \ |
| 192 | lj_target.h lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c \ | 196 | lj_ccall.h lj_ccallback.c lj_target.h lj_target_*.h lj_mcode.h \ |
| 193 | lj_clib.h lj_cparse.c lj_cparse.h lj_lib.c lj_lib.h lj_ir.c lj_ircall.h \ | 197 | lj_carith.c lj_carith.h lj_clib.c lj_clib.h lj_cparse.c lj_cparse.h \ |
| 194 | lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c \ | 198 | lj_lib.c lj_lib.h lj_ir.c lj_ircall.h lj_iropt.h lj_opt_mem.c \ |
| 195 | lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c \ | 199 | lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c lj_opt_loop.c \ |
| 196 | lj_mcode.c lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \ | 200 | lj_snap.h lj_opt_split.c lj_opt_sink.c lj_mcode.c lj_snap.c lj_record.c \ |
| 197 | lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h \ | 201 | lj_record.h lj_ffrecord.h lj_crecord.c lj_crecord.h lj_ffrecord.c \ |
| 198 | lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c \ | 202 | lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h lj_asm_*.h lj_trace.c \ |
| 199 | lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \ | 203 | lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c lib_base.c lj_libdef.h \ |
| 200 | lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c \ | 204 | lib_math.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c \ |
| 201 | lib_init.c | 205 | lib_debug.c lib_bit.c lib_jit.c lib_ffi.c lib_init.c |
| 202 | luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h | 206 | luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h |
| 203 | host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \ | 207 | host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \ |
| 204 | lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \ | 208 | lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \ |
diff --git a/src/lib_base.c b/src/lib_base.c index 383955d4..9702c5b4 100644 --- a/src/lib_base.c +++ b/src/lib_base.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include "lj_ff.h" | 31 | #include "lj_ff.h" |
| 32 | #include "lj_dispatch.h" | 32 | #include "lj_dispatch.h" |
| 33 | #include "lj_char.h" | 33 | #include "lj_char.h" |
| 34 | #include "lj_strscan.h" | ||
| 34 | #include "lj_lib.h" | 35 | #include "lj_lib.h" |
| 35 | 36 | ||
| 36 | /* -- Base library: checks ------------------------------------------------ */ | 37 | /* -- Base library: checks ------------------------------------------------ */ |
| @@ -191,7 +192,7 @@ LJLIB_ASM(tonumber) LJLIB_REC(.) | |||
| 191 | int32_t base = lj_lib_optint(L, 2, 10); | 192 | int32_t base = lj_lib_optint(L, 2, 10); |
| 192 | if (base == 10) { | 193 | if (base == 10) { |
| 193 | TValue *o = lj_lib_checkany(L, 1); | 194 | TValue *o = lj_lib_checkany(L, 1); |
| 194 | if (tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), o))) { | 195 | if (lj_strscan_numberobj(o)) { |
| 195 | copyTV(L, L->base-1, o); | 196 | copyTV(L, L->base-1, o); |
| 196 | return FFH_RES(1); | 197 | return FFH_RES(1); |
| 197 | } | 198 | } |
diff --git a/src/lj_api.c b/src/lj_api.c index b807900d..bfd471d2 100644 --- a/src/lj_api.c +++ b/src/lj_api.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include "lj_lex.h" | 26 | #include "lj_lex.h" |
| 27 | #include "lj_bcdump.h" | 27 | #include "lj_bcdump.h" |
| 28 | #include "lj_parse.h" | 28 | #include "lj_parse.h" |
| 29 | #include "lj_strscan.h" | ||
| 29 | 30 | ||
| 30 | /* -- Common helper functions --------------------------------------------- */ | 31 | /* -- Common helper functions --------------------------------------------- */ |
| 31 | 32 | ||
| @@ -236,7 +237,7 @@ LUA_API int lua_isnumber(lua_State *L, int idx) | |||
| 236 | { | 237 | { |
| 237 | cTValue *o = index2adr(L, idx); | 238 | cTValue *o = index2adr(L, idx); |
| 238 | TValue tmp; | 239 | TValue tmp; |
| 239 | return (tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), &tmp))); | 240 | return (tvisnumber(o) || (tvisstr(o) && lj_strscan_number(strV(o), &tmp))); |
| 240 | } | 241 | } |
| 241 | 242 | ||
| 242 | LUA_API int lua_isstring(lua_State *L, int idx) | 243 | LUA_API int lua_isstring(lua_State *L, int idx) |
| @@ -320,7 +321,7 @@ LUA_API lua_Number lua_tonumber(lua_State *L, int idx) | |||
| 320 | TValue tmp; | 321 | TValue tmp; |
| 321 | if (LJ_LIKELY(tvisnumber(o))) | 322 | if (LJ_LIKELY(tvisnumber(o))) |
| 322 | return numberVnum(o); | 323 | return numberVnum(o); |
| 323 | else if (tvisstr(o) && lj_str_tonum(strV(o), &tmp)) | 324 | else if (tvisstr(o) && lj_strscan_num(strV(o), &tmp)) |
| 324 | return numV(&tmp); | 325 | return numV(&tmp); |
| 325 | else | 326 | else |
| 326 | return 0; | 327 | return 0; |
| @@ -332,7 +333,7 @@ LUALIB_API lua_Number luaL_checknumber(lua_State *L, int idx) | |||
| 332 | TValue tmp; | 333 | TValue tmp; |
| 333 | if (LJ_LIKELY(tvisnumber(o))) | 334 | if (LJ_LIKELY(tvisnumber(o))) |
| 334 | return numberVnum(o); | 335 | return numberVnum(o); |
| 335 | else if (!(tvisstr(o) && lj_str_tonum(strV(o), &tmp))) | 336 | else if (!(tvisstr(o) && lj_strscan_num(strV(o), &tmp))) |
| 336 | lj_err_argt(L, idx, LUA_TNUMBER); | 337 | lj_err_argt(L, idx, LUA_TNUMBER); |
| 337 | return numV(&tmp); | 338 | return numV(&tmp); |
| 338 | } | 339 | } |
| @@ -345,7 +346,7 @@ LUALIB_API lua_Number luaL_optnumber(lua_State *L, int idx, lua_Number def) | |||
| 345 | return numberVnum(o); | 346 | return numberVnum(o); |
| 346 | else if (tvisnil(o)) | 347 | else if (tvisnil(o)) |
| 347 | return def; | 348 | return def; |
| 348 | else if (!(tvisstr(o) && lj_str_tonum(strV(o), &tmp))) | 349 | else if (!(tvisstr(o) && lj_strscan_num(strV(o), &tmp))) |
| 349 | lj_err_argt(L, idx, LUA_TNUMBER); | 350 | lj_err_argt(L, idx, LUA_TNUMBER); |
| 350 | return numV(&tmp); | 351 | return numV(&tmp); |
| 351 | } | 352 | } |
| @@ -360,7 +361,7 @@ LUA_API lua_Integer lua_tointeger(lua_State *L, int idx) | |||
| 360 | } else if (LJ_LIKELY(tvisnum(o))) { | 361 | } else if (LJ_LIKELY(tvisnum(o))) { |
| 361 | n = numV(o); | 362 | n = numV(o); |
| 362 | } else { | 363 | } else { |
| 363 | if (!(tvisstr(o) && lj_str_tonumber(strV(o), &tmp))) | 364 | if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp))) |
| 364 | return 0; | 365 | return 0; |
| 365 | if (tvisint(&tmp)) | 366 | if (tvisint(&tmp)) |
| 366 | return (lua_Integer)intV(&tmp); | 367 | return (lua_Integer)intV(&tmp); |
| @@ -383,7 +384,7 @@ LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int idx) | |||
| 383 | } else if (LJ_LIKELY(tvisnum(o))) { | 384 | } else if (LJ_LIKELY(tvisnum(o))) { |
| 384 | n = numV(o); | 385 | n = numV(o); |
| 385 | } else { | 386 | } else { |
| 386 | if (!(tvisstr(o) && lj_str_tonumber(strV(o), &tmp))) | 387 | if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp))) |
| 387 | lj_err_argt(L, idx, LUA_TNUMBER); | 388 | lj_err_argt(L, idx, LUA_TNUMBER); |
| 388 | if (tvisint(&tmp)) | 389 | if (tvisint(&tmp)) |
| 389 | return (lua_Integer)intV(&tmp); | 390 | return (lua_Integer)intV(&tmp); |
| @@ -408,7 +409,7 @@ LUALIB_API lua_Integer luaL_optinteger(lua_State *L, int idx, lua_Integer def) | |||
| 408 | } else if (tvisnil(o)) { | 409 | } else if (tvisnil(o)) { |
| 409 | return def; | 410 | return def; |
| 410 | } else { | 411 | } else { |
| 411 | if (!(tvisstr(o) && lj_str_tonumber(strV(o), &tmp))) | 412 | if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp))) |
| 412 | lj_err_argt(L, idx, LUA_TNUMBER); | 413 | lj_err_argt(L, idx, LUA_TNUMBER); |
| 413 | if (tvisint(&tmp)) | 414 | if (tvisint(&tmp)) |
| 414 | return (lua_Integer)intV(&tmp); | 415 | return (lua_Integer)intV(&tmp); |
diff --git a/src/lj_asm_arm.h b/src/lj_asm_arm.h index f307d6b8..8ba3dc06 100644 --- a/src/lj_asm_arm.h +++ b/src/lj_asm_arm.h | |||
| @@ -626,7 +626,7 @@ static void asm_conv64(ASMState *as, IRIns *ir) | |||
| 626 | 626 | ||
| 627 | static void asm_strto(ASMState *as, IRIns *ir) | 627 | static void asm_strto(ASMState *as, IRIns *ir) |
| 628 | { | 628 | { |
| 629 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_tonum]; | 629 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num]; |
| 630 | IRRef args[2]; | 630 | IRRef args[2]; |
| 631 | Reg rlo = 0, rhi = 0, tmp; | 631 | Reg rlo = 0, rhi = 0, tmp; |
| 632 | int destused = ra_used(ir); | 632 | int destused = ra_used(ir); |
diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h index 14ebd1b3..3de133b8 100644 --- a/src/lj_asm_mips.h +++ b/src/lj_asm_mips.h | |||
| @@ -541,7 +541,7 @@ static void asm_conv64(ASMState *as, IRIns *ir) | |||
| 541 | 541 | ||
| 542 | static void asm_strto(ASMState *as, IRIns *ir) | 542 | static void asm_strto(ASMState *as, IRIns *ir) |
| 543 | { | 543 | { |
| 544 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_tonum]; | 544 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num]; |
| 545 | IRRef args[2]; | 545 | IRRef args[2]; |
| 546 | RegSet drop = RSET_SCRATCH; | 546 | RegSet drop = RSET_SCRATCH; |
| 547 | if (ra_hasreg(ir->r)) rset_set(drop, ir->r); /* Spill dest reg (if any). */ | 547 | if (ra_hasreg(ir->r)) rset_set(drop, ir->r); /* Spill dest reg (if any). */ |
diff --git a/src/lj_asm_ppc.h b/src/lj_asm_ppc.h index 86052577..7d9a9c76 100644 --- a/src/lj_asm_ppc.h +++ b/src/lj_asm_ppc.h | |||
| @@ -533,7 +533,7 @@ static void asm_conv64(ASMState *as, IRIns *ir) | |||
| 533 | 533 | ||
| 534 | static void asm_strto(ASMState *as, IRIns *ir) | 534 | static void asm_strto(ASMState *as, IRIns *ir) |
| 535 | { | 535 | { |
| 536 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_tonum]; | 536 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num]; |
| 537 | IRRef args[2]; | 537 | IRRef args[2]; |
| 538 | int32_t ofs; | 538 | int32_t ofs; |
| 539 | RegSet drop = RSET_SCRATCH; | 539 | RegSet drop = RSET_SCRATCH; |
diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h index ceeefbee..da4cf7e2 100644 --- a/src/lj_asm_x86.h +++ b/src/lj_asm_x86.h | |||
| @@ -882,7 +882,7 @@ static void asm_conv_int64_fp(ASMState *as, IRIns *ir) | |||
| 882 | static void asm_strto(ASMState *as, IRIns *ir) | 882 | static void asm_strto(ASMState *as, IRIns *ir) |
| 883 | { | 883 | { |
| 884 | /* Force a spill slot for the destination register (if any). */ | 884 | /* Force a spill slot for the destination register (if any). */ |
| 885 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_tonum]; | 885 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num]; |
| 886 | IRRef args[2]; | 886 | IRRef args[2]; |
| 887 | RegSet drop = RSET_SCRATCH; | 887 | RegSet drop = RSET_SCRATCH; |
| 888 | if ((drop & RSET_FPR) != RSET_FPR && ra_hasreg(ir->r)) | 888 | if ((drop & RSET_FPR) != RSET_FPR && ra_hasreg(ir->r)) |
diff --git a/src/lj_char.h b/src/lj_char.h index 7b7c1322..c3c86d34 100644 --- a/src/lj_char.h +++ b/src/lj_char.h | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | #define LJ_CHAR_GRAPH (LJ_CHAR_ALNUM|LJ_CHAR_PUNCT) | 21 | #define LJ_CHAR_GRAPH (LJ_CHAR_ALNUM|LJ_CHAR_PUNCT) |
| 22 | 22 | ||
| 23 | /* Only pass -1 or 0..255 to these macros. Never pass a signed char! */ | 23 | /* Only pass -1 or 0..255 to these macros. Never pass a signed char! */ |
| 24 | #define lj_char_isa(c, t) (lj_char_bits[(c)+1] & t) | 24 | #define lj_char_isa(c, t) ((lj_char_bits+1)[(c)] & t) |
| 25 | #define lj_char_iscntrl(c) lj_char_isa((c), LJ_CHAR_CNTRL) | 25 | #define lj_char_iscntrl(c) lj_char_isa((c), LJ_CHAR_CNTRL) |
| 26 | #define lj_char_isspace(c) lj_char_isa((c), LJ_CHAR_SPACE) | 26 | #define lj_char_isspace(c) lj_char_isa((c), LJ_CHAR_SPACE) |
| 27 | #define lj_char_ispunct(c) lj_char_isa((c), LJ_CHAR_PUNCT) | 27 | #define lj_char_ispunct(c) lj_char_isa((c), LJ_CHAR_PUNCT) |
diff --git a/src/lj_cparse.c b/src/lj_cparse.c index e9826715..ab5903fa 100644 --- a/src/lj_cparse.c +++ b/src/lj_cparse.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "lj_frame.h" | 15 | #include "lj_frame.h" |
| 16 | #include "lj_vm.h" | 16 | #include "lj_vm.h" |
| 17 | #include "lj_char.h" | 17 | #include "lj_char.h" |
| 18 | #include "lj_strscan.h" | ||
| 18 | 19 | ||
| 19 | /* | 20 | /* |
| 20 | ** Important note: this is NOT a validating C parser! This is a minimal | 21 | ** Important note: this is NOT a validating C parser! This is a minimal |
| @@ -156,40 +157,19 @@ LJ_NORET LJ_NOINLINE static void cp_err(CPState *cp, ErrMsg em) | |||
| 156 | 157 | ||
| 157 | /* -- Main lexical scanner ------------------------------------------------ */ | 158 | /* -- Main lexical scanner ------------------------------------------------ */ |
| 158 | 159 | ||
| 159 | /* Parse integer literal. */ | 160 | /* Parse number literal. Only handles int32_t/uint32_t right now. */ |
| 160 | static CPToken cp_integer(CPState *cp) | 161 | static CPToken cp_number(CPState *cp) |
| 161 | { | 162 | { |
| 162 | uint32_t n = 0; | 163 | StrScanFmt fmt; |
| 163 | cp->val.id = CTID_INT32; | 164 | TValue o; |
| 164 | if (cp->c != '0') { /* Decimal. */ | 165 | do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp))); |
| 165 | do { | 166 | cp_save(cp, '\0'); |
| 166 | n = n*10 + (cp->c - '0'); | 167 | fmt = lj_strscan_scan((const uint8_t *)cp->sb.buf, &o, STRSCAN_OPT_C); |
| 167 | } while (lj_char_isdigit(cp_get(cp))); | 168 | if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32; |
| 168 | } else if ((cp_get(cp)& ~0x20) == 'X') { /* Hexadecimal. */ | 169 | else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32; |
| 169 | if (!lj_char_isxdigit(cp_get(cp))) | 170 | else if (!(cp->mode & CPARSE_MODE_SKIP)) |
| 170 | cp_err(cp, LJ_ERR_XNUMBER); | 171 | cp_errmsg(cp, CTOK_INTEGER, LJ_ERR_XNUMBER); |
| 171 | do { | 172 | cp->val.u32 = (uint32_t)o.i; |
| 172 | n = n*16 + (cp->c & 15); | ||
| 173 | if (!lj_char_isdigit(cp->c)) n += 9; | ||
| 174 | } while (lj_char_isxdigit(cp_get(cp))); | ||
| 175 | if (n >= 0x80000000u) cp->val.id = CTID_UINT32; | ||
| 176 | } else { /* Octal. */ | ||
| 177 | while (cp->c >= '0' && cp->c <= '7') { | ||
| 178 | n = n*8 + (cp->c - '0'); | ||
| 179 | cp_get(cp); | ||
| 180 | } | ||
| 181 | if (n >= 0x80000000u) cp->val.id = CTID_UINT32; | ||
| 182 | } | ||
| 183 | cp->val.u32 = n; | ||
| 184 | for (;;) { /* Parse suffixes. */ | ||
| 185 | if ((cp->c & ~0x20) == 'U') | ||
| 186 | cp->val.id = CTID_UINT32; | ||
| 187 | else if ((cp->c & ~0x20) != 'L') | ||
| 188 | break; | ||
| 189 | cp_get(cp); | ||
| 190 | } | ||
| 191 | if (lj_char_isident(cp->c) && !(cp->mode & CPARSE_MODE_SKIP)) | ||
| 192 | cp_errmsg(cp, cp->c, LJ_ERR_XNUMBER); | ||
| 193 | return CTOK_INTEGER; | 173 | return CTOK_INTEGER; |
| 194 | } | 174 | } |
| 195 | 175 | ||
| @@ -319,37 +299,34 @@ static CPToken cp_next_(CPState *cp) | |||
| 319 | lj_str_resetbuf(&cp->sb); | 299 | lj_str_resetbuf(&cp->sb); |
| 320 | for (;;) { | 300 | for (;;) { |
| 321 | if (lj_char_isident(cp->c)) | 301 | if (lj_char_isident(cp->c)) |
| 322 | return lj_char_isdigit(cp->c) ? cp_integer(cp) : cp_ident(cp); | 302 | return lj_char_isdigit(cp->c) ? cp_number(cp) : cp_ident(cp); |
| 323 | switch (cp->c) { | 303 | switch (cp->c) { |
| 324 | case '\n': case '\r': cp_newline(cp); /* fallthrough. */ | 304 | case '\n': case '\r': cp_newline(cp); /* fallthrough. */ |
| 325 | case ' ': case '\t': case '\v': case '\f': cp_get(cp); break; | 305 | case ' ': case '\t': case '\v': case '\f': cp_get(cp); break; |
| 326 | case '"': case '\'': return cp_string(cp); | 306 | case '"': case '\'': return cp_string(cp); |
| 327 | case '/': | 307 | case '/': |
| 328 | cp_get(cp); | 308 | if (cp_get(cp) == '*') cp_comment_c(cp); |
| 329 | if (cp->c == '*') cp_comment_c(cp); | ||
| 330 | else if (cp->c == '/') cp_comment_cpp(cp); | 309 | else if (cp->c == '/') cp_comment_cpp(cp); |
| 331 | else return '/'; | 310 | else return '/'; |
| 332 | break; | 311 | break; |
| 333 | case '|': | 312 | case '|': |
| 334 | cp_get(cp); if (cp->c != '|') return '|'; cp_get(cp); return CTOK_OROR; | 313 | if (cp_get(cp) != '|') return '|'; cp_get(cp); return CTOK_OROR; |
| 335 | case '&': | 314 | case '&': |
| 336 | cp_get(cp); if (cp->c != '&') return '&'; cp_get(cp); return CTOK_ANDAND; | 315 | if (cp_get(cp) != '&') return '&'; cp_get(cp); return CTOK_ANDAND; |
| 337 | case '=': | 316 | case '=': |
| 338 | cp_get(cp); if (cp->c != '=') return '='; cp_get(cp); return CTOK_EQ; | 317 | if (cp_get(cp) != '=') return '='; cp_get(cp); return CTOK_EQ; |
| 339 | case '!': | 318 | case '!': |
| 340 | cp_get(cp); if (cp->c != '=') return '!'; cp_get(cp); return CTOK_NE; | 319 | if (cp_get(cp) != '=') return '!'; cp_get(cp); return CTOK_NE; |
| 341 | case '<': | 320 | case '<': |
| 342 | cp_get(cp); | 321 | if (cp_get(cp) == '=') { cp_get(cp); return CTOK_LE; } |
| 343 | if (cp->c == '=') { cp_get(cp); return CTOK_LE; } | ||
| 344 | else if (cp->c == '<') { cp_get(cp); return CTOK_SHL; } | 322 | else if (cp->c == '<') { cp_get(cp); return CTOK_SHL; } |
| 345 | return '<'; | 323 | return '<'; |
| 346 | case '>': | 324 | case '>': |
| 347 | cp_get(cp); | 325 | if (cp_get(cp) == '=') { cp_get(cp); return CTOK_GE; } |
| 348 | if (cp->c == '=') { cp_get(cp); return CTOK_GE; } | ||
| 349 | else if (cp->c == '>') { cp_get(cp); return CTOK_SHR; } | 326 | else if (cp->c == '>') { cp_get(cp); return CTOK_SHR; } |
| 350 | return '>'; | 327 | return '>'; |
| 351 | case '-': | 328 | case '-': |
| 352 | cp_get(cp); if (cp->c != '>') return '-'; cp_get(cp); return CTOK_DEREF; | 329 | if (cp_get(cp) != '>') return '-'; cp_get(cp); return CTOK_DEREF; |
| 353 | case '$': | 330 | case '$': |
| 354 | return cp_param(cp); | 331 | return cp_param(cp); |
| 355 | case '\0': return CTOK_EOF; | 332 | case '\0': return CTOK_EOF; |
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index 716226bc..1ac0112e 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include "lj_crecord.h" | 26 | #include "lj_crecord.h" |
| 27 | #include "lj_dispatch.h" | 27 | #include "lj_dispatch.h" |
| 28 | #include "lj_vm.h" | 28 | #include "lj_vm.h" |
| 29 | #include "lj_strscan.h" | ||
| 29 | 30 | ||
| 30 | /* Some local macros to save typing. Undef'd at the end. */ | 31 | /* Some local macros to save typing. Undef'd at the end. */ |
| 31 | #define IR(ref) (&J->cur.ir[(ref)]) | 32 | #define IR(ref) (&J->cur.ir[(ref)]) |
| @@ -64,7 +65,7 @@ typedef void (LJ_FASTCALL *RecordFunc)(jit_State *J, RecordFFData *rd); | |||
| 64 | /* Get runtime value of int argument. */ | 65 | /* Get runtime value of int argument. */ |
| 65 | static int32_t argv2int(jit_State *J, TValue *o) | 66 | static int32_t argv2int(jit_State *J, TValue *o) |
| 66 | { | 67 | { |
| 67 | if (!tvisnumber(o) && !(tvisstr(o) && lj_str_tonumber(strV(o), o))) | 68 | if (!lj_strscan_numberobj(o)) |
| 68 | lj_trace_err(J, LJ_TRERR_BADTYPE); | 69 | lj_trace_err(J, LJ_TRERR_BADTYPE); |
| 69 | return tvisint(o) ? intV(o) : lj_num2int(numV(o)); | 70 | return tvisint(o) ? intV(o) : lj_num2int(numV(o)); |
| 70 | } | 71 | } |
| @@ -266,7 +267,7 @@ static void LJ_FASTCALL recff_tonumber(jit_State *J, RecordFFData *rd) | |||
| 266 | if (tref_isnumber_str(tr)) { | 267 | if (tref_isnumber_str(tr)) { |
| 267 | if (tref_isstr(tr)) { | 268 | if (tref_isstr(tr)) { |
| 268 | TValue tmp; | 269 | TValue tmp; |
| 269 | if (!lj_str_tonum(strV(&rd->argv[0]), &tmp)) | 270 | if (!lj_strscan_num(strV(&rd->argv[0]), &tmp)) |
| 270 | recff_nyiu(J); /* Would need an inverted STRTO for this case. */ | 271 | recff_nyiu(J); /* Would need an inverted STRTO for this case. */ |
| 271 | tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0); | 272 | tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0); |
| 272 | } | 273 | } |
diff --git a/src/lj_ir.c b/src/lj_ir.c index f198a6df..92be4149 100644 --- a/src/lj_ir.c +++ b/src/lj_ir.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include "lj_carith.h" | 28 | #include "lj_carith.h" |
| 29 | #endif | 29 | #endif |
| 30 | #include "lj_vm.h" | 30 | #include "lj_vm.h" |
| 31 | #include "lj_strscan.h" | ||
| 31 | #include "lj_lib.h" | 32 | #include "lj_lib.h" |
| 32 | 33 | ||
| 33 | /* Some local macros to save typing. Undef'd at the end. */ | 34 | /* Some local macros to save typing. Undef'd at the end. */ |
diff --git a/src/lj_ircall.h b/src/lj_ircall.h index 8f481106..ffe7305b 100644 --- a/src/lj_ircall.h +++ b/src/lj_ircall.h | |||
| @@ -102,7 +102,7 @@ typedef struct CCallInfo { | |||
| 102 | #define IRCALLDEF(_) \ | 102 | #define IRCALLDEF(_) \ |
| 103 | _(ANY, lj_str_cmp, 2, FN, INT, CCI_NOFPRCLOBBER) \ | 103 | _(ANY, lj_str_cmp, 2, FN, INT, CCI_NOFPRCLOBBER) \ |
| 104 | _(ANY, lj_str_new, 3, S, STR, CCI_L) \ | 104 | _(ANY, lj_str_new, 3, S, STR, CCI_L) \ |
| 105 | _(ANY, lj_str_tonum, 2, FN, INT, 0) \ | 105 | _(ANY, lj_strscan_num, 2, FN, INT, 0) \ |
| 106 | _(ANY, lj_str_fromint, 2, FN, STR, CCI_L) \ | 106 | _(ANY, lj_str_fromint, 2, FN, STR, CCI_L) \ |
| 107 | _(ANY, lj_str_fromnum, 2, FN, STR, CCI_L) \ | 107 | _(ANY, lj_str_fromnum, 2, FN, STR, CCI_L) \ |
| 108 | _(ANY, lj_tab_new1, 2, FS, TAB, CCI_L) \ | 108 | _(ANY, lj_tab_new1, 2, FS, TAB, CCI_L) \ |
diff --git a/src/lj_lex.c b/src/lj_lex.c index 669d2dfe..55e2bea1 100644 --- a/src/lj_lex.c +++ b/src/lj_lex.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include "lj_lex.h" | 23 | #include "lj_lex.h" |
| 24 | #include "lj_parse.h" | 24 | #include "lj_parse.h" |
| 25 | #include "lj_char.h" | 25 | #include "lj_char.h" |
| 26 | #include "lj_strscan.h" | ||
| 26 | 27 | ||
| 27 | /* Lua lexer token names. */ | 28 | /* Lua lexer token names. */ |
| 28 | static const char *const tokennames[] = { | 29 | static const char *const tokennames[] = { |
| @@ -84,100 +85,51 @@ static void inclinenumber(LexState *ls) | |||
| 84 | 85 | ||
| 85 | /* -- Scanner for terminals ----------------------------------------------- */ | 86 | /* -- Scanner for terminals ----------------------------------------------- */ |
| 86 | 87 | ||
| 87 | #if LJ_HASFFI | ||
| 88 | /* Load FFI library on-demand. Needed if we create cdata objects. */ | ||
| 89 | static void lex_loadffi(lua_State *L) | ||
| 90 | { | ||
| 91 | ptrdiff_t oldtop = savestack(L, L->top); | ||
| 92 | luaopen_ffi(L); | ||
| 93 | L->top = restorestack(L, oldtop); | ||
| 94 | } | ||
| 95 | |||
| 96 | /* Parse 64 bit integer. */ | ||
| 97 | static int lex_number64(LexState *ls, TValue *tv) | ||
| 98 | { | ||
| 99 | uint64_t n = 0; | ||
| 100 | uint8_t *p = (uint8_t *)ls->sb.buf; | ||
| 101 | CTypeID id = CTID_INT64; | ||
| 102 | GCcdata *cd; | ||
| 103 | int numl = 0; | ||
| 104 | if (p[0] == '0' && (p[1] & ~0x20) == 'X') { /* Hexadecimal. */ | ||
| 105 | p += 2; | ||
| 106 | if (!lj_char_isxdigit(*p)) return 0; | ||
| 107 | do { | ||
| 108 | n = n*16 + (*p & 15); | ||
| 109 | if (!lj_char_isdigit(*p)) n += 9; | ||
| 110 | p++; | ||
| 111 | } while (lj_char_isxdigit(*p)); | ||
| 112 | } else { /* Decimal. */ | ||
| 113 | if (!lj_char_isdigit(*p)) return 0; | ||
| 114 | do { | ||
| 115 | n = n*10 + (*p - '0'); | ||
| 116 | p++; | ||
| 117 | } while (lj_char_isdigit(*p)); | ||
| 118 | } | ||
| 119 | for (;;) { /* Parse suffixes. */ | ||
| 120 | if ((*p & ~0x20) == 'U') | ||
| 121 | id = CTID_UINT64; | ||
| 122 | else if ((*p & ~0x20) == 'L') | ||
| 123 | numl++; | ||
| 124 | else | ||
| 125 | break; | ||
| 126 | p++; | ||
| 127 | } | ||
| 128 | if (numl != 2 || *p != '\0') return 0; | ||
| 129 | /* Return cdata holding a 64 bit integer. */ | ||
| 130 | cd = lj_cdata_new_(ls->L, id, 8); | ||
| 131 | *(uint64_t *)cdataptr(cd) = n; | ||
| 132 | lj_parse_keepcdata(ls, tv, cd); | ||
| 133 | return 1; /* Ok. */ | ||
| 134 | } | ||
| 135 | #endif | ||
| 136 | |||
| 137 | /* Parse a number literal. */ | 88 | /* Parse a number literal. */ |
| 138 | static void lex_number(LexState *ls, TValue *tv) | 89 | static void lex_number(LexState *ls, TValue *tv) |
| 139 | { | 90 | { |
| 140 | int c, xp = 'E'; | 91 | StrScanFmt fmt; |
| 92 | int c, xp = 'e'; | ||
| 141 | lua_assert(lj_char_isdigit(ls->current)); | 93 | lua_assert(lj_char_isdigit(ls->current)); |
| 142 | if ((c = ls->current) == '0') { | 94 | if ((c = ls->current) == '0') { |
| 143 | save_and_next(ls); | 95 | save_and_next(ls); |
| 144 | if ((ls->current & ~0x20) == 'X') xp = 'P'; | 96 | if ((ls->current | 0x20) == 'x') xp = 'p'; |
| 145 | } | 97 | } |
| 146 | while (lj_char_isident(ls->current) || ls->current == '.' || | 98 | while (lj_char_isident(ls->current) || ls->current == '.' || |
| 147 | ((ls->current == '-' || ls->current == '+') && (c & ~0x20) == xp)) { | 99 | ((ls->current == '-' || ls->current == '+') && (c | 0x20) == xp)) { |
| 148 | c = ls->current; | 100 | c = ls->current; |
| 149 | save_and_next(ls); | 101 | save_and_next(ls); |
| 150 | } | 102 | } |
| 151 | #if LJ_HASFFI | ||
| 152 | c &= ~0x20; | ||
| 153 | if ((c == 'I' || c == 'L' || c == 'U') && !ctype_ctsG(G(ls->L))) | ||
| 154 | lex_loadffi(ls->L); | ||
| 155 | if (c == 'I') /* Parse imaginary part of complex number. */ | ||
| 156 | ls->sb.n--; | ||
| 157 | #endif | ||
| 158 | save(ls, '\0'); | 103 | save(ls, '\0'); |
| 159 | #if LJ_HASFFI | 104 | fmt = lj_strscan_scan((const uint8_t *)ls->sb.buf, tv, |
| 160 | if ((c == 'L' || c == 'U') && lex_number64(ls, tv)) { /* Parse 64 bit int. */ | 105 | (LJ_DUALNUM ? STRSCAN_OPT_TOINT : STRSCAN_OPT_TONUM) | |
| 161 | return; | 106 | (LJ_HASFFI ? (STRSCAN_OPT_LL|STRSCAN_OPT_IMAG) : 0)); |
| 162 | } else | 107 | if (LJ_DUALNUM && fmt == STRSCAN_INT) { |
| 163 | #endif | 108 | setitype(tv, LJ_TISNUM); |
| 164 | if (lj_str_numconv(ls->sb.buf, tv)) { | 109 | } else if (fmt == STRSCAN_NUM) { |
| 165 | #if LJ_HASFFI | 110 | /* Already in correct format. */ |
| 166 | if (c == 'I') { /* Return cdata holding a complex number. */ | 111 | } else if (LJ_HASFFI && fmt != STRSCAN_ERROR) { |
| 167 | GCcdata *cd = lj_cdata_new_(ls->L, CTID_COMPLEX_DOUBLE, 2*sizeof(double)); | 112 | lua_State *L = ls->L; |
| 168 | ((double *)cdataptr(cd))[0] = 0; | 113 | GCcdata *cd; |
| 169 | ((double *)cdataptr(cd))[1] = numberVnum(tv); | 114 | lua_assert(fmt == STRSCAN_I64 || fmt == STRSCAN_U64 || fmt == STRSCAN_IMAG); |
| 170 | lj_parse_keepcdata(ls, tv, cd); | 115 | if (!ctype_ctsG(G(L))) { |
| 116 | ptrdiff_t oldtop = savestack(L, L->top); | ||
| 117 | luaopen_ffi(L); /* Load FFI library on-demand. */ | ||
| 118 | L->top = restorestack(L, oldtop); | ||
| 171 | } | 119 | } |
| 172 | #endif | 120 | if (fmt == STRSCAN_IMAG) { |
| 173 | if (LJ_DUALNUM && tvisnum(tv)) { | 121 | cd = lj_cdata_new_(L, CTID_COMPLEX_DOUBLE, 2*sizeof(double)); |
| 174 | int32_t k = lj_num2int(numV(tv)); | 122 | ((double *)cdataptr(cd))[0] = 0; |
| 175 | if ((lua_Number)k == numV(tv)) /* -0 cannot end up here. */ | 123 | ((double *)cdataptr(cd))[1] = numV(tv); |
| 176 | setintV(tv, k); | 124 | } else { |
| 125 | cd = lj_cdata_new_(L, fmt==STRSCAN_I64 ? CTID_INT64 : CTID_UINT64, 8); | ||
| 126 | *(uint64_t *)cdataptr(cd) = tv->u64; | ||
| 177 | } | 127 | } |
| 178 | return; | 128 | lj_parse_keepcdata(ls, tv, cd); |
| 129 | } else { | ||
| 130 | lua_assert(fmt == STRSCAN_ERROR); | ||
| 131 | lj_lex_error(ls, TK_number, LJ_ERR_XNUMBER); | ||
| 179 | } | 132 | } |
| 180 | lj_lex_error(ls, TK_number, LJ_ERR_XNUMBER); | ||
| 181 | } | 133 | } |
| 182 | 134 | ||
| 183 | static int skip_sep(LexState *ls) | 135 | static int skip_sep(LexState *ls) |
diff --git a/src/lj_lib.c b/src/lj_lib.c index ae9b9301..4ab27f66 100644 --- a/src/lj_lib.c +++ b/src/lj_lib.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include "lj_bc.h" | 17 | #include "lj_bc.h" |
| 18 | #include "lj_dispatch.h" | 18 | #include "lj_dispatch.h" |
| 19 | #include "lj_vm.h" | 19 | #include "lj_vm.h" |
| 20 | #include "lj_strscan.h" | ||
| 20 | #include "lj_lib.h" | 21 | #include "lj_lib.h" |
| 21 | 22 | ||
| 22 | /* -- Library initialization ---------------------------------------------- */ | 23 | /* -- Library initialization ---------------------------------------------- */ |
| @@ -155,8 +156,7 @@ GCstr *lj_lib_optstr(lua_State *L, int narg) | |||
| 155 | void lj_lib_checknumber(lua_State *L, int narg) | 156 | void lj_lib_checknumber(lua_State *L, int narg) |
| 156 | { | 157 | { |
| 157 | TValue *o = L->base + narg-1; | 158 | TValue *o = L->base + narg-1; |
| 158 | if (!(o < L->top && | 159 | if (!(o < L->top && lj_strscan_numberobj(o))) |
| 159 | (tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), o))))) | ||
| 160 | lj_err_argt(L, narg, LUA_TNUMBER); | 160 | lj_err_argt(L, narg, LUA_TNUMBER); |
| 161 | } | 161 | } |
| 162 | #endif | 162 | #endif |
| @@ -165,7 +165,7 @@ lua_Number lj_lib_checknum(lua_State *L, int narg) | |||
| 165 | { | 165 | { |
| 166 | TValue *o = L->base + narg-1; | 166 | TValue *o = L->base + narg-1; |
| 167 | if (!(o < L->top && | 167 | if (!(o < L->top && |
| 168 | (tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), o))))) | 168 | (tvisnumber(o) || (tvisstr(o) && lj_strscan_num(strV(o), o))))) |
| 169 | lj_err_argt(L, narg, LUA_TNUMBER); | 169 | lj_err_argt(L, narg, LUA_TNUMBER); |
| 170 | if (LJ_UNLIKELY(tvisint(o))) { | 170 | if (LJ_UNLIKELY(tvisint(o))) { |
| 171 | lua_Number n = (lua_Number)intV(o); | 171 | lua_Number n = (lua_Number)intV(o); |
| @@ -179,8 +179,7 @@ lua_Number lj_lib_checknum(lua_State *L, int narg) | |||
| 179 | int32_t lj_lib_checkint(lua_State *L, int narg) | 179 | int32_t lj_lib_checkint(lua_State *L, int narg) |
| 180 | { | 180 | { |
| 181 | TValue *o = L->base + narg-1; | 181 | TValue *o = L->base + narg-1; |
| 182 | if (!(o < L->top && | 182 | if (!(o < L->top && lj_strscan_numberobj(o))) |
| 183 | (tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), o))))) | ||
| 184 | lj_err_argt(L, narg, LUA_TNUMBER); | 183 | lj_err_argt(L, narg, LUA_TNUMBER); |
| 185 | if (LJ_LIKELY(tvisint(o))) { | 184 | if (LJ_LIKELY(tvisint(o))) { |
| 186 | return intV(o); | 185 | return intV(o); |
| @@ -200,8 +199,7 @@ int32_t lj_lib_optint(lua_State *L, int narg, int32_t def) | |||
| 200 | int32_t lj_lib_checkbit(lua_State *L, int narg) | 199 | int32_t lj_lib_checkbit(lua_State *L, int narg) |
| 201 | { | 200 | { |
| 202 | TValue *o = L->base + narg-1; | 201 | TValue *o = L->base + narg-1; |
| 203 | if (!(o < L->top && | 202 | if (!(o < L->top && lj_strscan_numberobj(o))) |
| 204 | (tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), o))))) | ||
| 205 | lj_err_argt(L, narg, LUA_TNUMBER); | 203 | lj_err_argt(L, narg, LUA_TNUMBER); |
| 206 | if (LJ_LIKELY(tvisint(o))) { | 204 | if (LJ_LIKELY(tvisint(o))) { |
| 207 | return intV(o); | 205 | return intV(o); |
diff --git a/src/lj_meta.c b/src/lj_meta.c index ab8099e8..b33cb88d 100644 --- a/src/lj_meta.c +++ b/src/lj_meta.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include "lj_frame.h" | 18 | #include "lj_frame.h" |
| 19 | #include "lj_bc.h" | 19 | #include "lj_bc.h" |
| 20 | #include "lj_vm.h" | 20 | #include "lj_vm.h" |
| 21 | #include "lj_strscan.h" | ||
| 21 | 22 | ||
| 22 | /* -- Metamethod handling ------------------------------------------------- */ | 23 | /* -- Metamethod handling ------------------------------------------------- */ |
| 23 | 24 | ||
| @@ -193,7 +194,7 @@ static cTValue *str2num(cTValue *o, TValue *n) | |||
| 193 | return o; | 194 | return o; |
| 194 | else if (tvisint(o)) | 195 | else if (tvisint(o)) |
| 195 | return (setnumV(n, (lua_Number)intV(o)), n); | 196 | return (setnumV(n, (lua_Number)intV(o)), n); |
| 196 | else if (tvisstr(o) && lj_str_tonum(strV(o), n)) | 197 | else if (tvisstr(o) && lj_strscan_num(strV(o), n)) |
| 197 | return n; | 198 | return n; |
| 198 | else | 199 | else |
| 199 | return NULL; | 200 | return NULL; |
| @@ -436,12 +437,9 @@ void lj_meta_call(lua_State *L, TValue *func, TValue *top) | |||
| 436 | /* Helper for FORI. Coercion. */ | 437 | /* Helper for FORI. Coercion. */ |
| 437 | void LJ_FASTCALL lj_meta_for(lua_State *L, TValue *o) | 438 | void LJ_FASTCALL lj_meta_for(lua_State *L, TValue *o) |
| 438 | { | 439 | { |
| 439 | if (!(tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), o)))) | 440 | if (!lj_strscan_numberobj(o)) lj_err_msg(L, LJ_ERR_FORINIT); |
| 440 | lj_err_msg(L, LJ_ERR_FORINIT); | 441 | if (!lj_strscan_numberobj(o+1)) lj_err_msg(L, LJ_ERR_FORLIM); |
| 441 | if (!(tvisnumber(o+1) || (tvisstr(o+1) && lj_str_tonumber(strV(o+1), o+1)))) | 442 | if (!lj_strscan_numberobj(o+2)) lj_err_msg(L, LJ_ERR_FORSTEP); |
| 442 | lj_err_msg(L, LJ_ERR_FORLIM); | ||
| 443 | if (!(tvisnumber(o+2) || (tvisstr(o+2) && lj_str_tonumber(strV(o+2), o+2)))) | ||
| 444 | lj_err_msg(L, LJ_ERR_FORSTEP); | ||
| 445 | if (LJ_DUALNUM) { | 443 | if (LJ_DUALNUM) { |
| 446 | /* Ensure all slots are integers or all slots are numbers. */ | 444 | /* Ensure all slots are integers or all slots are numbers. */ |
| 447 | int32_t k[3]; | 445 | int32_t k[3]; |
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index 2240f5db..8f1c8770 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #endif | 25 | #endif |
| 26 | #include "lj_carith.h" | 26 | #include "lj_carith.h" |
| 27 | #include "lj_vm.h" | 27 | #include "lj_vm.h" |
| 28 | #include "lj_strscan.h" | ||
| 28 | 29 | ||
| 29 | /* Here's a short description how the FOLD engine processes instructions: | 30 | /* Here's a short description how the FOLD engine processes instructions: |
| 30 | ** | 31 | ** |
| @@ -693,7 +694,7 @@ LJFOLD(STRTO KGC) | |||
| 693 | LJFOLDF(kfold_strto) | 694 | LJFOLDF(kfold_strto) |
| 694 | { | 695 | { |
| 695 | TValue n; | 696 | TValue n; |
| 696 | if (lj_str_tonum(ir_kstr(fleft), &n)) | 697 | if (lj_strscan_num(ir_kstr(fleft), &n)) |
| 697 | return lj_ir_knum(J, numV(&n)); | 698 | return lj_ir_knum(J, numV(&n)); |
| 698 | return FAILFOLD; | 699 | return FAILFOLD; |
| 699 | } | 700 | } |
diff --git a/src/lj_opt_narrow.c b/src/lj_opt_narrow.c index 9bbb2083..2eb56c23 100644 --- a/src/lj_opt_narrow.c +++ b/src/lj_opt_narrow.c | |||
| @@ -11,13 +11,13 @@ | |||
| 11 | 11 | ||
| 12 | #if LJ_HASJIT | 12 | #if LJ_HASJIT |
| 13 | 13 | ||
| 14 | #include "lj_str.h" | ||
| 15 | #include "lj_bc.h" | 14 | #include "lj_bc.h" |
| 16 | #include "lj_ir.h" | 15 | #include "lj_ir.h" |
| 17 | #include "lj_jit.h" | 16 | #include "lj_jit.h" |
| 18 | #include "lj_iropt.h" | 17 | #include "lj_iropt.h" |
| 19 | #include "lj_trace.h" | 18 | #include "lj_trace.h" |
| 20 | #include "lj_vm.h" | 19 | #include "lj_vm.h" |
| 20 | #include "lj_strscan.h" | ||
| 21 | 21 | ||
| 22 | /* Rationale for narrowing optimizations: | 22 | /* Rationale for narrowing optimizations: |
| 23 | ** | 23 | ** |
| @@ -519,11 +519,11 @@ TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc, | |||
| 519 | { | 519 | { |
| 520 | if (tref_isstr(rb)) { | 520 | if (tref_isstr(rb)) { |
| 521 | rb = emitir(IRTG(IR_STRTO, IRT_NUM), rb, 0); | 521 | rb = emitir(IRTG(IR_STRTO, IRT_NUM), rb, 0); |
| 522 | lj_str_tonum(strV(vb), vb); | 522 | lj_strscan_num(strV(vb), vb); |
| 523 | } | 523 | } |
| 524 | if (tref_isstr(rc)) { | 524 | if (tref_isstr(rc)) { |
| 525 | rc = emitir(IRTG(IR_STRTO, IRT_NUM), rc, 0); | 525 | rc = emitir(IRTG(IR_STRTO, IRT_NUM), rc, 0); |
| 526 | lj_str_tonum(strV(vc), vc); | 526 | lj_strscan_num(strV(vc), vc); |
| 527 | } | 527 | } |
| 528 | /* Must not narrow MUL in non-DUALNUM variant, because it loses -0. */ | 528 | /* Must not narrow MUL in non-DUALNUM variant, because it loses -0. */ |
| 529 | if ((op >= IR_ADD && op <= (LJ_DUALNUM ? IR_MUL : IR_SUB)) && | 529 | if ((op >= IR_ADD && op <= (LJ_DUALNUM ? IR_MUL : IR_SUB)) && |
| @@ -541,7 +541,7 @@ TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc) | |||
| 541 | { | 541 | { |
| 542 | if (tref_isstr(rc)) { | 542 | if (tref_isstr(rc)) { |
| 543 | rc = emitir(IRTG(IR_STRTO, IRT_NUM), rc, 0); | 543 | rc = emitir(IRTG(IR_STRTO, IRT_NUM), rc, 0); |
| 544 | lj_str_tonum(strV(vc), vc); | 544 | lj_strscan_num(strV(vc), vc); |
| 545 | } | 545 | } |
| 546 | if (tref_isinteger(rc)) { | 546 | if (tref_isinteger(rc)) { |
| 547 | if ((uint32_t)numberVint(vc) != 0x80000000u) | 547 | if ((uint32_t)numberVint(vc) != 0x80000000u) |
| @@ -555,7 +555,7 @@ TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc) | |||
| 555 | TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vc) | 555 | TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vc) |
| 556 | { | 556 | { |
| 557 | TRef tmp; | 557 | TRef tmp; |
| 558 | if (tvisstr(vc) && !lj_str_tonum(strV(vc), vc)) | 558 | if (tvisstr(vc) && !lj_strscan_num(strV(vc), vc)) |
| 559 | lj_trace_err(J, LJ_TRERR_BADTYPE); | 559 | lj_trace_err(J, LJ_TRERR_BADTYPE); |
| 560 | if ((LJ_DUALNUM || (J->flags & JIT_F_OPT_NARROW)) && | 560 | if ((LJ_DUALNUM || (J->flags & JIT_F_OPT_NARROW)) && |
| 561 | tref_isinteger(rb) && tref_isinteger(rc) && | 561 | tref_isinteger(rb) && tref_isinteger(rc) && |
| @@ -575,7 +575,7 @@ TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vc) | |||
| 575 | /* Narrowing of power operator or math.pow. */ | 575 | /* Narrowing of power operator or math.pow. */ |
| 576 | TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vc) | 576 | TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vc) |
| 577 | { | 577 | { |
| 578 | if (tvisstr(vc) && !lj_str_tonum(strV(vc), vc)) | 578 | if (tvisstr(vc) && !lj_strscan_num(strV(vc), vc)) |
| 579 | lj_trace_err(J, LJ_TRERR_BADTYPE); | 579 | lj_trace_err(J, LJ_TRERR_BADTYPE); |
| 580 | /* Narrowing must be unconditional to preserve (-x)^i semantics. */ | 580 | /* Narrowing must be unconditional to preserve (-x)^i semantics. */ |
| 581 | if (tvisint(vc) || numisint(numV(vc))) { | 581 | if (tvisint(vc) || numisint(numV(vc))) { |
diff --git a/src/lj_str.c b/src/lj_str.c index 7bf4848a..1060ec6d 100644 --- a/src/lj_str.c +++ b/src/lj_str.c | |||
| @@ -169,85 +169,6 @@ void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s) | |||
| 169 | 169 | ||
| 170 | /* -- Type conversions ---------------------------------------------------- */ | 170 | /* -- Type conversions ---------------------------------------------------- */ |
| 171 | 171 | ||
| 172 | /* Convert string object to number. */ | ||
| 173 | int LJ_FASTCALL lj_str_tonum(GCstr *str, TValue *n) | ||
| 174 | { | ||
| 175 | int ok = lj_str_numconv(strdata(str), n); | ||
| 176 | if (ok && tvisint(n)) | ||
| 177 | setnumV(n, (lua_Number)intV(n)); | ||
| 178 | return ok; | ||
| 179 | } | ||
| 180 | |||
| 181 | int LJ_FASTCALL lj_str_tonumber(GCstr *str, TValue *n) | ||
| 182 | { | ||
| 183 | return lj_str_numconv(strdata(str), n); | ||
| 184 | } | ||
| 185 | |||
| 186 | /* Convert string to number. */ | ||
| 187 | int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n) | ||
| 188 | { | ||
| 189 | #if LJ_DUALNUM | ||
| 190 | int sign = 1; | ||
| 191 | #else | ||
| 192 | lua_Number sign = 1; | ||
| 193 | #endif | ||
| 194 | const uint8_t *p = (const uint8_t *)s; | ||
| 195 | while (lj_char_isspace(*p)) p++; | ||
| 196 | if (*p == '-') { p++; sign = -1; } else if (*p == '+') { p++; } | ||
| 197 | if ((uint32_t)(*p - '0') < 10) { | ||
| 198 | uint32_t k = (uint32_t)(*p++ - '0'); | ||
| 199 | if (k == 0 && ((*p & ~0x20) == 'X')) { | ||
| 200 | p++; | ||
| 201 | if (!lj_char_isxdigit(*p)) | ||
| 202 | return 0; /* Don't accept '0x' without hex digits. */ | ||
| 203 | do { | ||
| 204 | if (k >= 0x10000000u) goto parsedbl; | ||
| 205 | k = (k << 4) + (*p & 15u); | ||
| 206 | if (!lj_char_isdigit(*p)) k += 9; | ||
| 207 | p++; | ||
| 208 | } while (lj_char_isxdigit(*p)); | ||
| 209 | } else { | ||
| 210 | while ((uint32_t)(*p - '0') < 10) { | ||
| 211 | if (LJ_UNLIKELY(k >= 429496729) && (k != 429496729 || *p > '5')) | ||
| 212 | goto parsedbl; | ||
| 213 | k = k * 10u + (uint32_t)(*p++ - '0'); | ||
| 214 | } | ||
| 215 | } | ||
| 216 | while (LJ_UNLIKELY(lj_char_isspace(*p))) p++; | ||
| 217 | if (LJ_LIKELY(*p == '\0')) { | ||
| 218 | #if LJ_DUALNUM | ||
| 219 | if (sign == 1) { | ||
| 220 | if (k < 0x80000000u) { | ||
| 221 | setintV(n, (int32_t)k); | ||
| 222 | return 1; | ||
| 223 | } | ||
| 224 | } else if (k <= 0x80000000u) { | ||
| 225 | setintV(n, -(int32_t)k); | ||
| 226 | return 1; | ||
| 227 | } | ||
| 228 | #endif | ||
| 229 | setnumV(n, sign * (lua_Number)k); | ||
| 230 | return 1; | ||
| 231 | } | ||
| 232 | } | ||
| 233 | parsedbl: | ||
| 234 | { | ||
| 235 | TValue tv; | ||
| 236 | char *endptr; | ||
| 237 | setnumV(&tv, lua_str2number(s, &endptr)); | ||
| 238 | if (endptr == s) return 0; /* Conversion failed. */ | ||
| 239 | if (LJ_UNLIKELY(*endptr != '\0')) { | ||
| 240 | while (lj_char_isspace((uint8_t)*endptr)) endptr++; | ||
| 241 | if (*endptr != '\0') return 0; /* Invalid trailing characters? */ | ||
| 242 | } | ||
| 243 | if (LJ_LIKELY(!tvisnan(&tv))) | ||
| 244 | setnumV(n, numV(&tv)); | ||
| 245 | else | ||
| 246 | setnanV(n); /* Canonicalize injected NaNs. */ | ||
| 247 | return 1; | ||
| 248 | } | ||
| 249 | } | ||
| 250 | |||
| 251 | /* Print number to buffer. Canonicalizes non-finite values. */ | 172 | /* Print number to buffer. Canonicalizes non-finite values. */ |
| 252 | size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o) | 173 | size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o) |
| 253 | { | 174 | { |
diff --git a/src/lj_str.h b/src/lj_str.h index 3d9be4f3..2bf34ed4 100644 --- a/src/lj_str.h +++ b/src/lj_str.h | |||
| @@ -20,9 +20,6 @@ LJ_FUNC void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s); | |||
| 20 | #define lj_str_newlit(L, s) (lj_str_new(L, "" s, sizeof(s)-1)) | 20 | #define lj_str_newlit(L, s) (lj_str_new(L, "" s, sizeof(s)-1)) |
| 21 | 21 | ||
| 22 | /* Type conversions. */ | 22 | /* Type conversions. */ |
| 23 | LJ_FUNC int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n); | ||
| 24 | LJ_FUNC int LJ_FASTCALL lj_str_tonum(GCstr *str, TValue *n); | ||
| 25 | LJ_FUNC int LJ_FASTCALL lj_str_tonumber(GCstr *str, TValue *n); | ||
| 26 | LJ_FUNC size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o); | 23 | LJ_FUNC size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o); |
| 27 | LJ_FUNC char * LJ_FASTCALL lj_str_bufint(char *p, int32_t k); | 24 | LJ_FUNC char * LJ_FASTCALL lj_str_bufint(char *p, int32_t k); |
| 28 | LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np); | 25 | LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np); |
diff --git a/src/lj_strscan.c b/src/lj_strscan.c new file mode 100644 index 00000000..31189ae7 --- /dev/null +++ b/src/lj_strscan.c | |||
| @@ -0,0 +1,497 @@ | |||
| 1 | /* | ||
| 2 | ** String scanning. | ||
| 3 | ** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <math.h> | ||
| 7 | |||
| 8 | #define lj_strscan_c | ||
| 9 | #define LUA_CORE | ||
| 10 | |||
| 11 | #include "lj_obj.h" | ||
| 12 | #include "lj_char.h" | ||
| 13 | #include "lj_strscan.h" | ||
| 14 | |||
| 15 | /* -- Scanning numbers ---------------------------------------------------- */ | ||
| 16 | |||
| 17 | /* | ||
| 18 | ** Rationale for the builtin string to number conversion library: | ||
| 19 | ** | ||
| 20 | ** It removes a dependency on libc's strtod(), which is a true portability | ||
| 21 | ** nightmare. Mainly due to the plethora of supported OS and toolchain | ||
| 22 | ** combinations. Sadly, the various implementations | ||
| 23 | ** a) are often buggy, incomplete (no hex floats) and/or imprecise, | ||
| 24 | ** b) sometimes crash or hang on certain inputs, | ||
| 25 | ** c) return non-standard NaNs that need to be filtered out, and | ||
| 26 | ** d) fail if the locale-specific decimal separator is not a dot, | ||
| 27 | ** which can only be fixed with atrocious workarounds. | ||
| 28 | ** | ||
| 29 | ** Also, most of the strtod() implementations are hopelessly bloated, | ||
| 30 | ** which is not just an I-cache hog, but a problem for static linkage | ||
| 31 | ** on embedded systems, too. | ||
| 32 | ** | ||
| 33 | ** OTOH the builtin conversion function is very compact. Even though it | ||
| 34 | ** does a lot more, like parsing long longs, octal or imaginary numbers | ||
| 35 | ** and returning the result in different formats: | ||
| 36 | ** a) It needs less than 3 KB (!) of machine code (on x64 with -Os), | ||
| 37 | ** b) it doesn't perform any dynamic allocation and, | ||
| 38 | ** c) it needs only around 600 bytes of stack space. | ||
| 39 | ** | ||
| 40 | ** The builtin function is faster than strtod() for typical inputs, e.g. | ||
| 41 | ** "123", "1.5" or "1e6". Arguably, it's slower for very large exponents, | ||
| 42 | ** which are not very common (this could be fixed, if needed). | ||
| 43 | ** | ||
| 44 | ** And most importantly, the builtin function is equally precise on all | ||
| 45 | ** platforms. It correctly converts and rounds any input to a double. | ||
| 46 | ** If this is not the case, please send a bug report -- but PLEASE verify | ||
| 47 | ** that the implementation you're comparing to is not the culprit! | ||
| 48 | ** | ||
| 49 | ** The implementation quickly pre-scans the entire string first and | ||
| 50 | ** handles simple integers on-the-fly. Otherwise, it dispatches to the | ||
| 51 | ** base-specific parser. Hex and octal is straightforward. | ||
| 52 | ** | ||
| 53 | ** Decimal to binary conversion uses a fixed-length circular buffer in | ||
| 54 | ** base 100. Some simple cases are handled directly. For other cases, the | ||
| 55 | ** number in the buffer is up-scaled or down-scaled until the integer part | ||
| 56 | ** is in the proper range. Then the integer part is rounded and converted | ||
| 57 | ** to a double which is finally rescaled to the result. Denormals need | ||
| 58 | ** special treatment to prevent incorrect 'double rounding'. | ||
| 59 | */ | ||
| 60 | |||
| 61 | /* Definitions for circular decimal digit buffer (base 100 = 2 digits/byte). */ | ||
| 62 | #define STRSCAN_DIG 1024 | ||
| 63 | #define STRSCAN_MAXDIG 800 /* 772 + extra are sufficient. */ | ||
| 64 | #define STRSCAN_DDIG (STRSCAN_DIG/2) | ||
| 65 | #define STRSCAN_DMASK (STRSCAN_DDIG-1) | ||
| 66 | |||
| 67 | /* Helpers for circular buffer. */ | ||
| 68 | #define DNEXT(a) (((a)+1) & STRSCAN_DMASK) | ||
| 69 | #define DPREV(a) (((a)-1) & STRSCAN_DMASK) | ||
| 70 | #define DLEN(lo, hi) ((int32_t)(((lo)-(hi)) & STRSCAN_DMASK)) | ||
| 71 | |||
| 72 | #define casecmp(c, k) (((c) | 0x20) == k) | ||
| 73 | |||
| 74 | /* Final conversion to double. */ | ||
| 75 | static void strscan_double(uint64_t x, TValue *o, int32_t ex2, int32_t neg) | ||
| 76 | { | ||
| 77 | double n; | ||
| 78 | |||
| 79 | /* Avoid double rounding for denormals. */ | ||
| 80 | if (LJ_UNLIKELY(ex2 <= -1075 && x != 0)) { | ||
| 81 | /* NYI: all of this generates way too much code on 32 bit CPUs. */ | ||
| 82 | #if defined(__GNUC__) && LJ_64 | ||
| 83 | int32_t b = (int32_t)(__builtin_clzll(x)^63); | ||
| 84 | #else | ||
| 85 | int32_t b = (x>>32) ? 32+(int32_t)lj_fls((uint32_t)(x>>32)) : | ||
| 86 | (int32_t)lj_fls((uint32_t)x); | ||
| 87 | #endif | ||
| 88 | if ((int32_t)b + ex2 <= -1023 && (int32_t)b + ex2 >= -1075) { | ||
| 89 | uint64_t rb = (uint64_t)1 << (-1075-ex2); | ||
| 90 | if ((x & rb) && ((x & (rb+rb+rb-1)))) x += rb+rb; | ||
| 91 | x = (x & ~(rb+rb-1)); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | /* Convert to double using a signed int64_t conversion, then rescale. */ | ||
| 96 | lua_assert((int64_t)x >= 0); | ||
| 97 | n = (double)(int64_t)x; | ||
| 98 | if (neg) n = -n; | ||
| 99 | if (ex2) n = ldexp(n, ex2); | ||
| 100 | o->n = n; | ||
| 101 | } | ||
| 102 | |||
| 103 | /* Parse hexadecimal number. */ | ||
| 104 | static StrScanFmt strscan_hex(const uint8_t *p, TValue *o, | ||
| 105 | StrScanFmt fmt, uint32_t opt, | ||
| 106 | int32_t ex2, int32_t neg, uint32_t dig) | ||
| 107 | { | ||
| 108 | uint64_t x = 0; | ||
| 109 | uint32_t i; | ||
| 110 | |||
| 111 | /* Scan hex digits. */ | ||
| 112 | for (i = dig > 16 ? 16 : dig ; i; i--, p++) { | ||
| 113 | uint32_t d = (*p != '.' ? *p : *++p); if (d > '9') d += 9; | ||
| 114 | x = (x << 4) + (d & 15); | ||
| 115 | } | ||
| 116 | |||
| 117 | /* Summarize rounding-effect of excess digits. */ | ||
| 118 | for (i = 16; i < dig; i++, p++) | ||
| 119 | x |= ((*p != '.' ? *p : *++p) != '0'), ex2 += 4; | ||
| 120 | |||
| 121 | /* Format-specific handling. */ | ||
| 122 | switch (fmt) { | ||
| 123 | case STRSCAN_INT: | ||
| 124 | if (!(opt & STRSCAN_OPT_TONUM) && x < 0x80000000u+neg) { | ||
| 125 | o->i = neg ? -(int)x : (int)x; | ||
| 126 | return STRSCAN_INT; /* Fast path for 32 bit integers. */ | ||
| 127 | } | ||
| 128 | if (!(opt & STRSCAN_OPT_C)) { fmt = STRSCAN_NUM; break; } | ||
| 129 | /* fallthrough */ | ||
| 130 | case STRSCAN_U32: | ||
| 131 | if (dig > 8) return STRSCAN_ERROR; | ||
| 132 | o->i = neg ? -(int)x : (int)x; | ||
| 133 | return STRSCAN_U32; | ||
| 134 | case STRSCAN_I64: | ||
| 135 | case STRSCAN_U64: | ||
| 136 | if (dig > 16) return STRSCAN_ERROR; | ||
| 137 | o->u64 = neg ? (uint64_t)-(int64_t)x : x; | ||
| 138 | return fmt; | ||
| 139 | default: | ||
| 140 | break; | ||
| 141 | } | ||
| 142 | |||
| 143 | /* Reduce range then convert to double. */ | ||
| 144 | if ((x & U64x(c0000000,0000000))) { x = (x >> 2) | (x & 3); ex2 += 2; } | ||
| 145 | strscan_double(x, o, ex2, neg); | ||
| 146 | return fmt; | ||
| 147 | } | ||
| 148 | |||
| 149 | /* Parse octal number. */ | ||
| 150 | static StrScanFmt strscan_oct(const uint8_t *p, TValue *o, | ||
| 151 | StrScanFmt fmt, int32_t neg, uint32_t dig) | ||
| 152 | { | ||
| 153 | uint64_t x = 0; | ||
| 154 | |||
| 155 | /* Scan octal digits. */ | ||
| 156 | if (dig > 22 || (dig == 22 && *p > '1')) return STRSCAN_ERROR; | ||
| 157 | while (dig-- > 0) { | ||
| 158 | if (!(*p >= '0' && *p <= '7')) return STRSCAN_ERROR; | ||
| 159 | x = (x << 3) + (*p++ & 7); | ||
| 160 | } | ||
| 161 | |||
| 162 | /* Format-specific handling. */ | ||
| 163 | switch (fmt) { | ||
| 164 | case STRSCAN_INT: | ||
| 165 | if (x >= 0x80000000u+neg) fmt = STRSCAN_U32; | ||
| 166 | /* fallthrough */ | ||
| 167 | case STRSCAN_U32: | ||
| 168 | if ((x >> 32)) return STRSCAN_ERROR; | ||
| 169 | o->i = neg ? -(int)x : (int)x; | ||
| 170 | break; | ||
| 171 | default: | ||
| 172 | case STRSCAN_I64: | ||
| 173 | case STRSCAN_U64: | ||
| 174 | o->u64 = neg ? (uint64_t)-(int64_t)x : x; | ||
| 175 | break; | ||
| 176 | } | ||
| 177 | return fmt; | ||
| 178 | } | ||
| 179 | |||
| 180 | /* Parse decimal number. */ | ||
| 181 | static StrScanFmt strscan_dec(const uint8_t *p, TValue *o, | ||
| 182 | StrScanFmt fmt, uint32_t opt, | ||
| 183 | int32_t ex10, int32_t neg, uint32_t dig) | ||
| 184 | { | ||
| 185 | uint8_t xi[STRSCAN_DDIG], *xip = xi; | ||
| 186 | |||
| 187 | if (dig) { | ||
| 188 | uint32_t i = dig; | ||
| 189 | if (i > STRSCAN_MAXDIG) { | ||
| 190 | ex10 -= (int32_t)(i - STRSCAN_MAXDIG); | ||
| 191 | i = STRSCAN_MAXDIG; | ||
| 192 | } | ||
| 193 | /* Scan unaligned leading digit. */ | ||
| 194 | if (((ex10^i) & 1)) | ||
| 195 | *xip++ = ((*p != '.' ? *p : *++p) & 15), i--, p++; | ||
| 196 | /* Scan aligned double-digits. */ | ||
| 197 | for ( ; i > 1; i -= 2) { | ||
| 198 | uint32_t d = 10 * ((*p != '.' ? *p : *++p) & 15); p++; | ||
| 199 | *xip++ = d + ((*p != '.' ? *p : *++p) & 15); p++; | ||
| 200 | } | ||
| 201 | /* Scan and realign trailing digit. */ | ||
| 202 | if (i) *xip++ = 10 * ((*p != '.' ? *p : *++p) & 15), ex10--, p++; | ||
| 203 | |||
| 204 | /* Summarize rounding-effect of excess digits. */ | ||
| 205 | if (dig > STRSCAN_MAXDIG) { | ||
| 206 | do { | ||
| 207 | if ((*p != '.' ? *p : *++p) != '0') { xip[-1] |= 1; break; } | ||
| 208 | p++; | ||
| 209 | } while (--dig > STRSCAN_MAXDIG); | ||
| 210 | dig = STRSCAN_MAXDIG; | ||
| 211 | } else { /* Simplify exponent. */ | ||
| 212 | while (ex10 > 0 && dig <= 18) *xip++ = 0, ex10 -= 2, dig += 2; | ||
| 213 | } | ||
| 214 | } else { /* Only got zeros. */ | ||
| 215 | ex10 = 0; | ||
| 216 | xi[0] = 0; | ||
| 217 | } | ||
| 218 | |||
| 219 | /* Fast path for numbers in integer format (but handles e.g. 1e6, too). */ | ||
| 220 | if (dig <= 20 && ex10 == 0) { | ||
| 221 | uint8_t *xis; | ||
| 222 | uint64_t x = xi[0]; | ||
| 223 | double n; | ||
| 224 | for (xis = xi+1; xis < xip; xis++) x = x * 100 + *xis; | ||
| 225 | if (!(dig == 20 && (xi[0] > 18 || (int64_t)x >= 0))) { /* No overflow? */ | ||
| 226 | /* Format-specific handling. */ | ||
| 227 | switch (fmt) { | ||
| 228 | case STRSCAN_INT: | ||
| 229 | if (!(opt & STRSCAN_OPT_TONUM) && x < 0x80000000u+neg) { | ||
| 230 | o->i = neg ? -(int)x : (int)x; | ||
| 231 | return STRSCAN_INT; /* Fast path for 32 bit integers. */ | ||
| 232 | } | ||
| 233 | if (!(opt & STRSCAN_OPT_C)) { fmt = STRSCAN_NUM; goto plainnumber; } | ||
| 234 | /* fallthrough */ | ||
| 235 | case STRSCAN_U32: | ||
| 236 | if ((x >> 32) != 0) return STRSCAN_ERROR; | ||
| 237 | o->i = neg ? -(int)x : (int)x; | ||
| 238 | return STRSCAN_U32; | ||
| 239 | case STRSCAN_I64: | ||
| 240 | case STRSCAN_U64: | ||
| 241 | o->u64 = neg ? (uint64_t)-(int64_t)x : x; | ||
| 242 | return fmt; | ||
| 243 | default: | ||
| 244 | plainnumber: /* Fast path for plain numbers < 2^63. */ | ||
| 245 | if ((int64_t)x < 0) break; | ||
| 246 | n = (double)(int64_t)x; | ||
| 247 | if (neg) n = -n; | ||
| 248 | o->n = n; | ||
| 249 | return fmt; | ||
| 250 | } | ||
| 251 | } | ||
| 252 | } | ||
| 253 | |||
| 254 | /* Slow non-integer path. */ | ||
| 255 | if (fmt == STRSCAN_INT) { | ||
| 256 | if ((opt & STRSCAN_OPT_C)) return STRSCAN_ERROR; | ||
| 257 | fmt = STRSCAN_NUM; | ||
| 258 | } else if (fmt > STRSCAN_INT) { | ||
| 259 | return STRSCAN_ERROR; | ||
| 260 | } | ||
| 261 | { | ||
| 262 | uint32_t hi = 0, lo = (uint32_t)(xip-xi); | ||
| 263 | int32_t ex2 = 0, idig = (int32_t)lo + (ex10 >> 1); | ||
| 264 | |||
| 265 | lua_assert(lo > 0 && (ex10 & 1) == 0); | ||
| 266 | |||
| 267 | /* Handle simple overflow/underflow. */ | ||
| 268 | if (idig > 310/2) { if (neg) setminfV(o); else setpinfV(o); return fmt; } | ||
| 269 | else if (idig < -326/2) { o->n = 0.0; return fmt; } | ||
| 270 | |||
| 271 | /* Scale up until we have at least 17 or 18 integer part digits. */ | ||
| 272 | while (idig < 9 && idig < DLEN(lo, hi)) { | ||
| 273 | uint32_t i, cy = 0; | ||
| 274 | ex2 -= 6; | ||
| 275 | for (i = DPREV(lo); ; i = DPREV(i)) { | ||
| 276 | uint32_t d = (xi[i] << 6) + cy; | ||
| 277 | cy = (((d >> 2) * 5243) >> 17); d = d - cy * 100; /* Div/mod 100. */ | ||
| 278 | xi[i] = (uint8_t)d; | ||
| 279 | if (i == hi) break; | ||
| 280 | if (d == 0 && i == DPREV(lo)) lo = i; | ||
| 281 | } | ||
| 282 | if (cy) { | ||
| 283 | if (xi[DPREV(lo)] == 0) lo = DPREV(lo); | ||
| 284 | else if (hi == lo) { lo = DPREV(lo); xi[DPREV(lo)] |= xi[lo]; } | ||
| 285 | hi = DPREV(hi); xi[hi] = (uint8_t)cy; idig++; | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | /* Scale down until no more than 17 or 18 integer part digits remain. */ | ||
| 290 | while (idig > 9) { | ||
| 291 | uint32_t i, cy = 0; | ||
| 292 | ex2 += 6; | ||
| 293 | for (i = hi; i != lo; i = DNEXT(i)) { | ||
| 294 | cy += xi[i]; | ||
| 295 | xi[i] = (cy >> 6); | ||
| 296 | cy = 100 * (cy & 0x3f); | ||
| 297 | if (xi[i] == 0 && i == hi) hi = DNEXT(hi), idig--; | ||
| 298 | } | ||
| 299 | while (cy) { | ||
| 300 | if (hi == lo) { xi[DPREV(lo)] |= 1; break; } | ||
| 301 | xi[lo] = (cy >> 6); lo = DNEXT(lo); | ||
| 302 | cy = 100 * (cy & 0x3f); | ||
| 303 | } | ||
| 304 | } | ||
| 305 | |||
| 306 | /* Collect integer part digits and convert to rescaled double. */ | ||
| 307 | { | ||
| 308 | uint64_t x = xi[hi]; | ||
| 309 | uint32_t i; | ||
| 310 | for (i = DNEXT(hi); --idig > 0 && i != lo; i = DNEXT(i)) | ||
| 311 | x = x * 100 + xi[i]; | ||
| 312 | if (i == lo) { | ||
| 313 | while (--idig >= 0) x = x * 100; | ||
| 314 | } else { /* Gather round bit from remaining digits. */ | ||
| 315 | x <<= 1; ex2--; | ||
| 316 | do { | ||
| 317 | if (xi[i]) { x |= 1; break; } | ||
| 318 | i = DNEXT(i); | ||
| 319 | } while (i != lo); | ||
| 320 | } | ||
| 321 | strscan_double(x, o, ex2, neg); | ||
| 322 | } | ||
| 323 | } | ||
| 324 | return fmt; | ||
| 325 | } | ||
| 326 | |||
| 327 | /* Scan string containing a number. Returns format. Returns value in o. */ | ||
| 328 | StrScanFmt lj_strscan_scan(const uint8_t *p, TValue *o, uint32_t opt) | ||
| 329 | { | ||
| 330 | int32_t neg = 0; | ||
| 331 | |||
| 332 | /* Remove leading space, parse sign and non-numbers. */ | ||
| 333 | if (LJ_UNLIKELY(!lj_char_isdigit(*p))) { | ||
| 334 | while (lj_char_isspace(*p)) p++; | ||
| 335 | if (*p == '+' || *p == '-') neg = (*p++ == '-'); | ||
| 336 | if (LJ_UNLIKELY(*p >= 'A')) { /* Parse "inf", "infinity" or "nan". */ | ||
| 337 | TValue tmp; | ||
| 338 | setnanV(&tmp); | ||
| 339 | if (casecmp(p[0],'i') && casecmp(p[1],'n') && casecmp(p[2],'f')) { | ||
| 340 | if (neg) setminfV(&tmp); else setpinfV(&tmp); | ||
| 341 | p += 3; | ||
| 342 | if (casecmp(p[0],'i') && casecmp(p[1],'n') && casecmp(p[2],'i') && | ||
| 343 | casecmp(p[3],'t') && casecmp(p[4],'y')) p += 5; | ||
| 344 | } else if (casecmp(p[0],'n') && casecmp(p[1],'a') && casecmp(p[2],'n')) { | ||
| 345 | p += 3; | ||
| 346 | } | ||
| 347 | while (lj_char_isspace(*p)) p++; | ||
| 348 | if (*p) return STRSCAN_ERROR; | ||
| 349 | o->u64 = tmp.u64; | ||
| 350 | return STRSCAN_NUM; | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 354 | /* Parse regular number. */ | ||
| 355 | { | ||
| 356 | StrScanFmt fmt = STRSCAN_INT; | ||
| 357 | int cmask = LJ_CHAR_DIGIT; | ||
| 358 | int base = (opt & STRSCAN_OPT_C) && *p == '0' ? 0 : 10; | ||
| 359 | const uint8_t *sp, *dp = NULL; | ||
| 360 | uint32_t dig = 0, hasdig = 0, x = 0; | ||
| 361 | int32_t ex = 0; | ||
| 362 | |||
| 363 | /* Determine base and skip leading zeros. */ | ||
| 364 | if (LJ_UNLIKELY(*p <= '0')) { | ||
| 365 | if (*p == '0' && casecmp(p[1], 'x')) | ||
| 366 | base = 16, cmask = LJ_CHAR_XDIGIT, p += 2; | ||
| 367 | for ( ; ; p++) { | ||
| 368 | if (*p == '0') { | ||
| 369 | hasdig = 1; | ||
| 370 | } else if (*p == '.') { | ||
| 371 | if (dp) return STRSCAN_ERROR; | ||
| 372 | dp = p; | ||
| 373 | } else { | ||
| 374 | break; | ||
| 375 | } | ||
| 376 | } | ||
| 377 | } | ||
| 378 | |||
| 379 | /* Preliminary digit and decimal point scan. */ | ||
| 380 | for (sp = p; ; p++) { | ||
| 381 | if (LJ_LIKELY(lj_char_isa(*p, cmask))) { | ||
| 382 | x = x * 10 + (*p & 15); /* For fast path below. */ | ||
| 383 | dig++; | ||
| 384 | } else if (*p == '.') { | ||
| 385 | if (dp) return STRSCAN_ERROR; | ||
| 386 | dp = p; | ||
| 387 | } else { | ||
| 388 | break; | ||
| 389 | } | ||
| 390 | } | ||
| 391 | if (!(hasdig | dig)) return STRSCAN_ERROR; | ||
| 392 | |||
| 393 | /* Handle decimal point. */ | ||
| 394 | if (dp) { | ||
| 395 | fmt = STRSCAN_NUM; | ||
| 396 | if (dig) { | ||
| 397 | ex = (int)(dp-(p-1)); dp = p-1; | ||
| 398 | while (ex < 0 && *dp-- == '0') ex++, dig--; /* Skip trailing zeros. */ | ||
| 399 | if (base == 16) ex *= 4; | ||
| 400 | } | ||
| 401 | } | ||
| 402 | |||
| 403 | /* Parse exponent. */ | ||
| 404 | if (casecmp(*p, (uint32_t)(base == 16 ? 'p' : 'e'))) { | ||
| 405 | uint32_t xx; | ||
| 406 | int negx = 0; | ||
| 407 | fmt = STRSCAN_NUM; p++; | ||
| 408 | if (*p == '+' || *p == '-') negx = (*p++ == '-'); | ||
| 409 | if (!lj_char_isdigit(*p)) return STRSCAN_ERROR; | ||
| 410 | xx = (*p++ & 15); | ||
| 411 | while (lj_char_isdigit(*p)) { | ||
| 412 | if (xx < 65536) xx = xx * 10 + (*p & 15); | ||
| 413 | p++; | ||
| 414 | } | ||
| 415 | ex += negx ? -(int)xx : (int)xx; | ||
| 416 | } | ||
| 417 | |||
| 418 | /* Parse suffix. */ | ||
| 419 | if (*p) { | ||
| 420 | /* I (IMAG), U (U32), LL (I64), ULL/LLU (U64), L (long), UL/LU (ulong). */ | ||
| 421 | /* NYI: f (float). Not needed until cp_number() handles non-integers. */ | ||
| 422 | if (casecmp(*p, 'i')) { | ||
| 423 | if (!(opt & STRSCAN_OPT_IMAG)) return STRSCAN_ERROR; | ||
| 424 | p++; fmt = STRSCAN_IMAG; | ||
| 425 | } else if (fmt == STRSCAN_INT) { | ||
| 426 | if (casecmp(*p, 'u')) p++, fmt = STRSCAN_U32; | ||
| 427 | if (casecmp(*p, 'l')) { | ||
| 428 | p++; | ||
| 429 | if (casecmp(*p, 'l')) p++, fmt += STRSCAN_I64 - STRSCAN_INT; | ||
| 430 | else if (!(opt & STRSCAN_OPT_C)) return STRSCAN_ERROR; | ||
| 431 | else if (sizeof(long) == 8) fmt += STRSCAN_I64 - STRSCAN_INT; | ||
| 432 | } | ||
| 433 | if (casecmp(*p, 'u') && (fmt == STRSCAN_INT || fmt == STRSCAN_I64)) | ||
| 434 | p++, fmt += STRSCAN_U32 - STRSCAN_INT; | ||
| 435 | if ((fmt == STRSCAN_U32 && !(opt & STRSCAN_OPT_C)) || | ||
| 436 | (fmt >= STRSCAN_I64 && !(opt & STRSCAN_OPT_LL))) | ||
| 437 | return STRSCAN_ERROR; | ||
| 438 | } | ||
| 439 | while (lj_char_isspace(*p)) p++; | ||
| 440 | if (*p) return STRSCAN_ERROR; | ||
| 441 | } | ||
| 442 | |||
| 443 | /* Fast path for decimal 32 bit integers. */ | ||
| 444 | if (fmt == STRSCAN_INT && base == 10 && | ||
| 445 | (dig < 10 || (dig == 10 && *sp <= '2' && x < 0x80000000u+neg))) { | ||
| 446 | if ((opt & STRSCAN_OPT_TONUM)) { | ||
| 447 | double n = (double)(int32_t)x; | ||
| 448 | if (neg) n = -n; | ||
| 449 | o->n = n; | ||
| 450 | return STRSCAN_NUM; | ||
| 451 | } else { | ||
| 452 | o->i = neg ? -(int)x : (int)x; | ||
| 453 | return STRSCAN_INT; | ||
| 454 | } | ||
| 455 | } | ||
| 456 | |||
| 457 | /* Dispatch to base-specific parser. */ | ||
| 458 | if (base == 0 && !(fmt == STRSCAN_NUM || fmt == STRSCAN_IMAG)) | ||
| 459 | return strscan_oct(sp, o, fmt, neg, dig); | ||
| 460 | if (base == 16) | ||
| 461 | fmt = strscan_hex(sp, o, fmt, opt, ex, neg, dig); | ||
| 462 | else | ||
| 463 | fmt = strscan_dec(sp, o, fmt, opt, ex, neg, dig); | ||
| 464 | |||
| 465 | /* Try to convert number to integer, if requested. */ | ||
| 466 | if (fmt == STRSCAN_NUM && (opt & STRSCAN_OPT_TOINT)) { | ||
| 467 | double n = o->n; | ||
| 468 | int32_t i = lj_num2int(n); | ||
| 469 | if (n == (lua_Number)i) { o->i = i; return STRSCAN_INT; } | ||
| 470 | } | ||
| 471 | return fmt; | ||
| 472 | } | ||
| 473 | } | ||
| 474 | |||
| 475 | int LJ_FASTCALL lj_strscan_num(GCstr *str, TValue *o) | ||
| 476 | { | ||
| 477 | StrScanFmt fmt = lj_strscan_scan((const uint8_t *)strdata(str), o, | ||
| 478 | STRSCAN_OPT_TONUM); | ||
| 479 | lua_assert(fmt == STRSCAN_ERROR || fmt == STRSCAN_NUM); | ||
| 480 | return (fmt != STRSCAN_ERROR); | ||
| 481 | } | ||
| 482 | |||
| 483 | #if LJ_DUALNUM | ||
| 484 | int LJ_FASTCALL lj_strscan_number(GCstr *str, TValue *o) | ||
| 485 | { | ||
| 486 | StrScanFmt fmt = lj_strscan_scan((const uint8_t *)strdata(str), o, | ||
| 487 | STRSCAN_OPT_TOINT); | ||
| 488 | lua_assert(fmt == STRSCAN_ERROR || fmt == STRSCAN_NUM || fmt == STRSCAN_INT); | ||
| 489 | if (fmt == STRSCAN_INT) setitype(o, LJ_TISNUM); | ||
| 490 | return (fmt != STRSCAN_ERROR); | ||
| 491 | } | ||
| 492 | #endif | ||
| 493 | |||
| 494 | #undef DNEXT | ||
| 495 | #undef DPREV | ||
| 496 | #undef DLEN | ||
| 497 | |||
diff --git a/src/lj_strscan.h b/src/lj_strscan.h new file mode 100644 index 00000000..da5bd095 --- /dev/null +++ b/src/lj_strscan.h | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | /* | ||
| 2 | ** String scanning. | ||
| 3 | ** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef _LJ_STRSCAN_H | ||
| 7 | #define _LJ_STRSCAN_H | ||
| 8 | |||
| 9 | #include "lj_obj.h" | ||
| 10 | |||
| 11 | /* Options for accepted/returned formats. */ | ||
| 12 | #define STRSCAN_OPT_TOINT 0x01 /* Convert to int32_t, if possible. */ | ||
| 13 | #define STRSCAN_OPT_TONUM 0x02 /* Always convert to double. */ | ||
| 14 | #define STRSCAN_OPT_IMAG 0x04 | ||
| 15 | #define STRSCAN_OPT_LL 0x08 | ||
| 16 | #define STRSCAN_OPT_C 0x10 | ||
| 17 | |||
| 18 | /* Returned format. */ | ||
| 19 | typedef enum { | ||
| 20 | STRSCAN_ERROR, | ||
| 21 | STRSCAN_NUM, STRSCAN_IMAG, | ||
| 22 | STRSCAN_INT, STRSCAN_U32, STRSCAN_I64, STRSCAN_U64, | ||
| 23 | } StrScanFmt; | ||
| 24 | |||
| 25 | LJ_FUNC StrScanFmt lj_strscan_scan(const uint8_t *p, TValue *o, uint32_t opt); | ||
| 26 | LJ_FUNC int LJ_FASTCALL lj_strscan_num(GCstr *str, TValue *o); | ||
| 27 | #if LJ_DUALNUM | ||
| 28 | LJ_FUNC int LJ_FASTCALL lj_strscan_number(GCstr *str, TValue *o); | ||
| 29 | #else | ||
| 30 | #define lj_strscan_number(s, o) lj_strscan_num((s), (o)) | ||
| 31 | #endif | ||
| 32 | |||
| 33 | /* Check for number or convert string to number/int in-place (!). */ | ||
| 34 | static LJ_AINLINE int lj_strscan_numberobj(TValue *o) | ||
| 35 | { | ||
| 36 | return tvisnumber(o) || (tvisstr(o) && lj_strscan_number(strV(o), o)); | ||
| 37 | } | ||
| 38 | |||
| 39 | #endif | ||
diff --git a/src/ljamalg.c b/src/ljamalg.c index b1124464..a64c9429 100644 --- a/src/ljamalg.c +++ b/src/ljamalg.c | |||
| @@ -43,6 +43,7 @@ | |||
| 43 | #include "lj_dispatch.c" | 43 | #include "lj_dispatch.c" |
| 44 | #include "lj_vmevent.c" | 44 | #include "lj_vmevent.c" |
| 45 | #include "lj_vmmath.c" | 45 | #include "lj_vmmath.c" |
| 46 | #include "lj_strscan.c" | ||
| 46 | #include "lj_api.c" | 47 | #include "lj_api.c" |
| 47 | #include "lj_lex.c" | 48 | #include "lj_lex.c" |
| 48 | #include "lj_parse.c" | 49 | #include "lj_parse.c" |
diff --git a/src/luaconf.h b/src/luaconf.h index dfb79e19..5c29d4f3 100644 --- a/src/luaconf.h +++ b/src/luaconf.h | |||
| @@ -98,7 +98,6 @@ | |||
| 98 | #define LUA_NUMBER_FMT "%.14g" | 98 | #define LUA_NUMBER_FMT "%.14g" |
| 99 | #define lua_number2str(s, n) sprintf((s), LUA_NUMBER_FMT, (n)) | 99 | #define lua_number2str(s, n) sprintf((s), LUA_NUMBER_FMT, (n)) |
| 100 | #define LUAI_MAXNUMBER2STR 32 | 100 | #define LUAI_MAXNUMBER2STR 32 |
| 101 | #define lua_str2number(s, p) strtod((s), (p)) | ||
| 102 | #define LUA_INTFRMLEN "l" | 101 | #define LUA_INTFRMLEN "l" |
| 103 | #define LUA_INTFRM_T long | 102 | #define LUA_INTFRM_T long |
| 104 | 103 | ||
