aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2012-08-25 23:02:29 +0200
committerMike Pall <mike>2012-08-25 23:02:29 +0200
commit4c882fe71406a923f07c8e9a0b9189036e0ba386 (patch)
tree22aa3995b5bdc2fce05ba17488799e67abc635ba /src
parent653facd0d5c1a4f7eae43eefbf8148f57e28e606 (diff)
downloadluajit-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/Makefile4
-rw-r--r--src/Makefile.dep56
-rw-r--r--src/lib_base.c3
-rw-r--r--src/lj_api.c15
-rw-r--r--src/lj_asm_arm.h2
-rw-r--r--src/lj_asm_mips.h2
-rw-r--r--src/lj_asm_ppc.h2
-rw-r--r--src/lj_asm_x86.h2
-rw-r--r--src/lj_char.h2
-rw-r--r--src/lj_cparse.c67
-rw-r--r--src/lj_ffrecord.c5
-rw-r--r--src/lj_ir.c1
-rw-r--r--src/lj_ircall.h2
-rw-r--r--src/lj_lex.c110
-rw-r--r--src/lj_lib.c12
-rw-r--r--src/lj_meta.c12
-rw-r--r--src/lj_opt_fold.c3
-rw-r--r--src/lj_opt_narrow.c12
-rw-r--r--src/lj_str.c79
-rw-r--r--src/lj_str.h3
-rw-r--r--src/lj_strscan.c497
-rw-r--r--src/lj_strscan.h39
-rw-r--r--src/ljamalg.c1
-rw-r--r--src/luaconf.h1
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
447LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o \ 447LJCORE_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 \
3lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ 3lib_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
7lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ 8lib_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
9lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ 10lib_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
39lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 40lj_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
43lj_asm.o: lj_asm.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 45lj_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
78lj_cparse.o: lj_cparse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 80lj_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
81lj_crecord.o: lj_crecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 83lj_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
105lj_func.o: lj_func.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 107lj_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 \
115lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 117lj_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
119lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 121lj_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
122lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \ 124lj_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
125lj_mcode.o: lj_mcode.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 127lj_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
128lj_meta.o: lj_meta.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 130lj_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
131lj_obj.o: lj_obj.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h 133lj_obj.o: lj_obj.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h
132lj_opt_dce.o: lj_opt_dce.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 134lj_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
134lj_opt_fold.o: lj_opt_fold.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 136lj_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
138lj_opt_loop.o: lj_opt_loop.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 140lj_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
141lj_opt_mem.o: lj_opt_mem.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 143lj_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
143lj_opt_narrow.o: lj_opt_narrow.c lj_obj.h lua.h luaconf.h lj_def.h \ 145lj_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
146lj_opt_sink.o: lj_opt_sink.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 148lj_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
148lj_opt_split.o: lj_opt_split.c lj_obj.h lua.h luaconf.h lj_def.h \ 150lj_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
166lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 168lj_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
170lj_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
168lj_tab.o: lj_tab.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 172lj_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
170lj_trace.o: lj_trace.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 174lj_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
202luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h 206luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h
203host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \ 207host/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
242LUA_API int lua_isstring(lua_State *L, int idx) 243LUA_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
627static void asm_strto(ASMState *as, IRIns *ir) 627static 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
542static void asm_strto(ASMState *as, IRIns *ir) 542static 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
534static void asm_strto(ASMState *as, IRIns *ir) 534static 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)
882static void asm_strto(ASMState *as, IRIns *ir) 882static 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. */
160static CPToken cp_integer(CPState *cp) 161static 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. */
65static int32_t argv2int(jit_State *J, TValue *o) 66static 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. */
28static const char *const tokennames[] = { 29static 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. */
89static 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. */
97static 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. */
138static void lex_number(LexState *ls, TValue *tv) 89static 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
183static int skip_sep(LexState *ls) 135static 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)
155void lj_lib_checknumber(lua_State *L, int narg) 156void 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)
179int32_t lj_lib_checkint(lua_State *L, int narg) 179int32_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)
200int32_t lj_lib_checkbit(lua_State *L, int narg) 199int32_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. */
437void LJ_FASTCALL lj_meta_for(lua_State *L, TValue *o) 438void 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)
693LJFOLDF(kfold_strto) 694LJFOLDF(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)
555TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vc) 555TRef 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. */
576TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vc) 576TRef 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. */
173int 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
181int 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. */
187int 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 }
233parsedbl:
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. */
252size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o) 173size_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. */
23LJ_FUNC int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n);
24LJ_FUNC int LJ_FASTCALL lj_str_tonum(GCstr *str, TValue *n);
25LJ_FUNC int LJ_FASTCALL lj_str_tonumber(GCstr *str, TValue *n);
26LJ_FUNC size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o); 23LJ_FUNC size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o);
27LJ_FUNC char * LJ_FASTCALL lj_str_bufint(char *p, int32_t k); 24LJ_FUNC char * LJ_FASTCALL lj_str_bufint(char *p, int32_t k);
28LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np); 25LJ_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. */
75static 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. */
104static 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. */
150static 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. */
181static 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. */
328StrScanFmt 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
475int 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
484int 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. */
19typedef enum {
20 STRSCAN_ERROR,
21 STRSCAN_NUM, STRSCAN_IMAG,
22 STRSCAN_INT, STRSCAN_U32, STRSCAN_I64, STRSCAN_U64,
23} StrScanFmt;
24
25LJ_FUNC StrScanFmt lj_strscan_scan(const uint8_t *p, TValue *o, uint32_t opt);
26LJ_FUNC int LJ_FASTCALL lj_strscan_num(GCstr *str, TValue *o);
27#if LJ_DUALNUM
28LJ_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 (!). */
34static 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