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 | ||