immunio 0.15.4 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE +0 -27
- data/ext/immunio/Rakefile +9 -0
- data/lib/immunio/plugins/active_record.rb +1 -1
- data/lib/immunio/plugins/active_record_relation.rb +1 -1
- data/lib/immunio/plugins/environment_reporter.rb +20 -0
- data/lib/immunio/rufus_lua_ext/ref.rb +1 -3
- data/lib/immunio/version.rb +1 -1
- data/lib/immunio/vm.rb +1 -2
- data/lua-hooks/Makefile +97 -0
- data/lua-hooks/ext/all.c +41 -52
- data/lua-hooks/ext/all.o +0 -0
- data/lua-hooks/ext/libinjection/libinjection_html5.o +0 -0
- data/lua-hooks/ext/libinjection/libinjection_sqli.o +0 -0
- data/lua-hooks/ext/libinjection/libinjection_xss.o +0 -0
- data/lua-hooks/ext/libinjection/lualib.c +2 -2
- data/lua-hooks/ext/lpeg/lpcap.c +2 -2
- data/lua-hooks/ext/lpeg/lpcap.o +0 -0
- data/lua-hooks/ext/lpeg/lpcode.c +2 -2
- data/lua-hooks/ext/lpeg/lpcode.h +1 -1
- data/lua-hooks/ext/lpeg/lpcode.o +0 -0
- data/lua-hooks/ext/lpeg/lpprint.o +0 -0
- data/lua-hooks/ext/lpeg/lptree.c +2 -2
- data/lua-hooks/ext/lpeg/lptypes.h +1 -1
- data/lua-hooks/ext/lpeg/lpvm.c +2 -2
- data/lua-hooks/ext/lpeg/lpvm.o +0 -0
- data/lua-hooks/ext/lua-cmsgpack/lua_cmsgpack.c +16 -3
- data/lua-hooks/ext/lua-snapshot/snapshot.c +14 -7
- data/lua-hooks/ext/luajit/COPYRIGHT +56 -0
- data/lua-hooks/ext/luajit/Makefile +159 -0
- data/lua-hooks/ext/luajit/README +16 -0
- data/lua-hooks/ext/luajit/doc/bluequad-print.css +166 -0
- data/lua-hooks/ext/luajit/doc/bluequad.css +325 -0
- data/lua-hooks/ext/luajit/doc/changes.html +804 -0
- data/lua-hooks/ext/luajit/doc/contact.html +104 -0
- data/lua-hooks/ext/luajit/doc/ext_c_api.html +189 -0
- data/lua-hooks/ext/luajit/doc/ext_ffi.html +332 -0
- data/lua-hooks/ext/luajit/doc/ext_ffi_api.html +570 -0
- data/lua-hooks/ext/luajit/doc/ext_ffi_semantics.html +1261 -0
- data/lua-hooks/ext/luajit/doc/ext_ffi_tutorial.html +603 -0
- data/lua-hooks/ext/luajit/doc/ext_jit.html +201 -0
- data/lua-hooks/ext/luajit/doc/ext_profiler.html +365 -0
- data/lua-hooks/ext/luajit/doc/extensions.html +448 -0
- data/lua-hooks/ext/luajit/doc/faq.html +186 -0
- data/lua-hooks/ext/luajit/doc/img/contact.png +0 -0
- data/lua-hooks/ext/luajit/doc/install.html +659 -0
- data/lua-hooks/ext/luajit/doc/luajit.html +236 -0
- data/lua-hooks/ext/luajit/doc/running.html +309 -0
- data/lua-hooks/ext/luajit/doc/status.html +118 -0
- data/lua-hooks/ext/luajit/dynasm/dasm_arm.h +456 -0
- data/lua-hooks/ext/luajit/dynasm/dasm_arm.lua +1125 -0
- data/lua-hooks/ext/luajit/dynasm/dasm_arm64.h +518 -0
- data/lua-hooks/ext/luajit/dynasm/dasm_arm64.lua +1166 -0
- data/lua-hooks/ext/luajit/dynasm/dasm_mips.h +416 -0
- data/lua-hooks/ext/luajit/dynasm/dasm_mips.lua +953 -0
- data/lua-hooks/ext/luajit/dynasm/dasm_ppc.h +419 -0
- data/lua-hooks/ext/luajit/dynasm/dasm_ppc.lua +1919 -0
- data/lua-hooks/ext/luajit/dynasm/dasm_proto.h +83 -0
- data/lua-hooks/ext/luajit/dynasm/dasm_x64.lua +12 -0
- data/lua-hooks/ext/luajit/dynasm/dasm_x86.h +471 -0
- data/lua-hooks/ext/luajit/dynasm/dasm_x86.lua +1945 -0
- data/lua-hooks/ext/luajit/dynasm/dynasm.lua +1094 -0
- data/lua-hooks/ext/luajit/etc/luajit.1 +88 -0
- data/lua-hooks/ext/luajit/etc/luajit.pc +25 -0
- data/lua-hooks/ext/luajit/src/Makefile +697 -0
- data/lua-hooks/ext/luajit/src/Makefile.dep +244 -0
- data/lua-hooks/ext/luajit/src/host/README +4 -0
- data/lua-hooks/ext/luajit/src/host/buildvm +0 -0
- data/lua-hooks/ext/luajit/src/host/buildvm.c +518 -0
- data/lua-hooks/ext/luajit/src/host/buildvm.h +105 -0
- data/lua-hooks/ext/luajit/src/host/buildvm.o +0 -0
- data/lua-hooks/ext/luajit/src/host/buildvm_arch.h +7449 -0
- data/lua-hooks/ext/luajit/src/host/buildvm_asm.c +345 -0
- data/lua-hooks/ext/luajit/src/host/buildvm_asm.o +0 -0
- data/lua-hooks/ext/luajit/src/host/buildvm_fold.c +229 -0
- data/lua-hooks/ext/luajit/src/host/buildvm_fold.o +0 -0
- data/lua-hooks/ext/luajit/src/host/buildvm_lib.c +457 -0
- data/lua-hooks/ext/luajit/src/host/buildvm_lib.o +0 -0
- data/lua-hooks/ext/luajit/src/host/buildvm_libbc.h +45 -0
- data/lua-hooks/ext/luajit/src/host/buildvm_peobj.c +368 -0
- data/lua-hooks/ext/luajit/src/host/buildvm_peobj.o +0 -0
- data/lua-hooks/ext/luajit/src/host/genlibbc.lua +197 -0
- data/lua-hooks/ext/luajit/src/host/genminilua.lua +428 -0
- data/lua-hooks/ext/luajit/src/host/minilua +0 -0
- data/lua-hooks/ext/luajit/src/host/minilua.c +7770 -0
- data/lua-hooks/ext/luajit/src/host/minilua.o +0 -0
- data/lua-hooks/ext/luajit/src/jit/bc.lua +190 -0
- data/lua-hooks/ext/luajit/src/jit/bcsave.lua +661 -0
- data/lua-hooks/ext/luajit/src/jit/dis_arm.lua +689 -0
- data/lua-hooks/ext/luajit/src/jit/dis_mips.lua +428 -0
- data/lua-hooks/ext/luajit/src/jit/dis_mipsel.lua +17 -0
- data/lua-hooks/ext/luajit/src/jit/dis_ppc.lua +591 -0
- data/lua-hooks/ext/luajit/src/jit/dis_x64.lua +17 -0
- data/lua-hooks/ext/luajit/src/jit/dis_x86.lua +838 -0
- data/lua-hooks/ext/luajit/src/jit/dump.lua +706 -0
- data/lua-hooks/ext/luajit/src/jit/p.lua +310 -0
- data/lua-hooks/ext/luajit/src/jit/v.lua +170 -0
- data/lua-hooks/ext/luajit/src/jit/vmdef.lua +362 -0
- data/lua-hooks/ext/luajit/src/jit/zone.lua +45 -0
- data/lua-hooks/ext/{lua → luajit/src}/lauxlib.h +10 -17
- data/lua-hooks/ext/luajit/src/lib_aux.c +356 -0
- data/lua-hooks/ext/luajit/src/lib_aux.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_aux_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_base.c +664 -0
- data/lua-hooks/ext/luajit/src/lib_base.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_base_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_bit.c +180 -0
- data/lua-hooks/ext/luajit/src/lib_bit.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_bit_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_debug.c +405 -0
- data/lua-hooks/ext/luajit/src/lib_debug.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_debug_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_ffi.c +872 -0
- data/lua-hooks/ext/luajit/src/lib_ffi.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_ffi_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_init.c +55 -0
- data/lua-hooks/ext/luajit/src/lib_init.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_init_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_io.c +541 -0
- data/lua-hooks/ext/luajit/src/lib_io.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_io_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_jit.c +767 -0
- data/lua-hooks/ext/luajit/src/lib_jit.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_jit_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_math.c +230 -0
- data/lua-hooks/ext/luajit/src/lib_math.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_math_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_os.c +292 -0
- data/lua-hooks/ext/luajit/src/lib_os.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_os_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_package.c +610 -0
- data/lua-hooks/ext/luajit/src/lib_package.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_package_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_string.c +752 -0
- data/lua-hooks/ext/luajit/src/lib_string.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_string_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_table.c +307 -0
- data/lua-hooks/ext/luajit/src/lib_table.o +0 -0
- data/lua-hooks/ext/luajit/src/lib_table_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/libluajit.a +0 -0
- data/lua-hooks/ext/luajit/src/libluajit.so +0 -0
- data/lua-hooks/ext/luajit/src/lj.supp +26 -0
- data/lua-hooks/ext/luajit/src/lj_alloc.c +1398 -0
- data/lua-hooks/ext/luajit/src/lj_alloc.h +17 -0
- data/lua-hooks/ext/luajit/src/lj_alloc.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_alloc_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_api.c +1210 -0
- data/lua-hooks/ext/luajit/src/lj_api.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_api_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_arch.h +509 -0
- data/lua-hooks/ext/luajit/src/lj_asm.c +2278 -0
- data/lua-hooks/ext/luajit/src/lj_asm.h +17 -0
- data/lua-hooks/ext/luajit/src/lj_asm.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_asm_arm.h +2217 -0
- data/lua-hooks/ext/luajit/src/lj_asm_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_asm_mips.h +1833 -0
- data/lua-hooks/ext/luajit/src/lj_asm_ppc.h +2015 -0
- data/lua-hooks/ext/luajit/src/lj_asm_x86.h +2634 -0
- data/lua-hooks/ext/luajit/src/lj_bc.c +14 -0
- data/lua-hooks/ext/luajit/src/lj_bc.h +265 -0
- data/lua-hooks/ext/luajit/src/lj_bc.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_bc_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_bcdef.h +220 -0
- data/lua-hooks/ext/luajit/src/lj_bcdump.h +68 -0
- data/lua-hooks/ext/luajit/src/lj_bcread.c +457 -0
- data/lua-hooks/ext/luajit/src/lj_bcread.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_bcread_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_bcwrite.c +361 -0
- data/lua-hooks/ext/luajit/src/lj_bcwrite.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_bcwrite_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_buf.c +234 -0
- data/lua-hooks/ext/luajit/src/lj_buf.h +105 -0
- data/lua-hooks/ext/luajit/src/lj_buf.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_buf_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_carith.c +429 -0
- data/lua-hooks/ext/luajit/src/lj_carith.h +37 -0
- data/lua-hooks/ext/luajit/src/lj_carith.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_carith_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_ccall.c +984 -0
- data/lua-hooks/ext/luajit/src/lj_ccall.h +178 -0
- data/lua-hooks/ext/luajit/src/lj_ccall.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_ccall_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_ccallback.c +712 -0
- data/lua-hooks/ext/luajit/src/lj_ccallback.h +25 -0
- data/lua-hooks/ext/luajit/src/lj_ccallback.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_ccallback_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_cconv.c +752 -0
- data/lua-hooks/ext/luajit/src/lj_cconv.h +70 -0
- data/lua-hooks/ext/luajit/src/lj_cconv.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_cconv_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_cdata.c +288 -0
- data/lua-hooks/ext/luajit/src/lj_cdata.h +76 -0
- data/lua-hooks/ext/luajit/src/lj_cdata.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_cdata_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_char.c +43 -0
- data/lua-hooks/ext/luajit/src/lj_char.h +42 -0
- data/lua-hooks/ext/luajit/src/lj_char.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_char_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_clib.c +418 -0
- data/lua-hooks/ext/luajit/src/lj_clib.h +29 -0
- data/lua-hooks/ext/luajit/src/lj_clib.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_clib_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_cparse.c +1862 -0
- data/lua-hooks/ext/luajit/src/lj_cparse.h +65 -0
- data/lua-hooks/ext/luajit/src/lj_cparse.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_cparse_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_crecord.c +1834 -0
- data/lua-hooks/ext/luajit/src/lj_crecord.h +38 -0
- data/lua-hooks/ext/luajit/src/lj_crecord.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_crecord_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_ctype.c +635 -0
- data/lua-hooks/ext/luajit/src/lj_ctype.h +461 -0
- data/lua-hooks/ext/luajit/src/lj_ctype.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_ctype_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_debug.c +699 -0
- data/lua-hooks/ext/luajit/src/lj_debug.h +65 -0
- data/lua-hooks/ext/luajit/src/lj_debug.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_debug_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_def.h +365 -0
- data/lua-hooks/ext/luajit/src/lj_dispatch.c +557 -0
- data/lua-hooks/ext/luajit/src/lj_dispatch.h +138 -0
- data/lua-hooks/ext/luajit/src/lj_dispatch.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_dispatch_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_emit_arm.h +356 -0
- data/lua-hooks/ext/luajit/src/lj_emit_mips.h +211 -0
- data/lua-hooks/ext/luajit/src/lj_emit_ppc.h +238 -0
- data/lua-hooks/ext/luajit/src/lj_emit_x86.h +462 -0
- data/lua-hooks/ext/luajit/src/lj_err.c +794 -0
- data/lua-hooks/ext/luajit/src/lj_err.h +41 -0
- data/lua-hooks/ext/luajit/src/lj_err.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_err_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_errmsg.h +190 -0
- data/lua-hooks/ext/luajit/src/lj_ff.h +18 -0
- data/lua-hooks/ext/luajit/src/lj_ffdef.h +209 -0
- data/lua-hooks/ext/luajit/src/lj_ffrecord.c +1247 -0
- data/lua-hooks/ext/luajit/src/lj_ffrecord.h +24 -0
- data/lua-hooks/ext/luajit/src/lj_ffrecord.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_ffrecord_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_folddef.h +1138 -0
- data/lua-hooks/ext/luajit/src/lj_frame.h +259 -0
- data/lua-hooks/ext/luajit/src/lj_func.c +185 -0
- data/lua-hooks/ext/luajit/src/lj_func.h +24 -0
- data/lua-hooks/ext/luajit/src/lj_func.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_func_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_gc.c +845 -0
- data/lua-hooks/ext/luajit/src/lj_gc.h +134 -0
- data/lua-hooks/ext/luajit/src/lj_gc.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_gc_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_gdbjit.c +787 -0
- data/lua-hooks/ext/luajit/src/lj_gdbjit.h +22 -0
- data/lua-hooks/ext/luajit/src/lj_gdbjit.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_gdbjit_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_ir.c +505 -0
- data/lua-hooks/ext/luajit/src/lj_ir.h +577 -0
- data/lua-hooks/ext/luajit/src/lj_ir.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_ir_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_ircall.h +321 -0
- data/lua-hooks/ext/luajit/src/lj_iropt.h +161 -0
- data/lua-hooks/ext/luajit/src/lj_jit.h +440 -0
- data/lua-hooks/ext/luajit/src/lj_lex.c +482 -0
- data/lua-hooks/ext/luajit/src/lj_lex.h +86 -0
- data/lua-hooks/ext/luajit/src/lj_lex.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_lex_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_lib.c +303 -0
- data/lua-hooks/ext/luajit/src/lj_lib.h +115 -0
- data/lua-hooks/ext/luajit/src/lj_lib.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_lib_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_libdef.h +414 -0
- data/lua-hooks/ext/luajit/src/lj_load.c +168 -0
- data/lua-hooks/ext/luajit/src/lj_load.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_load_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_mcode.c +386 -0
- data/lua-hooks/ext/luajit/src/lj_mcode.h +30 -0
- data/lua-hooks/ext/luajit/src/lj_mcode.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_mcode_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_meta.c +477 -0
- data/lua-hooks/ext/luajit/src/lj_meta.h +38 -0
- data/lua-hooks/ext/luajit/src/lj_meta.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_meta_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_obj.c +50 -0
- data/lua-hooks/ext/luajit/src/lj_obj.h +976 -0
- data/lua-hooks/ext/luajit/src/lj_obj.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_obj_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_opt_dce.c +78 -0
- data/lua-hooks/ext/luajit/src/lj_opt_dce.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_opt_dce_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_opt_fold.c +2488 -0
- data/lua-hooks/ext/luajit/src/lj_opt_fold.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_opt_fold_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_opt_loop.c +449 -0
- data/lua-hooks/ext/luajit/src/lj_opt_loop.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_opt_loop_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_opt_mem.c +935 -0
- data/lua-hooks/ext/luajit/src/lj_opt_mem.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_opt_mem_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_opt_narrow.c +652 -0
- data/lua-hooks/ext/luajit/src/lj_opt_narrow.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_opt_narrow_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_opt_sink.c +245 -0
- data/lua-hooks/ext/luajit/src/lj_opt_sink.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_opt_sink_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_opt_split.c +856 -0
- data/lua-hooks/ext/luajit/src/lj_opt_split.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_opt_split_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_parse.c +2725 -0
- data/lua-hooks/ext/luajit/src/lj_parse.h +18 -0
- data/lua-hooks/ext/luajit/src/lj_parse.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_parse_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_profile.c +368 -0
- data/lua-hooks/ext/luajit/src/lj_profile.h +21 -0
- data/lua-hooks/ext/luajit/src/lj_profile.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_profile_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_recdef.h +270 -0
- data/lua-hooks/ext/luajit/src/lj_record.c +2554 -0
- data/lua-hooks/ext/luajit/src/lj_record.h +45 -0
- data/lua-hooks/ext/luajit/src/lj_record.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_record_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_snap.c +870 -0
- data/lua-hooks/ext/luajit/src/lj_snap.h +34 -0
- data/lua-hooks/ext/luajit/src/lj_snap.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_snap_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_state.c +300 -0
- data/lua-hooks/ext/luajit/src/lj_state.h +35 -0
- data/lua-hooks/ext/luajit/src/lj_state.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_state_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_str.c +197 -0
- data/lua-hooks/ext/luajit/src/lj_str.h +27 -0
- data/lua-hooks/ext/luajit/src/lj_str.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_str_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_strfmt.c +554 -0
- data/lua-hooks/ext/luajit/src/lj_strfmt.h +125 -0
- data/lua-hooks/ext/luajit/src/lj_strfmt.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_strfmt_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_strscan.c +547 -0
- data/lua-hooks/ext/luajit/src/lj_strscan.h +39 -0
- data/lua-hooks/ext/luajit/src/lj_strscan.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_strscan_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_tab.c +666 -0
- data/lua-hooks/ext/luajit/src/lj_tab.h +73 -0
- data/lua-hooks/ext/luajit/src/lj_tab.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_tab_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_target.h +164 -0
- data/lua-hooks/ext/luajit/src/lj_target_arm.h +270 -0
- data/lua-hooks/ext/luajit/src/lj_target_arm64.h +97 -0
- data/lua-hooks/ext/luajit/src/lj_target_mips.h +260 -0
- data/lua-hooks/ext/luajit/src/lj_target_ppc.h +280 -0
- data/lua-hooks/ext/luajit/src/lj_target_x86.h +345 -0
- data/lua-hooks/ext/luajit/src/lj_trace.c +859 -0
- data/lua-hooks/ext/luajit/src/lj_trace.h +54 -0
- data/lua-hooks/ext/luajit/src/lj_trace.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_trace_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_traceerr.h +63 -0
- data/lua-hooks/ext/luajit/src/lj_udata.c +34 -0
- data/lua-hooks/ext/luajit/src/lj_udata.h +14 -0
- data/lua-hooks/ext/luajit/src/lj_udata.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_udata_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_vm.S +2730 -0
- data/lua-hooks/ext/luajit/src/lj_vm.h +114 -0
- data/lua-hooks/ext/luajit/src/lj_vm.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_vm_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_vmevent.c +58 -0
- data/lua-hooks/ext/luajit/src/lj_vmevent.h +59 -0
- data/lua-hooks/ext/luajit/src/lj_vmevent.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_vmevent_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_vmmath.c +152 -0
- data/lua-hooks/ext/luajit/src/lj_vmmath.o +0 -0
- data/lua-hooks/ext/luajit/src/lj_vmmath_dyn.o +0 -0
- data/lua-hooks/ext/luajit/src/ljamalg.c +96 -0
- data/lua-hooks/ext/{lua → luajit/src}/lua.h +12 -7
- data/lua-hooks/ext/luajit/src/lua.hpp +9 -0
- data/lua-hooks/ext/luajit/src/luaconf.h +156 -0
- data/lua-hooks/ext/luajit/src/luajit +0 -0
- data/lua-hooks/ext/luajit/src/luajit.c +570 -0
- data/lua-hooks/ext/luajit/src/luajit.h +79 -0
- data/lua-hooks/ext/luajit/src/luajit.o +0 -0
- data/lua-hooks/ext/luajit/src/lualib.h +43 -0
- data/lua-hooks/ext/luajit/src/msvcbuild.bat +114 -0
- data/lua-hooks/ext/luajit/src/ps4build.bat +103 -0
- data/lua-hooks/ext/luajit/src/psvitabuild.bat +93 -0
- data/lua-hooks/ext/luajit/src/vm_arm.dasc +4585 -0
- data/lua-hooks/ext/luajit/src/vm_arm64.dasc +3764 -0
- data/lua-hooks/ext/luajit/src/vm_mips.dasc +4355 -0
- data/lua-hooks/ext/luajit/src/vm_ppc.dasc +5252 -0
- data/lua-hooks/ext/luajit/src/vm_x64.dasc +4902 -0
- data/lua-hooks/ext/luajit/src/vm_x86.dasc +5710 -0
- data/lua-hooks/ext/luajit/src/xb1build.bat +101 -0
- data/lua-hooks/ext/luajit/src/xedkbuild.bat +92 -0
- data/lua-hooks/ext/luautf8/lutf8lib.c +3 -3
- data/lua-hooks/lib/boot.lua +37 -2
- metadata +372 -69
- data/lua-hooks/ext/bitop/README +0 -22
- data/lua-hooks/ext/bitop/bit.c +0 -189
- data/lua-hooks/ext/extconf.rb +0 -38
- data/lua-hooks/ext/lua/COPYRIGHT +0 -34
- data/lua-hooks/ext/lua/lapi.c +0 -1087
- data/lua-hooks/ext/lua/lapi.h +0 -16
- data/lua-hooks/ext/lua/lauxlib.c +0 -652
- data/lua-hooks/ext/lua/lbaselib.c +0 -659
- data/lua-hooks/ext/lua/lcode.c +0 -831
- data/lua-hooks/ext/lua/lcode.h +0 -76
- data/lua-hooks/ext/lua/ldblib.c +0 -398
- data/lua-hooks/ext/lua/ldebug.c +0 -638
- data/lua-hooks/ext/lua/ldebug.h +0 -33
- data/lua-hooks/ext/lua/ldo.c +0 -519
- data/lua-hooks/ext/lua/ldo.h +0 -57
- data/lua-hooks/ext/lua/ldump.c +0 -164
- data/lua-hooks/ext/lua/lfunc.c +0 -174
- data/lua-hooks/ext/lua/lfunc.h +0 -34
- data/lua-hooks/ext/lua/lgc.c +0 -710
- data/lua-hooks/ext/lua/lgc.h +0 -110
- data/lua-hooks/ext/lua/linit.c +0 -38
- data/lua-hooks/ext/lua/liolib.c +0 -556
- data/lua-hooks/ext/lua/llex.c +0 -463
- data/lua-hooks/ext/lua/llex.h +0 -81
- data/lua-hooks/ext/lua/llimits.h +0 -128
- data/lua-hooks/ext/lua/lmathlib.c +0 -263
- data/lua-hooks/ext/lua/lmem.c +0 -86
- data/lua-hooks/ext/lua/lmem.h +0 -49
- data/lua-hooks/ext/lua/loadlib.c +0 -705
- data/lua-hooks/ext/lua/loadlib_rel.c +0 -760
- data/lua-hooks/ext/lua/lobject.c +0 -214
- data/lua-hooks/ext/lua/lobject.h +0 -381
- data/lua-hooks/ext/lua/lopcodes.c +0 -102
- data/lua-hooks/ext/lua/lopcodes.h +0 -268
- data/lua-hooks/ext/lua/loslib.c +0 -243
- data/lua-hooks/ext/lua/lparser.c +0 -1339
- data/lua-hooks/ext/lua/lparser.h +0 -82
- data/lua-hooks/ext/lua/lstate.c +0 -214
- data/lua-hooks/ext/lua/lstate.h +0 -169
- data/lua-hooks/ext/lua/lstring.c +0 -111
- data/lua-hooks/ext/lua/lstring.h +0 -31
- data/lua-hooks/ext/lua/lstrlib.c +0 -871
- data/lua-hooks/ext/lua/ltable.c +0 -588
- data/lua-hooks/ext/lua/ltable.h +0 -40
- data/lua-hooks/ext/lua/ltablib.c +0 -287
- data/lua-hooks/ext/lua/ltm.c +0 -75
- data/lua-hooks/ext/lua/ltm.h +0 -54
- data/lua-hooks/ext/lua/lua.c +0 -392
- data/lua-hooks/ext/lua/lua.def +0 -131
- data/lua-hooks/ext/lua/lua.rc +0 -28
- data/lua-hooks/ext/lua/lua_dll.rc +0 -26
- data/lua-hooks/ext/lua/luac.c +0 -200
- data/lua-hooks/ext/lua/luac.rc +0 -1
- data/lua-hooks/ext/lua/luaconf.h +0 -763
- data/lua-hooks/ext/lua/luaconf.h.in +0 -724
- data/lua-hooks/ext/lua/luaconf.h.orig +0 -763
- data/lua-hooks/ext/lua/lualib.h +0 -53
- data/lua-hooks/ext/lua/lundump.c +0 -227
- data/lua-hooks/ext/lua/lundump.h +0 -36
- data/lua-hooks/ext/lua/lvm.c +0 -767
- data/lua-hooks/ext/lua/lvm.h +0 -36
- data/lua-hooks/ext/lua/lzio.c +0 -82
- data/lua-hooks/ext/lua/lzio.h +0 -67
- data/lua-hooks/ext/lua/print.c +0 -227
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
** FFI C library loader.
|
|
3
|
+
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#ifndef _LJ_CLIB_H
|
|
7
|
+
#define _LJ_CLIB_H
|
|
8
|
+
|
|
9
|
+
#include "lj_obj.h"
|
|
10
|
+
|
|
11
|
+
#if LJ_HASFFI
|
|
12
|
+
|
|
13
|
+
/* Namespace for C library indexing. */
|
|
14
|
+
#define CLNS_INDEX ((1u<<CT_FUNC)|(1u<<CT_EXTERN)|(1u<<CT_CONSTVAL))
|
|
15
|
+
|
|
16
|
+
/* C library namespace. */
|
|
17
|
+
typedef struct CLibrary {
|
|
18
|
+
void *handle; /* Opaque handle for dynamic library loader. */
|
|
19
|
+
GCtab *cache; /* Cache for resolved symbols. Anchored in ud->env. */
|
|
20
|
+
} CLibrary;
|
|
21
|
+
|
|
22
|
+
LJ_FUNC TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name);
|
|
23
|
+
LJ_FUNC void lj_clib_load(lua_State *L, GCtab *mt, GCstr *name, int global);
|
|
24
|
+
LJ_FUNC void lj_clib_unload(CLibrary *cl);
|
|
25
|
+
LJ_FUNC void lj_clib_default(lua_State *L, GCtab *mt);
|
|
26
|
+
|
|
27
|
+
#endif
|
|
28
|
+
|
|
29
|
+
#endif
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,1862 @@
|
|
|
1
|
+
/*
|
|
2
|
+
** C declaration parser.
|
|
3
|
+
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#include "lj_obj.h"
|
|
7
|
+
|
|
8
|
+
#if LJ_HASFFI
|
|
9
|
+
|
|
10
|
+
#include "lj_gc.h"
|
|
11
|
+
#include "lj_err.h"
|
|
12
|
+
#include "lj_buf.h"
|
|
13
|
+
#include "lj_ctype.h"
|
|
14
|
+
#include "lj_cparse.h"
|
|
15
|
+
#include "lj_frame.h"
|
|
16
|
+
#include "lj_vm.h"
|
|
17
|
+
#include "lj_char.h"
|
|
18
|
+
#include "lj_strscan.h"
|
|
19
|
+
#include "lj_strfmt.h"
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
** Important note: this is NOT a validating C parser! This is a minimal
|
|
23
|
+
** C declaration parser, solely for use by the LuaJIT FFI.
|
|
24
|
+
**
|
|
25
|
+
** It ought to return correct results for properly formed C declarations,
|
|
26
|
+
** but it may accept some invalid declarations, too (and return nonsense).
|
|
27
|
+
** Also, it shows rather generic error messages to avoid unnecessary bloat.
|
|
28
|
+
** If in doubt, please check the input against your favorite C compiler.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/* -- C lexer ------------------------------------------------------------- */
|
|
32
|
+
|
|
33
|
+
/* C lexer token names. */
|
|
34
|
+
static const char *const ctoknames[] = {
|
|
35
|
+
#define CTOKSTR(name, str) str,
|
|
36
|
+
CTOKDEF(CTOKSTR)
|
|
37
|
+
#undef CTOKSTR
|
|
38
|
+
NULL
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/* Forward declaration. */
|
|
42
|
+
LJ_NORET static void cp_err(CPState *cp, ErrMsg em);
|
|
43
|
+
|
|
44
|
+
static const char *cp_tok2str(CPState *cp, CPToken tok)
|
|
45
|
+
{
|
|
46
|
+
lua_assert(tok < CTOK_FIRSTDECL);
|
|
47
|
+
if (tok > CTOK_OFS)
|
|
48
|
+
return ctoknames[tok-CTOK_OFS-1];
|
|
49
|
+
else if (!lj_char_iscntrl(tok))
|
|
50
|
+
return lj_strfmt_pushf(cp->L, "%c", tok);
|
|
51
|
+
else
|
|
52
|
+
return lj_strfmt_pushf(cp->L, "char(%d)", tok);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* End-of-line? */
|
|
56
|
+
static LJ_AINLINE int cp_iseol(CPChar c)
|
|
57
|
+
{
|
|
58
|
+
return (c == '\n' || c == '\r');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* Peek next raw character. */
|
|
62
|
+
static LJ_AINLINE CPChar cp_rawpeek(CPState *cp)
|
|
63
|
+
{
|
|
64
|
+
return (CPChar)(uint8_t)(*cp->p);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static LJ_NOINLINE CPChar cp_get_bs(CPState *cp);
|
|
68
|
+
|
|
69
|
+
/* Get next character. */
|
|
70
|
+
static LJ_AINLINE CPChar cp_get(CPState *cp)
|
|
71
|
+
{
|
|
72
|
+
cp->c = (CPChar)(uint8_t)(*cp->p++);
|
|
73
|
+
if (LJ_LIKELY(cp->c != '\\')) return cp->c;
|
|
74
|
+
return cp_get_bs(cp);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Transparently skip backslash-escaped line breaks. */
|
|
78
|
+
static LJ_NOINLINE CPChar cp_get_bs(CPState *cp)
|
|
79
|
+
{
|
|
80
|
+
CPChar c2, c = cp_rawpeek(cp);
|
|
81
|
+
if (!cp_iseol(c)) return cp->c;
|
|
82
|
+
cp->p++;
|
|
83
|
+
c2 = cp_rawpeek(cp);
|
|
84
|
+
if (cp_iseol(c2) && c2 != c) cp->p++;
|
|
85
|
+
cp->linenumber++;
|
|
86
|
+
return cp_get(cp);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* Save character in buffer. */
|
|
90
|
+
static LJ_AINLINE void cp_save(CPState *cp, CPChar c)
|
|
91
|
+
{
|
|
92
|
+
lj_buf_putb(&cp->sb, c);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */
|
|
96
|
+
static void cp_newline(CPState *cp)
|
|
97
|
+
{
|
|
98
|
+
CPChar c = cp_rawpeek(cp);
|
|
99
|
+
if (cp_iseol(c) && c != cp->c) cp->p++;
|
|
100
|
+
cp->linenumber++;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
LJ_NORET static void cp_errmsg(CPState *cp, CPToken tok, ErrMsg em, ...)
|
|
104
|
+
{
|
|
105
|
+
const char *msg, *tokstr;
|
|
106
|
+
lua_State *L;
|
|
107
|
+
va_list argp;
|
|
108
|
+
if (tok == 0) {
|
|
109
|
+
tokstr = NULL;
|
|
110
|
+
} else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING ||
|
|
111
|
+
tok >= CTOK_FIRSTDECL) {
|
|
112
|
+
if (sbufP(&cp->sb) == sbufB(&cp->sb)) cp_save(cp, '$');
|
|
113
|
+
cp_save(cp, '\0');
|
|
114
|
+
tokstr = sbufB(&cp->sb);
|
|
115
|
+
} else {
|
|
116
|
+
tokstr = cp_tok2str(cp, tok);
|
|
117
|
+
}
|
|
118
|
+
L = cp->L;
|
|
119
|
+
va_start(argp, em);
|
|
120
|
+
msg = lj_strfmt_pushvf(L, err2msg(em), argp);
|
|
121
|
+
va_end(argp);
|
|
122
|
+
if (tokstr)
|
|
123
|
+
msg = lj_strfmt_pushf(L, err2msg(LJ_ERR_XNEAR), msg, tokstr);
|
|
124
|
+
if (cp->linenumber > 1)
|
|
125
|
+
msg = lj_strfmt_pushf(L, "%s at line %d", msg, cp->linenumber);
|
|
126
|
+
lj_err_callermsg(L, msg);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
LJ_NORET LJ_NOINLINE static void cp_err_token(CPState *cp, CPToken tok)
|
|
130
|
+
{
|
|
131
|
+
cp_errmsg(cp, cp->tok, LJ_ERR_XTOKEN, cp_tok2str(cp, tok));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
LJ_NORET LJ_NOINLINE static void cp_err_badidx(CPState *cp, CType *ct)
|
|
135
|
+
{
|
|
136
|
+
GCstr *s = lj_ctype_repr(cp->cts->L, ctype_typeid(cp->cts, ct), NULL);
|
|
137
|
+
cp_errmsg(cp, 0, LJ_ERR_FFI_BADIDX, strdata(s));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
LJ_NORET LJ_NOINLINE static void cp_err(CPState *cp, ErrMsg em)
|
|
141
|
+
{
|
|
142
|
+
cp_errmsg(cp, 0, em);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/* -- Main lexical scanner ------------------------------------------------ */
|
|
146
|
+
|
|
147
|
+
/* Parse number literal. Only handles int32_t/uint32_t right now. */
|
|
148
|
+
static CPToken cp_number(CPState *cp)
|
|
149
|
+
{
|
|
150
|
+
StrScanFmt fmt;
|
|
151
|
+
TValue o;
|
|
152
|
+
do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
|
|
153
|
+
cp_save(cp, '\0');
|
|
154
|
+
fmt = lj_strscan_scan((const uint8_t *)sbufB(&cp->sb), &o, STRSCAN_OPT_C);
|
|
155
|
+
if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32;
|
|
156
|
+
else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32;
|
|
157
|
+
else if (!(cp->mode & CPARSE_MODE_SKIP))
|
|
158
|
+
cp_errmsg(cp, CTOK_INTEGER, LJ_ERR_XNUMBER);
|
|
159
|
+
cp->val.u32 = (uint32_t)o.i;
|
|
160
|
+
return CTOK_INTEGER;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/* Parse identifier or keyword. */
|
|
164
|
+
static CPToken cp_ident(CPState *cp)
|
|
165
|
+
{
|
|
166
|
+
do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
|
|
167
|
+
cp->str = lj_buf_str(cp->L, &cp->sb);
|
|
168
|
+
cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask);
|
|
169
|
+
if (ctype_type(cp->ct->info) == CT_KW)
|
|
170
|
+
return ctype_cid(cp->ct->info);
|
|
171
|
+
return CTOK_IDENT;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* Parse parameter. */
|
|
175
|
+
static CPToken cp_param(CPState *cp)
|
|
176
|
+
{
|
|
177
|
+
CPChar c = cp_get(cp);
|
|
178
|
+
TValue *o = cp->param;
|
|
179
|
+
if (lj_char_isident(c) || c == '$') /* Reserve $xyz for future extensions. */
|
|
180
|
+
cp_errmsg(cp, c, LJ_ERR_XSYNTAX);
|
|
181
|
+
if (!o || o >= cp->L->top)
|
|
182
|
+
cp_err(cp, LJ_ERR_FFI_NUMPARAM);
|
|
183
|
+
cp->param = o+1;
|
|
184
|
+
if (tvisstr(o)) {
|
|
185
|
+
cp->str = strV(o);
|
|
186
|
+
cp->val.id = 0;
|
|
187
|
+
cp->ct = &cp->cts->tab[0];
|
|
188
|
+
return CTOK_IDENT;
|
|
189
|
+
} else if (tvisnumber(o)) {
|
|
190
|
+
cp->val.i32 = numberVint(o);
|
|
191
|
+
cp->val.id = CTID_INT32;
|
|
192
|
+
return CTOK_INTEGER;
|
|
193
|
+
} else {
|
|
194
|
+
GCcdata *cd;
|
|
195
|
+
if (!tviscdata(o))
|
|
196
|
+
lj_err_argtype(cp->L, (int)(o-cp->L->base)+1, "type parameter");
|
|
197
|
+
cd = cdataV(o);
|
|
198
|
+
if (cd->ctypeid == CTID_CTYPEID)
|
|
199
|
+
cp->val.id = *(CTypeID *)cdataptr(cd);
|
|
200
|
+
else
|
|
201
|
+
cp->val.id = cd->ctypeid;
|
|
202
|
+
return '$';
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* Parse string or character constant. */
|
|
207
|
+
static CPToken cp_string(CPState *cp)
|
|
208
|
+
{
|
|
209
|
+
CPChar delim = cp->c;
|
|
210
|
+
cp_get(cp);
|
|
211
|
+
while (cp->c != delim) {
|
|
212
|
+
CPChar c = cp->c;
|
|
213
|
+
if (c == '\0') cp_errmsg(cp, CTOK_EOF, LJ_ERR_XSTR);
|
|
214
|
+
if (c == '\\') {
|
|
215
|
+
c = cp_get(cp);
|
|
216
|
+
switch (c) {
|
|
217
|
+
case '\0': cp_errmsg(cp, CTOK_EOF, LJ_ERR_XSTR); break;
|
|
218
|
+
case 'a': c = '\a'; break;
|
|
219
|
+
case 'b': c = '\b'; break;
|
|
220
|
+
case 'f': c = '\f'; break;
|
|
221
|
+
case 'n': c = '\n'; break;
|
|
222
|
+
case 'r': c = '\r'; break;
|
|
223
|
+
case 't': c = '\t'; break;
|
|
224
|
+
case 'v': c = '\v'; break;
|
|
225
|
+
case 'e': c = 27; break;
|
|
226
|
+
case 'x':
|
|
227
|
+
c = 0;
|
|
228
|
+
while (lj_char_isxdigit(cp_get(cp)))
|
|
229
|
+
c = (c<<4) + (lj_char_isdigit(cp->c) ? cp->c-'0' : (cp->c&15)+9);
|
|
230
|
+
cp_save(cp, (c & 0xff));
|
|
231
|
+
continue;
|
|
232
|
+
default:
|
|
233
|
+
if (lj_char_isdigit(c)) {
|
|
234
|
+
c -= '0';
|
|
235
|
+
if (lj_char_isdigit(cp_get(cp))) {
|
|
236
|
+
c = c*8 + (cp->c - '0');
|
|
237
|
+
if (lj_char_isdigit(cp_get(cp))) {
|
|
238
|
+
c = c*8 + (cp->c - '0');
|
|
239
|
+
cp_get(cp);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
cp_save(cp, (c & 0xff));
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
cp_save(cp, c);
|
|
249
|
+
cp_get(cp);
|
|
250
|
+
}
|
|
251
|
+
cp_get(cp);
|
|
252
|
+
if (delim == '"') {
|
|
253
|
+
cp->str = lj_buf_str(cp->L, &cp->sb);
|
|
254
|
+
return CTOK_STRING;
|
|
255
|
+
} else {
|
|
256
|
+
if (sbuflen(&cp->sb) != 1) cp_err_token(cp, '\'');
|
|
257
|
+
cp->val.i32 = (int32_t)(char)*sbufB(&cp->sb);
|
|
258
|
+
cp->val.id = CTID_INT32;
|
|
259
|
+
return CTOK_INTEGER;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* Skip C comment. */
|
|
264
|
+
static void cp_comment_c(CPState *cp)
|
|
265
|
+
{
|
|
266
|
+
do {
|
|
267
|
+
if (cp_get(cp) == '*') {
|
|
268
|
+
do {
|
|
269
|
+
if (cp_get(cp) == '/') { cp_get(cp); return; }
|
|
270
|
+
} while (cp->c == '*');
|
|
271
|
+
}
|
|
272
|
+
if (cp_iseol(cp->c)) cp_newline(cp);
|
|
273
|
+
} while (cp->c != '\0');
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/* Skip C++ comment. */
|
|
277
|
+
static void cp_comment_cpp(CPState *cp)
|
|
278
|
+
{
|
|
279
|
+
while (!cp_iseol(cp_get(cp)) && cp->c != '\0')
|
|
280
|
+
;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/* Lexical scanner for C. Only a minimal subset is implemented. */
|
|
284
|
+
static CPToken cp_next_(CPState *cp)
|
|
285
|
+
{
|
|
286
|
+
lj_buf_reset(&cp->sb);
|
|
287
|
+
for (;;) {
|
|
288
|
+
if (lj_char_isident(cp->c))
|
|
289
|
+
return lj_char_isdigit(cp->c) ? cp_number(cp) : cp_ident(cp);
|
|
290
|
+
switch (cp->c) {
|
|
291
|
+
case '\n': case '\r': cp_newline(cp); /* fallthrough. */
|
|
292
|
+
case ' ': case '\t': case '\v': case '\f': cp_get(cp); break;
|
|
293
|
+
case '"': case '\'': return cp_string(cp);
|
|
294
|
+
case '/':
|
|
295
|
+
if (cp_get(cp) == '*') cp_comment_c(cp);
|
|
296
|
+
else if (cp->c == '/') cp_comment_cpp(cp);
|
|
297
|
+
else return '/';
|
|
298
|
+
break;
|
|
299
|
+
case '|':
|
|
300
|
+
if (cp_get(cp) != '|') return '|'; cp_get(cp); return CTOK_OROR;
|
|
301
|
+
case '&':
|
|
302
|
+
if (cp_get(cp) != '&') return '&'; cp_get(cp); return CTOK_ANDAND;
|
|
303
|
+
case '=':
|
|
304
|
+
if (cp_get(cp) != '=') return '='; cp_get(cp); return CTOK_EQ;
|
|
305
|
+
case '!':
|
|
306
|
+
if (cp_get(cp) != '=') return '!'; cp_get(cp); return CTOK_NE;
|
|
307
|
+
case '<':
|
|
308
|
+
if (cp_get(cp) == '=') { cp_get(cp); return CTOK_LE; }
|
|
309
|
+
else if (cp->c == '<') { cp_get(cp); return CTOK_SHL; }
|
|
310
|
+
return '<';
|
|
311
|
+
case '>':
|
|
312
|
+
if (cp_get(cp) == '=') { cp_get(cp); return CTOK_GE; }
|
|
313
|
+
else if (cp->c == '>') { cp_get(cp); return CTOK_SHR; }
|
|
314
|
+
return '>';
|
|
315
|
+
case '-':
|
|
316
|
+
if (cp_get(cp) != '>') return '-'; cp_get(cp); return CTOK_DEREF;
|
|
317
|
+
case '$':
|
|
318
|
+
return cp_param(cp);
|
|
319
|
+
case '\0': return CTOK_EOF;
|
|
320
|
+
default: { CPToken c = cp->c; cp_get(cp); return c; }
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
static LJ_NOINLINE CPToken cp_next(CPState *cp)
|
|
326
|
+
{
|
|
327
|
+
return (cp->tok = cp_next_(cp));
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/* -- C parser ------------------------------------------------------------ */
|
|
331
|
+
|
|
332
|
+
/* Namespaces for resolving identifiers. */
|
|
333
|
+
#define CPNS_DEFAULT \
|
|
334
|
+
((1u<<CT_KW)|(1u<<CT_TYPEDEF)|(1u<<CT_FUNC)|(1u<<CT_EXTERN)|(1u<<CT_CONSTVAL))
|
|
335
|
+
#define CPNS_STRUCT ((1u<<CT_KW)|(1u<<CT_STRUCT)|(1u<<CT_ENUM))
|
|
336
|
+
|
|
337
|
+
typedef CTypeID CPDeclIdx; /* Index into declaration stack. */
|
|
338
|
+
typedef uint32_t CPscl; /* Storage class flags. */
|
|
339
|
+
|
|
340
|
+
/* Type declaration context. */
|
|
341
|
+
typedef struct CPDecl {
|
|
342
|
+
CPDeclIdx top; /* Top of declaration stack. */
|
|
343
|
+
CPDeclIdx pos; /* Insertion position in declaration chain. */
|
|
344
|
+
CPDeclIdx specpos; /* Saved position for declaration specifier. */
|
|
345
|
+
uint32_t mode; /* Declarator mode. */
|
|
346
|
+
CPState *cp; /* C parser state. */
|
|
347
|
+
GCstr *name; /* Name of declared identifier (if direct). */
|
|
348
|
+
GCstr *redir; /* Redirected symbol name. */
|
|
349
|
+
CTypeID nameid; /* Existing typedef for declared identifier. */
|
|
350
|
+
CTInfo attr; /* Attributes. */
|
|
351
|
+
CTInfo fattr; /* Function attributes. */
|
|
352
|
+
CTInfo specattr; /* Saved attributes. */
|
|
353
|
+
CTInfo specfattr; /* Saved function attributes. */
|
|
354
|
+
CTSize bits; /* Field size in bits (if any). */
|
|
355
|
+
CType stack[CPARSE_MAX_DECLSTACK]; /* Type declaration stack. */
|
|
356
|
+
} CPDecl;
|
|
357
|
+
|
|
358
|
+
/* Forward declarations. */
|
|
359
|
+
static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl);
|
|
360
|
+
static void cp_declarator(CPState *cp, CPDecl *decl);
|
|
361
|
+
static CTypeID cp_decl_abstract(CPState *cp);
|
|
362
|
+
|
|
363
|
+
/* Initialize C parser state. Caller must set up: L, p, srcname, mode. */
|
|
364
|
+
static void cp_init(CPState *cp)
|
|
365
|
+
{
|
|
366
|
+
cp->linenumber = 1;
|
|
367
|
+
cp->depth = 0;
|
|
368
|
+
cp->curpack = 0;
|
|
369
|
+
cp->packstack[0] = 255;
|
|
370
|
+
lj_buf_init(cp->L, &cp->sb);
|
|
371
|
+
lua_assert(cp->p != NULL);
|
|
372
|
+
cp_get(cp); /* Read-ahead first char. */
|
|
373
|
+
cp->tok = 0;
|
|
374
|
+
cp->tmask = CPNS_DEFAULT;
|
|
375
|
+
cp_next(cp); /* Read-ahead first token. */
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/* Cleanup C parser state. */
|
|
379
|
+
static void cp_cleanup(CPState *cp)
|
|
380
|
+
{
|
|
381
|
+
global_State *g = G(cp->L);
|
|
382
|
+
lj_buf_free(g, &cp->sb);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/* Check and consume optional token. */
|
|
386
|
+
static int cp_opt(CPState *cp, CPToken tok)
|
|
387
|
+
{
|
|
388
|
+
if (cp->tok == tok) { cp_next(cp); return 1; }
|
|
389
|
+
return 0;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/* Check and consume token. */
|
|
393
|
+
static void cp_check(CPState *cp, CPToken tok)
|
|
394
|
+
{
|
|
395
|
+
if (cp->tok != tok) cp_err_token(cp, tok);
|
|
396
|
+
cp_next(cp);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/* Check if the next token may start a type declaration. */
|
|
400
|
+
static int cp_istypedecl(CPState *cp)
|
|
401
|
+
{
|
|
402
|
+
if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECL) return 1;
|
|
403
|
+
if (cp->tok == CTOK_IDENT && ctype_istypedef(cp->ct->info)) return 1;
|
|
404
|
+
if (cp->tok == '$') return 1;
|
|
405
|
+
return 0;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/* -- Constant expression evaluator --------------------------------------- */
|
|
409
|
+
|
|
410
|
+
/* Forward declarations. */
|
|
411
|
+
static void cp_expr_unary(CPState *cp, CPValue *k);
|
|
412
|
+
static void cp_expr_sub(CPState *cp, CPValue *k, int pri);
|
|
413
|
+
|
|
414
|
+
/* Please note that type handling is very weak here. Most ops simply
|
|
415
|
+
** assume integer operands. Accessors are only needed to compute types and
|
|
416
|
+
** return synthetic values. The only purpose of the expression evaluator
|
|
417
|
+
** is to compute the values of constant expressions one would typically
|
|
418
|
+
** find in C header files. And again: this is NOT a validating C parser!
|
|
419
|
+
*/
|
|
420
|
+
|
|
421
|
+
/* Parse comma separated expression and return last result. */
|
|
422
|
+
static void cp_expr_comma(CPState *cp, CPValue *k)
|
|
423
|
+
{
|
|
424
|
+
do { cp_expr_sub(cp, k, 0); } while (cp_opt(cp, ','));
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/* Parse sizeof/alignof operator. */
|
|
428
|
+
static void cp_expr_sizeof(CPState *cp, CPValue *k, int wantsz)
|
|
429
|
+
{
|
|
430
|
+
CTSize sz;
|
|
431
|
+
CTInfo info;
|
|
432
|
+
if (cp_opt(cp, '(')) {
|
|
433
|
+
if (cp_istypedecl(cp))
|
|
434
|
+
k->id = cp_decl_abstract(cp);
|
|
435
|
+
else
|
|
436
|
+
cp_expr_comma(cp, k);
|
|
437
|
+
cp_check(cp, ')');
|
|
438
|
+
} else {
|
|
439
|
+
cp_expr_unary(cp, k);
|
|
440
|
+
}
|
|
441
|
+
info = lj_ctype_info(cp->cts, k->id, &sz);
|
|
442
|
+
if (wantsz) {
|
|
443
|
+
if (sz != CTSIZE_INVALID)
|
|
444
|
+
k->u32 = sz;
|
|
445
|
+
else if (k->id != CTID_A_CCHAR) /* Special case for sizeof("string"). */
|
|
446
|
+
cp_err(cp, LJ_ERR_FFI_INVSIZE);
|
|
447
|
+
} else {
|
|
448
|
+
k->u32 = 1u << ctype_align(info);
|
|
449
|
+
}
|
|
450
|
+
k->id = CTID_UINT32; /* Really size_t. */
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/* Parse prefix operators. */
|
|
454
|
+
static void cp_expr_prefix(CPState *cp, CPValue *k)
|
|
455
|
+
{
|
|
456
|
+
if (cp->tok == CTOK_INTEGER) {
|
|
457
|
+
*k = cp->val; cp_next(cp);
|
|
458
|
+
} else if (cp_opt(cp, '+')) {
|
|
459
|
+
cp_expr_unary(cp, k); /* Nothing to do (well, integer promotion). */
|
|
460
|
+
} else if (cp_opt(cp, '-')) {
|
|
461
|
+
cp_expr_unary(cp, k); k->i32 = -k->i32;
|
|
462
|
+
} else if (cp_opt(cp, '~')) {
|
|
463
|
+
cp_expr_unary(cp, k); k->i32 = ~k->i32;
|
|
464
|
+
} else if (cp_opt(cp, '!')) {
|
|
465
|
+
cp_expr_unary(cp, k); k->i32 = !k->i32; k->id = CTID_INT32;
|
|
466
|
+
} else if (cp_opt(cp, '(')) {
|
|
467
|
+
if (cp_istypedecl(cp)) { /* Cast operator. */
|
|
468
|
+
CTypeID id = cp_decl_abstract(cp);
|
|
469
|
+
cp_check(cp, ')');
|
|
470
|
+
cp_expr_unary(cp, k);
|
|
471
|
+
k->id = id; /* No conversion performed. */
|
|
472
|
+
} else { /* Sub-expression. */
|
|
473
|
+
cp_expr_comma(cp, k);
|
|
474
|
+
cp_check(cp, ')');
|
|
475
|
+
}
|
|
476
|
+
} else if (cp_opt(cp, '*')) { /* Indirection. */
|
|
477
|
+
CType *ct;
|
|
478
|
+
cp_expr_unary(cp, k);
|
|
479
|
+
ct = lj_ctype_rawref(cp->cts, k->id);
|
|
480
|
+
if (!ctype_ispointer(ct->info))
|
|
481
|
+
cp_err_badidx(cp, ct);
|
|
482
|
+
k->u32 = 0; k->id = ctype_cid(ct->info);
|
|
483
|
+
} else if (cp_opt(cp, '&')) { /* Address operator. */
|
|
484
|
+
cp_expr_unary(cp, k);
|
|
485
|
+
k->id = lj_ctype_intern(cp->cts, CTINFO(CT_PTR, CTALIGN_PTR+k->id),
|
|
486
|
+
CTSIZE_PTR);
|
|
487
|
+
} else if (cp_opt(cp, CTOK_SIZEOF)) {
|
|
488
|
+
cp_expr_sizeof(cp, k, 1);
|
|
489
|
+
} else if (cp_opt(cp, CTOK_ALIGNOF)) {
|
|
490
|
+
cp_expr_sizeof(cp, k, 0);
|
|
491
|
+
} else if (cp->tok == CTOK_IDENT) {
|
|
492
|
+
if (ctype_type(cp->ct->info) == CT_CONSTVAL) {
|
|
493
|
+
k->u32 = cp->ct->size; k->id = ctype_cid(cp->ct->info);
|
|
494
|
+
} else if (ctype_type(cp->ct->info) == CT_EXTERN) {
|
|
495
|
+
k->u32 = cp->val.id; k->id = ctype_cid(cp->ct->info);
|
|
496
|
+
} else if (ctype_type(cp->ct->info) == CT_FUNC) {
|
|
497
|
+
k->u32 = cp->val.id; k->id = cp->val.id;
|
|
498
|
+
} else {
|
|
499
|
+
goto err_expr;
|
|
500
|
+
}
|
|
501
|
+
cp_next(cp);
|
|
502
|
+
} else if (cp->tok == CTOK_STRING) {
|
|
503
|
+
CTSize sz = cp->str->len;
|
|
504
|
+
while (cp_next(cp) == CTOK_STRING)
|
|
505
|
+
sz += cp->str->len;
|
|
506
|
+
k->u32 = sz + 1;
|
|
507
|
+
k->id = CTID_A_CCHAR;
|
|
508
|
+
} else {
|
|
509
|
+
err_expr:
|
|
510
|
+
cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/* Parse postfix operators. */
|
|
515
|
+
static void cp_expr_postfix(CPState *cp, CPValue *k)
|
|
516
|
+
{
|
|
517
|
+
for (;;) {
|
|
518
|
+
CType *ct;
|
|
519
|
+
if (cp_opt(cp, '[')) { /* Array/pointer index. */
|
|
520
|
+
CPValue k2;
|
|
521
|
+
cp_expr_comma(cp, &k2);
|
|
522
|
+
ct = lj_ctype_rawref(cp->cts, k->id);
|
|
523
|
+
if (!ctype_ispointer(ct->info)) {
|
|
524
|
+
ct = lj_ctype_rawref(cp->cts, k2.id);
|
|
525
|
+
if (!ctype_ispointer(ct->info))
|
|
526
|
+
cp_err_badidx(cp, ct);
|
|
527
|
+
}
|
|
528
|
+
cp_check(cp, ']');
|
|
529
|
+
k->u32 = 0;
|
|
530
|
+
} else if (cp->tok == '.' || cp->tok == CTOK_DEREF) { /* Struct deref. */
|
|
531
|
+
CTSize ofs;
|
|
532
|
+
CType *fct;
|
|
533
|
+
ct = lj_ctype_rawref(cp->cts, k->id);
|
|
534
|
+
if (cp->tok == CTOK_DEREF) {
|
|
535
|
+
if (!ctype_ispointer(ct->info))
|
|
536
|
+
cp_err_badidx(cp, ct);
|
|
537
|
+
ct = lj_ctype_rawref(cp->cts, ctype_cid(ct->info));
|
|
538
|
+
}
|
|
539
|
+
cp_next(cp);
|
|
540
|
+
if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
|
|
541
|
+
if (!ctype_isstruct(ct->info) || ct->size == CTSIZE_INVALID ||
|
|
542
|
+
!(fct = lj_ctype_getfield(cp->cts, ct, cp->str, &ofs)) ||
|
|
543
|
+
ctype_isbitfield(fct->info)) {
|
|
544
|
+
GCstr *s = lj_ctype_repr(cp->cts->L, ctype_typeid(cp->cts, ct), NULL);
|
|
545
|
+
cp_errmsg(cp, 0, LJ_ERR_FFI_BADMEMBER, strdata(s), strdata(cp->str));
|
|
546
|
+
}
|
|
547
|
+
ct = fct;
|
|
548
|
+
k->u32 = ctype_isconstval(ct->info) ? ct->size : 0;
|
|
549
|
+
cp_next(cp);
|
|
550
|
+
} else {
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
k->id = ctype_cid(ct->info);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/* Parse infix operators. */
|
|
558
|
+
static void cp_expr_infix(CPState *cp, CPValue *k, int pri)
|
|
559
|
+
{
|
|
560
|
+
CPValue k2;
|
|
561
|
+
k2.u32 = 0; k2.id = 0; /* Silence the compiler. */
|
|
562
|
+
for (;;) {
|
|
563
|
+
switch (pri) {
|
|
564
|
+
case 0:
|
|
565
|
+
if (cp_opt(cp, '?')) {
|
|
566
|
+
CPValue k3;
|
|
567
|
+
cp_expr_comma(cp, &k2); /* Right-associative. */
|
|
568
|
+
cp_check(cp, ':');
|
|
569
|
+
cp_expr_sub(cp, &k3, 0);
|
|
570
|
+
k->u32 = k->u32 ? k2.u32 : k3.u32;
|
|
571
|
+
k->id = k2.id > k3.id ? k2.id : k3.id;
|
|
572
|
+
continue;
|
|
573
|
+
}
|
|
574
|
+
case 1:
|
|
575
|
+
if (cp_opt(cp, CTOK_OROR)) {
|
|
576
|
+
cp_expr_sub(cp, &k2, 2); k->i32 = k->u32 || k2.u32; k->id = CTID_INT32;
|
|
577
|
+
continue;
|
|
578
|
+
}
|
|
579
|
+
case 2:
|
|
580
|
+
if (cp_opt(cp, CTOK_ANDAND)) {
|
|
581
|
+
cp_expr_sub(cp, &k2, 3); k->i32 = k->u32 && k2.u32; k->id = CTID_INT32;
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
case 3:
|
|
585
|
+
if (cp_opt(cp, '|')) {
|
|
586
|
+
cp_expr_sub(cp, &k2, 4); k->u32 = k->u32 | k2.u32; goto arith_result;
|
|
587
|
+
}
|
|
588
|
+
case 4:
|
|
589
|
+
if (cp_opt(cp, '^')) {
|
|
590
|
+
cp_expr_sub(cp, &k2, 5); k->u32 = k->u32 ^ k2.u32; goto arith_result;
|
|
591
|
+
}
|
|
592
|
+
case 5:
|
|
593
|
+
if (cp_opt(cp, '&')) {
|
|
594
|
+
cp_expr_sub(cp, &k2, 6); k->u32 = k->u32 & k2.u32; goto arith_result;
|
|
595
|
+
}
|
|
596
|
+
case 6:
|
|
597
|
+
if (cp_opt(cp, CTOK_EQ)) {
|
|
598
|
+
cp_expr_sub(cp, &k2, 7); k->i32 = k->u32 == k2.u32; k->id = CTID_INT32;
|
|
599
|
+
continue;
|
|
600
|
+
} else if (cp_opt(cp, CTOK_NE)) {
|
|
601
|
+
cp_expr_sub(cp, &k2, 7); k->i32 = k->u32 != k2.u32; k->id = CTID_INT32;
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
case 7:
|
|
605
|
+
if (cp_opt(cp, '<')) {
|
|
606
|
+
cp_expr_sub(cp, &k2, 8);
|
|
607
|
+
if (k->id == CTID_INT32 && k2.id == CTID_INT32)
|
|
608
|
+
k->i32 = k->i32 < k2.i32;
|
|
609
|
+
else
|
|
610
|
+
k->i32 = k->u32 < k2.u32;
|
|
611
|
+
k->id = CTID_INT32;
|
|
612
|
+
continue;
|
|
613
|
+
} else if (cp_opt(cp, '>')) {
|
|
614
|
+
cp_expr_sub(cp, &k2, 8);
|
|
615
|
+
if (k->id == CTID_INT32 && k2.id == CTID_INT32)
|
|
616
|
+
k->i32 = k->i32 > k2.i32;
|
|
617
|
+
else
|
|
618
|
+
k->i32 = k->u32 > k2.u32;
|
|
619
|
+
k->id = CTID_INT32;
|
|
620
|
+
continue;
|
|
621
|
+
} else if (cp_opt(cp, CTOK_LE)) {
|
|
622
|
+
cp_expr_sub(cp, &k2, 8);
|
|
623
|
+
if (k->id == CTID_INT32 && k2.id == CTID_INT32)
|
|
624
|
+
k->i32 = k->i32 <= k2.i32;
|
|
625
|
+
else
|
|
626
|
+
k->i32 = k->u32 <= k2.u32;
|
|
627
|
+
k->id = CTID_INT32;
|
|
628
|
+
continue;
|
|
629
|
+
} else if (cp_opt(cp, CTOK_GE)) {
|
|
630
|
+
cp_expr_sub(cp, &k2, 8);
|
|
631
|
+
if (k->id == CTID_INT32 && k2.id == CTID_INT32)
|
|
632
|
+
k->i32 = k->i32 >= k2.i32;
|
|
633
|
+
else
|
|
634
|
+
k->i32 = k->u32 >= k2.u32;
|
|
635
|
+
k->id = CTID_INT32;
|
|
636
|
+
continue;
|
|
637
|
+
}
|
|
638
|
+
case 8:
|
|
639
|
+
if (cp_opt(cp, CTOK_SHL)) {
|
|
640
|
+
cp_expr_sub(cp, &k2, 9); k->u32 = k->u32 << k2.u32;
|
|
641
|
+
continue;
|
|
642
|
+
} else if (cp_opt(cp, CTOK_SHR)) {
|
|
643
|
+
cp_expr_sub(cp, &k2, 9);
|
|
644
|
+
if (k->id == CTID_INT32)
|
|
645
|
+
k->i32 = k->i32 >> k2.i32;
|
|
646
|
+
else
|
|
647
|
+
k->u32 = k->u32 >> k2.u32;
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
case 9:
|
|
651
|
+
if (cp_opt(cp, '+')) {
|
|
652
|
+
cp_expr_sub(cp, &k2, 10); k->u32 = k->u32 + k2.u32;
|
|
653
|
+
arith_result:
|
|
654
|
+
if (k2.id > k->id) k->id = k2.id; /* Trivial promotion to unsigned. */
|
|
655
|
+
continue;
|
|
656
|
+
} else if (cp_opt(cp, '-')) {
|
|
657
|
+
cp_expr_sub(cp, &k2, 10); k->u32 = k->u32 - k2.u32; goto arith_result;
|
|
658
|
+
}
|
|
659
|
+
case 10:
|
|
660
|
+
if (cp_opt(cp, '*')) {
|
|
661
|
+
cp_expr_unary(cp, &k2); k->u32 = k->u32 * k2.u32; goto arith_result;
|
|
662
|
+
} else if (cp_opt(cp, '/')) {
|
|
663
|
+
cp_expr_unary(cp, &k2);
|
|
664
|
+
if (k2.id > k->id) k->id = k2.id; /* Trivial promotion to unsigned. */
|
|
665
|
+
if (k2.u32 == 0 ||
|
|
666
|
+
(k->id == CTID_INT32 && k->u32 == 0x80000000u && k2.i32 == -1))
|
|
667
|
+
cp_err(cp, LJ_ERR_BADVAL);
|
|
668
|
+
if (k->id == CTID_INT32)
|
|
669
|
+
k->i32 = k->i32 / k2.i32;
|
|
670
|
+
else
|
|
671
|
+
k->u32 = k->u32 / k2.u32;
|
|
672
|
+
continue;
|
|
673
|
+
} else if (cp_opt(cp, '%')) {
|
|
674
|
+
cp_expr_unary(cp, &k2);
|
|
675
|
+
if (k2.id > k->id) k->id = k2.id; /* Trivial promotion to unsigned. */
|
|
676
|
+
if (k2.u32 == 0 ||
|
|
677
|
+
(k->id == CTID_INT32 && k->u32 == 0x80000000u && k2.i32 == -1))
|
|
678
|
+
cp_err(cp, LJ_ERR_BADVAL);
|
|
679
|
+
if (k->id == CTID_INT32)
|
|
680
|
+
k->i32 = k->i32 % k2.i32;
|
|
681
|
+
else
|
|
682
|
+
k->u32 = k->u32 % k2.u32;
|
|
683
|
+
continue;
|
|
684
|
+
}
|
|
685
|
+
default:
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/* Parse and evaluate unary expression. */
|
|
692
|
+
static void cp_expr_unary(CPState *cp, CPValue *k)
|
|
693
|
+
{
|
|
694
|
+
if (++cp->depth > CPARSE_MAX_DECLDEPTH) cp_err(cp, LJ_ERR_XLEVELS);
|
|
695
|
+
cp_expr_prefix(cp, k);
|
|
696
|
+
cp_expr_postfix(cp, k);
|
|
697
|
+
cp->depth--;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/* Parse and evaluate sub-expression. */
|
|
701
|
+
static void cp_expr_sub(CPState *cp, CPValue *k, int pri)
|
|
702
|
+
{
|
|
703
|
+
cp_expr_unary(cp, k);
|
|
704
|
+
cp_expr_infix(cp, k, pri);
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/* Parse constant integer expression. */
|
|
708
|
+
static void cp_expr_kint(CPState *cp, CPValue *k)
|
|
709
|
+
{
|
|
710
|
+
CType *ct;
|
|
711
|
+
cp_expr_sub(cp, k, 0);
|
|
712
|
+
ct = ctype_raw(cp->cts, k->id);
|
|
713
|
+
if (!ctype_isinteger(ct->info)) cp_err(cp, LJ_ERR_BADVAL);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
/* Parse (non-negative) size expression. */
|
|
717
|
+
static CTSize cp_expr_ksize(CPState *cp)
|
|
718
|
+
{
|
|
719
|
+
CPValue k;
|
|
720
|
+
cp_expr_kint(cp, &k);
|
|
721
|
+
if (k.u32 >= 0x80000000u) cp_err(cp, LJ_ERR_FFI_INVSIZE);
|
|
722
|
+
return k.u32;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/* -- Type declaration stack management ----------------------------------- */
|
|
726
|
+
|
|
727
|
+
/* Add declaration element behind the insertion position. */
|
|
728
|
+
static CPDeclIdx cp_add(CPDecl *decl, CTInfo info, CTSize size)
|
|
729
|
+
{
|
|
730
|
+
CPDeclIdx top = decl->top;
|
|
731
|
+
if (top >= CPARSE_MAX_DECLSTACK) cp_err(decl->cp, LJ_ERR_XLEVELS);
|
|
732
|
+
decl->stack[top].info = info;
|
|
733
|
+
decl->stack[top].size = size;
|
|
734
|
+
decl->stack[top].sib = 0;
|
|
735
|
+
setgcrefnull(decl->stack[top].name);
|
|
736
|
+
decl->stack[top].next = decl->stack[decl->pos].next;
|
|
737
|
+
decl->stack[decl->pos].next = (CTypeID1)top;
|
|
738
|
+
decl->top = top+1;
|
|
739
|
+
return top;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/* Push declaration element before the insertion position. */
|
|
743
|
+
static CPDeclIdx cp_push(CPDecl *decl, CTInfo info, CTSize size)
|
|
744
|
+
{
|
|
745
|
+
return (decl->pos = cp_add(decl, info, size));
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/* Push or merge attributes. */
|
|
749
|
+
static void cp_push_attributes(CPDecl *decl)
|
|
750
|
+
{
|
|
751
|
+
CType *ct = &decl->stack[decl->pos];
|
|
752
|
+
if (ctype_isfunc(ct->info)) { /* Ok to modify in-place. */
|
|
753
|
+
#if LJ_TARGET_X86
|
|
754
|
+
if ((decl->fattr & CTFP_CCONV))
|
|
755
|
+
ct->info = (ct->info & (CTMASK_NUM|CTF_VARARG|CTMASK_CID)) +
|
|
756
|
+
(decl->fattr & ~CTMASK_CID);
|
|
757
|
+
#endif
|
|
758
|
+
} else {
|
|
759
|
+
if ((decl->attr & CTFP_ALIGNED) && !(decl->mode & CPARSE_MODE_FIELD))
|
|
760
|
+
cp_push(decl, CTINFO(CT_ATTRIB, CTATTRIB(CTA_ALIGN)),
|
|
761
|
+
ctype_align(decl->attr));
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
/* Push unrolled type to declaration stack and merge qualifiers. */
|
|
766
|
+
static void cp_push_type(CPDecl *decl, CTypeID id)
|
|
767
|
+
{
|
|
768
|
+
CType *ct = ctype_get(decl->cp->cts, id);
|
|
769
|
+
CTInfo info = ct->info;
|
|
770
|
+
CTSize size = ct->size;
|
|
771
|
+
switch (ctype_type(info)) {
|
|
772
|
+
case CT_STRUCT: case CT_ENUM:
|
|
773
|
+
cp_push(decl, CTINFO(CT_TYPEDEF, id), 0); /* Don't copy unique types. */
|
|
774
|
+
if ((decl->attr & CTF_QUAL)) { /* Push unmerged qualifiers. */
|
|
775
|
+
cp_push(decl, CTINFO(CT_ATTRIB, CTATTRIB(CTA_QUAL)),
|
|
776
|
+
(decl->attr & CTF_QUAL));
|
|
777
|
+
decl->attr &= ~CTF_QUAL;
|
|
778
|
+
}
|
|
779
|
+
break;
|
|
780
|
+
case CT_ATTRIB:
|
|
781
|
+
if (ctype_isxattrib(info, CTA_QUAL))
|
|
782
|
+
decl->attr &= ~size; /* Remove redundant qualifiers. */
|
|
783
|
+
cp_push_type(decl, ctype_cid(info)); /* Unroll. */
|
|
784
|
+
cp_push(decl, info & ~CTMASK_CID, size); /* Copy type. */
|
|
785
|
+
break;
|
|
786
|
+
case CT_ARRAY:
|
|
787
|
+
if ((ct->info & (CTF_VECTOR|CTF_COMPLEX))) {
|
|
788
|
+
info |= (decl->attr & CTF_QUAL);
|
|
789
|
+
decl->attr &= ~CTF_QUAL;
|
|
790
|
+
}
|
|
791
|
+
cp_push_type(decl, ctype_cid(info)); /* Unroll. */
|
|
792
|
+
cp_push(decl, info & ~CTMASK_CID, size); /* Copy type. */
|
|
793
|
+
decl->stack[decl->pos].sib = 1; /* Mark as already checked and sized. */
|
|
794
|
+
/* Note: this is not copied to the ct->sib in the C type table. */
|
|
795
|
+
break;
|
|
796
|
+
case CT_FUNC:
|
|
797
|
+
/* Copy type, link parameters (shared). */
|
|
798
|
+
decl->stack[cp_push(decl, info, size)].sib = ct->sib;
|
|
799
|
+
break;
|
|
800
|
+
default:
|
|
801
|
+
/* Copy type, merge common qualifiers. */
|
|
802
|
+
cp_push(decl, info|(decl->attr & CTF_QUAL), size);
|
|
803
|
+
decl->attr &= ~CTF_QUAL;
|
|
804
|
+
break;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
/* Consume the declaration element chain and intern the C type. */
|
|
809
|
+
static CTypeID cp_decl_intern(CPState *cp, CPDecl *decl)
|
|
810
|
+
{
|
|
811
|
+
CTypeID id = 0;
|
|
812
|
+
CPDeclIdx idx = 0;
|
|
813
|
+
CTSize csize = CTSIZE_INVALID;
|
|
814
|
+
CTSize cinfo = 0;
|
|
815
|
+
do {
|
|
816
|
+
CType *ct = &decl->stack[idx];
|
|
817
|
+
CTInfo info = ct->info;
|
|
818
|
+
CTInfo size = ct->size;
|
|
819
|
+
/* The cid is already part of info for copies of pointers/functions. */
|
|
820
|
+
idx = ct->next;
|
|
821
|
+
if (ctype_istypedef(info)) {
|
|
822
|
+
lua_assert(id == 0);
|
|
823
|
+
id = ctype_cid(info);
|
|
824
|
+
/* Always refetch info/size, since struct/enum may have been completed. */
|
|
825
|
+
cinfo = ctype_get(cp->cts, id)->info;
|
|
826
|
+
csize = ctype_get(cp->cts, id)->size;
|
|
827
|
+
lua_assert(ctype_isstruct(cinfo) || ctype_isenum(cinfo));
|
|
828
|
+
} else if (ctype_isfunc(info)) { /* Intern function. */
|
|
829
|
+
CType *fct;
|
|
830
|
+
CTypeID fid;
|
|
831
|
+
CTypeID sib;
|
|
832
|
+
if (id) {
|
|
833
|
+
CType *refct = ctype_raw(cp->cts, id);
|
|
834
|
+
/* Reject function or refarray return types. */
|
|
835
|
+
if (ctype_isfunc(refct->info) || ctype_isrefarray(refct->info))
|
|
836
|
+
cp_err(cp, LJ_ERR_FFI_INVTYPE);
|
|
837
|
+
}
|
|
838
|
+
/* No intervening attributes allowed, skip forward. */
|
|
839
|
+
while (idx) {
|
|
840
|
+
CType *ctn = &decl->stack[idx];
|
|
841
|
+
if (!ctype_isattrib(ctn->info)) break;
|
|
842
|
+
idx = ctn->next; /* Skip attribute. */
|
|
843
|
+
}
|
|
844
|
+
sib = ct->sib; /* Next line may reallocate the C type table. */
|
|
845
|
+
fid = lj_ctype_new(cp->cts, &fct);
|
|
846
|
+
csize = CTSIZE_INVALID;
|
|
847
|
+
fct->info = cinfo = info + id;
|
|
848
|
+
fct->size = size;
|
|
849
|
+
fct->sib = sib;
|
|
850
|
+
id = fid;
|
|
851
|
+
} else if (ctype_isattrib(info)) {
|
|
852
|
+
if (ctype_isxattrib(info, CTA_QUAL))
|
|
853
|
+
cinfo |= size;
|
|
854
|
+
else if (ctype_isxattrib(info, CTA_ALIGN))
|
|
855
|
+
CTF_INSERT(cinfo, ALIGN, size);
|
|
856
|
+
id = lj_ctype_intern(cp->cts, info+id, size);
|
|
857
|
+
/* Inherit csize/cinfo from original type. */
|
|
858
|
+
} else {
|
|
859
|
+
if (ctype_isnum(info)) { /* Handle mode/vector-size attributes. */
|
|
860
|
+
lua_assert(id == 0);
|
|
861
|
+
if (!(info & CTF_BOOL)) {
|
|
862
|
+
CTSize msize = ctype_msizeP(decl->attr);
|
|
863
|
+
CTSize vsize = ctype_vsizeP(decl->attr);
|
|
864
|
+
if (msize && (!(info & CTF_FP) || (msize == 4 || msize == 8))) {
|
|
865
|
+
CTSize malign = lj_fls(msize);
|
|
866
|
+
if (malign > 4) malign = 4; /* Limit alignment. */
|
|
867
|
+
CTF_INSERT(info, ALIGN, malign);
|
|
868
|
+
size = msize; /* Override size via mode. */
|
|
869
|
+
}
|
|
870
|
+
if (vsize) { /* Vector size set? */
|
|
871
|
+
CTSize esize = lj_fls(size);
|
|
872
|
+
if (vsize >= esize) {
|
|
873
|
+
/* Intern the element type first. */
|
|
874
|
+
id = lj_ctype_intern(cp->cts, info, size);
|
|
875
|
+
/* Then create a vector (array) with vsize alignment. */
|
|
876
|
+
size = (1u << vsize);
|
|
877
|
+
if (vsize > 4) vsize = 4; /* Limit alignment. */
|
|
878
|
+
if (ctype_align(info) > vsize) vsize = ctype_align(info);
|
|
879
|
+
info = CTINFO(CT_ARRAY, (info & CTF_QUAL) + CTF_VECTOR +
|
|
880
|
+
CTALIGN(vsize));
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
} else if (ctype_isptr(info)) {
|
|
885
|
+
/* Reject pointer/ref to ref. */
|
|
886
|
+
if (id && ctype_isref(ctype_raw(cp->cts, id)->info))
|
|
887
|
+
cp_err(cp, LJ_ERR_FFI_INVTYPE);
|
|
888
|
+
if (ctype_isref(info)) {
|
|
889
|
+
info &= ~CTF_VOLATILE; /* Refs are always const, never volatile. */
|
|
890
|
+
/* No intervening attributes allowed, skip forward. */
|
|
891
|
+
while (idx) {
|
|
892
|
+
CType *ctn = &decl->stack[idx];
|
|
893
|
+
if (!ctype_isattrib(ctn->info)) break;
|
|
894
|
+
idx = ctn->next; /* Skip attribute. */
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
} else if (ctype_isarray(info)) { /* Check for valid array size etc. */
|
|
898
|
+
if (ct->sib == 0) { /* Only check/size arrays not copied by unroll. */
|
|
899
|
+
if (ctype_isref(cinfo)) /* Reject arrays of refs. */
|
|
900
|
+
cp_err(cp, LJ_ERR_FFI_INVTYPE);
|
|
901
|
+
/* Reject VLS or unknown-sized types. */
|
|
902
|
+
if (ctype_isvltype(cinfo) || csize == CTSIZE_INVALID)
|
|
903
|
+
cp_err(cp, LJ_ERR_FFI_INVSIZE);
|
|
904
|
+
/* a[] and a[?] keep their invalid size. */
|
|
905
|
+
if (size != CTSIZE_INVALID) {
|
|
906
|
+
uint64_t xsz = (uint64_t)size * csize;
|
|
907
|
+
if (xsz >= 0x80000000u) cp_err(cp, LJ_ERR_FFI_INVSIZE);
|
|
908
|
+
size = (CTSize)xsz;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
if ((cinfo & CTF_ALIGN) > (info & CTF_ALIGN)) /* Find max. align. */
|
|
912
|
+
info = (info & ~CTF_ALIGN) | (cinfo & CTF_ALIGN);
|
|
913
|
+
info |= (cinfo & CTF_QUAL); /* Inherit qual. */
|
|
914
|
+
} else {
|
|
915
|
+
lua_assert(ctype_isvoid(info));
|
|
916
|
+
}
|
|
917
|
+
csize = size;
|
|
918
|
+
cinfo = info+id;
|
|
919
|
+
id = lj_ctype_intern(cp->cts, info+id, size);
|
|
920
|
+
}
|
|
921
|
+
} while (idx);
|
|
922
|
+
return id;
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
/* -- C declaration parser ------------------------------------------------ */
|
|
926
|
+
|
|
927
|
+
#define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be)
|
|
928
|
+
|
|
929
|
+
/* Reset declaration state to declaration specifier. */
|
|
930
|
+
static void cp_decl_reset(CPDecl *decl)
|
|
931
|
+
{
|
|
932
|
+
decl->pos = decl->specpos;
|
|
933
|
+
decl->top = decl->specpos+1;
|
|
934
|
+
decl->stack[decl->specpos].next = 0;
|
|
935
|
+
decl->attr = decl->specattr;
|
|
936
|
+
decl->fattr = decl->specfattr;
|
|
937
|
+
decl->name = NULL;
|
|
938
|
+
decl->redir = NULL;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
/* Parse constant initializer. */
|
|
942
|
+
/* NYI: FP constants and strings as initializers. */
|
|
943
|
+
static CTypeID cp_decl_constinit(CPState *cp, CType **ctp, CTypeID ctypeid)
|
|
944
|
+
{
|
|
945
|
+
CType *ctt = ctype_get(cp->cts, ctypeid);
|
|
946
|
+
CTInfo info;
|
|
947
|
+
CTSize size;
|
|
948
|
+
CPValue k;
|
|
949
|
+
CTypeID constid;
|
|
950
|
+
while (ctype_isattrib(ctt->info)) { /* Skip attributes. */
|
|
951
|
+
ctypeid = ctype_cid(ctt->info); /* Update ID, too. */
|
|
952
|
+
ctt = ctype_get(cp->cts, ctypeid);
|
|
953
|
+
}
|
|
954
|
+
info = ctt->info;
|
|
955
|
+
size = ctt->size;
|
|
956
|
+
if (!ctype_isinteger(info) || !(info & CTF_CONST) || size > 4)
|
|
957
|
+
cp_err(cp, LJ_ERR_FFI_INVTYPE);
|
|
958
|
+
cp_check(cp, '=');
|
|
959
|
+
cp_expr_sub(cp, &k, 0);
|
|
960
|
+
constid = lj_ctype_new(cp->cts, ctp);
|
|
961
|
+
(*ctp)->info = CTINFO(CT_CONSTVAL, CTF_CONST|ctypeid);
|
|
962
|
+
k.u32 <<= 8*(4-size);
|
|
963
|
+
if ((info & CTF_UNSIGNED))
|
|
964
|
+
k.u32 >>= 8*(4-size);
|
|
965
|
+
else
|
|
966
|
+
k.u32 = (uint32_t)((int32_t)k.u32 >> 8*(4-size));
|
|
967
|
+
(*ctp)->size = k.u32;
|
|
968
|
+
return constid;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
/* Parse size in parentheses as part of attribute. */
|
|
972
|
+
static CTSize cp_decl_sizeattr(CPState *cp)
|
|
973
|
+
{
|
|
974
|
+
CTSize sz;
|
|
975
|
+
uint32_t oldtmask = cp->tmask;
|
|
976
|
+
cp->tmask = CPNS_DEFAULT; /* Required for expression evaluator. */
|
|
977
|
+
cp_check(cp, '(');
|
|
978
|
+
sz = cp_expr_ksize(cp);
|
|
979
|
+
cp->tmask = oldtmask;
|
|
980
|
+
cp_check(cp, ')');
|
|
981
|
+
return sz;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
/* Parse alignment attribute. */
|
|
985
|
+
static void cp_decl_align(CPState *cp, CPDecl *decl)
|
|
986
|
+
{
|
|
987
|
+
CTSize al = 4; /* Unspecified alignment is 16 bytes. */
|
|
988
|
+
if (cp->tok == '(') {
|
|
989
|
+
al = cp_decl_sizeattr(cp);
|
|
990
|
+
al = al ? lj_fls(al) : 0;
|
|
991
|
+
}
|
|
992
|
+
CTF_INSERT(decl->attr, ALIGN, al);
|
|
993
|
+
decl->attr |= CTFP_ALIGNED;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
/* Parse GCC asm("name") redirect. */
|
|
997
|
+
static void cp_decl_asm(CPState *cp, CPDecl *decl)
|
|
998
|
+
{
|
|
999
|
+
UNUSED(decl);
|
|
1000
|
+
cp_next(cp);
|
|
1001
|
+
cp_check(cp, '(');
|
|
1002
|
+
if (cp->tok == CTOK_STRING) {
|
|
1003
|
+
GCstr *str = cp->str;
|
|
1004
|
+
while (cp_next(cp) == CTOK_STRING) {
|
|
1005
|
+
lj_strfmt_pushf(cp->L, "%s%s", strdata(str), strdata(cp->str));
|
|
1006
|
+
cp->L->top--;
|
|
1007
|
+
str = strV(cp->L->top);
|
|
1008
|
+
}
|
|
1009
|
+
decl->redir = str;
|
|
1010
|
+
}
|
|
1011
|
+
cp_check(cp, ')');
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
/* Parse GCC __attribute__((mode(...))). */
|
|
1015
|
+
static void cp_decl_mode(CPState *cp, CPDecl *decl)
|
|
1016
|
+
{
|
|
1017
|
+
cp_check(cp, '(');
|
|
1018
|
+
if (cp->tok == CTOK_IDENT) {
|
|
1019
|
+
const char *s = strdata(cp->str);
|
|
1020
|
+
CTSize sz = 0, vlen = 0;
|
|
1021
|
+
if (s[0] == '_' && s[1] == '_') s += 2;
|
|
1022
|
+
if (*s == 'V') {
|
|
1023
|
+
s++;
|
|
1024
|
+
vlen = *s++ - '0';
|
|
1025
|
+
if (*s >= '0' && *s <= '9')
|
|
1026
|
+
vlen = vlen*10 + (*s++ - '0');
|
|
1027
|
+
}
|
|
1028
|
+
switch (*s++) {
|
|
1029
|
+
case 'Q': sz = 1; break;
|
|
1030
|
+
case 'H': sz = 2; break;
|
|
1031
|
+
case 'S': sz = 4; break;
|
|
1032
|
+
case 'D': sz = 8; break;
|
|
1033
|
+
case 'T': sz = 16; break;
|
|
1034
|
+
case 'O': sz = 32; break;
|
|
1035
|
+
default: goto bad_size;
|
|
1036
|
+
}
|
|
1037
|
+
if (*s == 'I' || *s == 'F') {
|
|
1038
|
+
CTF_INSERT(decl->attr, MSIZEP, sz);
|
|
1039
|
+
if (vlen) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vlen*sz));
|
|
1040
|
+
}
|
|
1041
|
+
bad_size:
|
|
1042
|
+
cp_next(cp);
|
|
1043
|
+
}
|
|
1044
|
+
cp_check(cp, ')');
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
/* Parse GCC __attribute__((...)). */
|
|
1048
|
+
static void cp_decl_gccattribute(CPState *cp, CPDecl *decl)
|
|
1049
|
+
{
|
|
1050
|
+
cp_next(cp);
|
|
1051
|
+
cp_check(cp, '(');
|
|
1052
|
+
cp_check(cp, '(');
|
|
1053
|
+
while (cp->tok != ')') {
|
|
1054
|
+
if (cp->tok == CTOK_IDENT) {
|
|
1055
|
+
GCstr *attrstr = cp->str;
|
|
1056
|
+
cp_next(cp);
|
|
1057
|
+
switch (attrstr->hash) {
|
|
1058
|
+
case H_(64a9208e,8ce14319): case H_(8e6331b2,95a282af): /* aligned */
|
|
1059
|
+
cp_decl_align(cp, decl);
|
|
1060
|
+
break;
|
|
1061
|
+
case H_(42eb47de,f0ede26c): case H_(29f48a09,cf383e0c): /* packed */
|
|
1062
|
+
decl->attr |= CTFP_PACKED;
|
|
1063
|
+
break;
|
|
1064
|
+
case H_(0a84eef6,8dfab04c): case H_(995cf92c,d5696591): /* mode */
|
|
1065
|
+
cp_decl_mode(cp, decl);
|
|
1066
|
+
break;
|
|
1067
|
+
case H_(0ab31997,2d5213fa): case H_(bf875611,200e9990): /* vector_size */
|
|
1068
|
+
{
|
|
1069
|
+
CTSize vsize = cp_decl_sizeattr(cp);
|
|
1070
|
+
if (vsize) CTF_INSERT(decl->attr, VSIZEP, lj_fls(vsize));
|
|
1071
|
+
}
|
|
1072
|
+
break;
|
|
1073
|
+
#if LJ_TARGET_X86
|
|
1074
|
+
case H_(5ad22db8,c689b848): case H_(439150fa,65ea78cb): /* regparm */
|
|
1075
|
+
CTF_INSERT(decl->fattr, REGPARM, cp_decl_sizeattr(cp));
|
|
1076
|
+
decl->fattr |= CTFP_CCONV;
|
|
1077
|
+
break;
|
|
1078
|
+
case H_(18fc0b98,7ff4c074): case H_(4e62abed,0a747424): /* cdecl */
|
|
1079
|
+
CTF_INSERT(decl->fattr, CCONV, CTCC_CDECL);
|
|
1080
|
+
decl->fattr |= CTFP_CCONV;
|
|
1081
|
+
break;
|
|
1082
|
+
case H_(72b2e41b,494c5a44): case H_(f2356d59,f25fc9bd): /* thiscall */
|
|
1083
|
+
CTF_INSERT(decl->fattr, CCONV, CTCC_THISCALL);
|
|
1084
|
+
decl->fattr |= CTFP_CCONV;
|
|
1085
|
+
break;
|
|
1086
|
+
case H_(0d0ffc42,ab746f88): case H_(21c54ba1,7f0ca7e3): /* fastcall */
|
|
1087
|
+
CTF_INSERT(decl->fattr, CCONV, CTCC_FASTCALL);
|
|
1088
|
+
decl->fattr |= CTFP_CCONV;
|
|
1089
|
+
break;
|
|
1090
|
+
case H_(ef76b040,9412e06a): case H_(de56697b,c750e6e1): /* stdcall */
|
|
1091
|
+
CTF_INSERT(decl->fattr, CCONV, CTCC_STDCALL);
|
|
1092
|
+
decl->fattr |= CTFP_CCONV;
|
|
1093
|
+
break;
|
|
1094
|
+
case H_(ea78b622,f234bd8e): case H_(252ffb06,8d50f34b): /* sseregparm */
|
|
1095
|
+
decl->fattr |= CTF_SSEREGPARM;
|
|
1096
|
+
decl->fattr |= CTFP_CCONV;
|
|
1097
|
+
break;
|
|
1098
|
+
#endif
|
|
1099
|
+
default: /* Skip all other attributes. */
|
|
1100
|
+
goto skip_attr;
|
|
1101
|
+
}
|
|
1102
|
+
} else if (cp->tok >= CTOK_FIRSTDECL) { /* For __attribute((const)) etc. */
|
|
1103
|
+
cp_next(cp);
|
|
1104
|
+
skip_attr:
|
|
1105
|
+
if (cp_opt(cp, '(')) {
|
|
1106
|
+
while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp);
|
|
1107
|
+
cp_check(cp, ')');
|
|
1108
|
+
}
|
|
1109
|
+
} else {
|
|
1110
|
+
break;
|
|
1111
|
+
}
|
|
1112
|
+
if (!cp_opt(cp, ',')) break;
|
|
1113
|
+
}
|
|
1114
|
+
cp_check(cp, ')');
|
|
1115
|
+
cp_check(cp, ')');
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
/* Parse MSVC __declspec(...). */
|
|
1119
|
+
static void cp_decl_msvcattribute(CPState *cp, CPDecl *decl)
|
|
1120
|
+
{
|
|
1121
|
+
cp_next(cp);
|
|
1122
|
+
cp_check(cp, '(');
|
|
1123
|
+
while (cp->tok == CTOK_IDENT) {
|
|
1124
|
+
GCstr *attrstr = cp->str;
|
|
1125
|
+
cp_next(cp);
|
|
1126
|
+
switch (attrstr->hash) {
|
|
1127
|
+
case H_(bc2395fa,98f267f8): /* align */
|
|
1128
|
+
cp_decl_align(cp, decl);
|
|
1129
|
+
break;
|
|
1130
|
+
default: /* Ignore all other attributes. */
|
|
1131
|
+
if (cp_opt(cp, '(')) {
|
|
1132
|
+
while (cp->tok != ')' && cp->tok != CTOK_EOF) cp_next(cp);
|
|
1133
|
+
cp_check(cp, ')');
|
|
1134
|
+
}
|
|
1135
|
+
break;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
cp_check(cp, ')');
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
/* Parse declaration attributes (and common qualifiers). */
|
|
1142
|
+
static void cp_decl_attributes(CPState *cp, CPDecl *decl)
|
|
1143
|
+
{
|
|
1144
|
+
for (;;) {
|
|
1145
|
+
switch (cp->tok) {
|
|
1146
|
+
case CTOK_CONST: decl->attr |= CTF_CONST; break;
|
|
1147
|
+
case CTOK_VOLATILE: decl->attr |= CTF_VOLATILE; break;
|
|
1148
|
+
case CTOK_RESTRICT: break; /* Ignore. */
|
|
1149
|
+
case CTOK_EXTENSION: break; /* Ignore. */
|
|
1150
|
+
case CTOK_ATTRIBUTE: cp_decl_gccattribute(cp, decl); continue;
|
|
1151
|
+
case CTOK_ASM: cp_decl_asm(cp, decl); continue;
|
|
1152
|
+
case CTOK_DECLSPEC: cp_decl_msvcattribute(cp, decl); continue;
|
|
1153
|
+
case CTOK_CCDECL:
|
|
1154
|
+
#if LJ_TARGET_X86
|
|
1155
|
+
CTF_INSERT(decl->fattr, CCONV, cp->ct->size);
|
|
1156
|
+
decl->fattr |= CTFP_CCONV;
|
|
1157
|
+
#endif
|
|
1158
|
+
break;
|
|
1159
|
+
case CTOK_PTRSZ:
|
|
1160
|
+
#if LJ_64
|
|
1161
|
+
CTF_INSERT(decl->attr, MSIZEP, cp->ct->size);
|
|
1162
|
+
#endif
|
|
1163
|
+
break;
|
|
1164
|
+
default: return;
|
|
1165
|
+
}
|
|
1166
|
+
cp_next(cp);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
/* Parse struct/union/enum name. */
|
|
1171
|
+
static CTypeID cp_struct_name(CPState *cp, CPDecl *sdecl, CTInfo info)
|
|
1172
|
+
{
|
|
1173
|
+
CTypeID sid;
|
|
1174
|
+
CType *ct;
|
|
1175
|
+
cp->tmask = CPNS_STRUCT;
|
|
1176
|
+
cp_next(cp);
|
|
1177
|
+
cp_decl_attributes(cp, sdecl);
|
|
1178
|
+
cp->tmask = CPNS_DEFAULT;
|
|
1179
|
+
if (cp->tok != '{') {
|
|
1180
|
+
if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
|
|
1181
|
+
if (cp->val.id) { /* Name of existing struct/union/enum. */
|
|
1182
|
+
sid = cp->val.id;
|
|
1183
|
+
ct = cp->ct;
|
|
1184
|
+
if ((ct->info ^ info) & (CTMASK_NUM|CTF_UNION)) /* Wrong type. */
|
|
1185
|
+
cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(gco2str(gcref(ct->name))));
|
|
1186
|
+
} else { /* Create named, incomplete struct/union/enum. */
|
|
1187
|
+
if ((cp->mode & CPARSE_MODE_NOIMPLICIT))
|
|
1188
|
+
cp_errmsg(cp, 0, LJ_ERR_FFI_BADTAG, strdata(cp->str));
|
|
1189
|
+
sid = lj_ctype_new(cp->cts, &ct);
|
|
1190
|
+
ct->info = info;
|
|
1191
|
+
ct->size = CTSIZE_INVALID;
|
|
1192
|
+
ctype_setname(ct, cp->str);
|
|
1193
|
+
lj_ctype_addname(cp->cts, ct, sid);
|
|
1194
|
+
}
|
|
1195
|
+
cp_next(cp);
|
|
1196
|
+
} else { /* Create anonymous, incomplete struct/union/enum. */
|
|
1197
|
+
sid = lj_ctype_new(cp->cts, &ct);
|
|
1198
|
+
ct->info = info;
|
|
1199
|
+
ct->size = CTSIZE_INVALID;
|
|
1200
|
+
}
|
|
1201
|
+
if (cp->tok == '{') {
|
|
1202
|
+
if (ct->size != CTSIZE_INVALID || ct->sib)
|
|
1203
|
+
cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(gco2str(gcref(ct->name))));
|
|
1204
|
+
ct->sib = 1; /* Indicate the type is currently being defined. */
|
|
1205
|
+
}
|
|
1206
|
+
return sid;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
/* Determine field alignment. */
|
|
1210
|
+
static CTSize cp_field_align(CPState *cp, CType *ct, CTInfo info)
|
|
1211
|
+
{
|
|
1212
|
+
CTSize align = ctype_align(info);
|
|
1213
|
+
UNUSED(cp); UNUSED(ct);
|
|
1214
|
+
#if (LJ_TARGET_X86 && !LJ_ABI_WIN) || (LJ_TARGET_ARM && __APPLE__)
|
|
1215
|
+
/* The SYSV i386 and iOS ABIs limit alignment of non-vector fields to 2^2. */
|
|
1216
|
+
if (align > 2 && !(info & CTFP_ALIGNED)) {
|
|
1217
|
+
if (ctype_isarray(info) && !(info & CTF_VECTOR)) {
|
|
1218
|
+
do {
|
|
1219
|
+
ct = ctype_rawchild(cp->cts, ct);
|
|
1220
|
+
info = ct->info;
|
|
1221
|
+
} while (ctype_isarray(info) && !(info & CTF_VECTOR));
|
|
1222
|
+
}
|
|
1223
|
+
if (ctype_isnum(info) || ctype_isenum(info))
|
|
1224
|
+
align = 2;
|
|
1225
|
+
}
|
|
1226
|
+
#endif
|
|
1227
|
+
return align;
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
/* Layout struct/union fields. */
|
|
1231
|
+
static void cp_struct_layout(CPState *cp, CTypeID sid, CTInfo sattr)
|
|
1232
|
+
{
|
|
1233
|
+
CTSize bofs = 0, bmaxofs = 0; /* Bit offset and max. bit offset. */
|
|
1234
|
+
CTSize maxalign = ctype_align(sattr);
|
|
1235
|
+
CType *sct = ctype_get(cp->cts, sid);
|
|
1236
|
+
CTInfo sinfo = sct->info;
|
|
1237
|
+
CTypeID fieldid = sct->sib;
|
|
1238
|
+
while (fieldid) {
|
|
1239
|
+
CType *ct = ctype_get(cp->cts, fieldid);
|
|
1240
|
+
CTInfo attr = ct->size; /* Field declaration attributes (temp.). */
|
|
1241
|
+
|
|
1242
|
+
if (ctype_isfield(ct->info) ||
|
|
1243
|
+
(ctype_isxattrib(ct->info, CTA_SUBTYPE) && attr)) {
|
|
1244
|
+
CTSize align, amask; /* Alignment (pow2) and alignment mask (bits). */
|
|
1245
|
+
CTSize sz;
|
|
1246
|
+
CTInfo info = lj_ctype_info(cp->cts, ctype_cid(ct->info), &sz);
|
|
1247
|
+
CTSize bsz, csz = 8*sz; /* Field size and container size (in bits). */
|
|
1248
|
+
sinfo |= (info & (CTF_QUAL|CTF_VLA)); /* Merge pseudo-qualifiers. */
|
|
1249
|
+
|
|
1250
|
+
/* Check for size overflow and determine alignment. */
|
|
1251
|
+
if (sz >= 0x20000000u || bofs + csz < bofs || (info & CTF_VLA)) {
|
|
1252
|
+
if (!(sz == CTSIZE_INVALID && ctype_isarray(info) &&
|
|
1253
|
+
!(sinfo & CTF_UNION)))
|
|
1254
|
+
cp_err(cp, LJ_ERR_FFI_INVSIZE);
|
|
1255
|
+
csz = sz = 0; /* Treat a[] and a[?] as zero-sized. */
|
|
1256
|
+
}
|
|
1257
|
+
align = cp_field_align(cp, ct, info);
|
|
1258
|
+
if (((attr|sattr) & CTFP_PACKED) ||
|
|
1259
|
+
((attr & CTFP_ALIGNED) && ctype_align(attr) > align))
|
|
1260
|
+
align = ctype_align(attr);
|
|
1261
|
+
if (cp->packstack[cp->curpack] < align)
|
|
1262
|
+
align = cp->packstack[cp->curpack];
|
|
1263
|
+
if (align > maxalign) maxalign = align;
|
|
1264
|
+
amask = (8u << align) - 1;
|
|
1265
|
+
|
|
1266
|
+
bsz = ctype_bitcsz(ct->info); /* Bitfield size (temp.). */
|
|
1267
|
+
if (bsz == CTBSZ_FIELD || !ctype_isfield(ct->info)) {
|
|
1268
|
+
bsz = csz; /* Regular fields or subtypes always fill the container. */
|
|
1269
|
+
bofs = (bofs + amask) & ~amask; /* Start new aligned field. */
|
|
1270
|
+
ct->size = (bofs >> 3); /* Store field offset. */
|
|
1271
|
+
} else { /* Bitfield. */
|
|
1272
|
+
if (bsz == 0 || (attr & CTFP_ALIGNED) ||
|
|
1273
|
+
(!((attr|sattr) & CTFP_PACKED) && (bofs & amask) + bsz > csz))
|
|
1274
|
+
bofs = (bofs + amask) & ~amask; /* Start new aligned field. */
|
|
1275
|
+
|
|
1276
|
+
/* Prefer regular field over bitfield. */
|
|
1277
|
+
if (bsz == csz && (bofs & amask) == 0) {
|
|
1278
|
+
ct->info = CTINFO(CT_FIELD, ctype_cid(ct->info));
|
|
1279
|
+
ct->size = (bofs >> 3); /* Store field offset. */
|
|
1280
|
+
} else {
|
|
1281
|
+
ct->info = CTINFO(CT_BITFIELD,
|
|
1282
|
+
(info & (CTF_QUAL|CTF_UNSIGNED|CTF_BOOL)) +
|
|
1283
|
+
(csz << (CTSHIFT_BITCSZ-3)) + (bsz << CTSHIFT_BITBSZ));
|
|
1284
|
+
#if LJ_BE
|
|
1285
|
+
ct->info += ((csz - (bofs & (csz-1)) - bsz) << CTSHIFT_BITPOS);
|
|
1286
|
+
#else
|
|
1287
|
+
ct->info += ((bofs & (csz-1)) << CTSHIFT_BITPOS);
|
|
1288
|
+
#endif
|
|
1289
|
+
ct->size = ((bofs & ~(csz-1)) >> 3); /* Store container offset. */
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
/* Determine next offset or max. offset. */
|
|
1294
|
+
if ((sinfo & CTF_UNION)) {
|
|
1295
|
+
if (bsz > bmaxofs) bmaxofs = bsz;
|
|
1296
|
+
} else {
|
|
1297
|
+
bofs += bsz;
|
|
1298
|
+
}
|
|
1299
|
+
} /* All other fields in the chain are already set up. */
|
|
1300
|
+
|
|
1301
|
+
fieldid = ct->sib;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
/* Complete struct/union. */
|
|
1305
|
+
sct->info = sinfo + CTALIGN(maxalign);
|
|
1306
|
+
bofs = (sinfo & CTF_UNION) ? bmaxofs : bofs;
|
|
1307
|
+
maxalign = (8u << maxalign) - 1;
|
|
1308
|
+
sct->size = (((bofs + maxalign) & ~maxalign) >> 3);
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
/* Parse struct/union declaration. */
|
|
1312
|
+
static CTypeID cp_decl_struct(CPState *cp, CPDecl *sdecl, CTInfo sinfo)
|
|
1313
|
+
{
|
|
1314
|
+
CTypeID sid = cp_struct_name(cp, sdecl, sinfo);
|
|
1315
|
+
if (cp_opt(cp, '{')) { /* Struct/union definition. */
|
|
1316
|
+
CTypeID lastid = sid;
|
|
1317
|
+
int lastdecl = 0;
|
|
1318
|
+
while (cp->tok != '}') {
|
|
1319
|
+
CPDecl decl;
|
|
1320
|
+
CPscl scl = cp_decl_spec(cp, &decl, CDF_STATIC);
|
|
1321
|
+
decl.mode = scl ? CPARSE_MODE_DIRECT :
|
|
1322
|
+
CPARSE_MODE_DIRECT|CPARSE_MODE_ABSTRACT|CPARSE_MODE_FIELD;
|
|
1323
|
+
|
|
1324
|
+
for (;;) {
|
|
1325
|
+
CTypeID ctypeid;
|
|
1326
|
+
|
|
1327
|
+
if (lastdecl) cp_err_token(cp, '}');
|
|
1328
|
+
|
|
1329
|
+
/* Parse field declarator. */
|
|
1330
|
+
decl.bits = CTSIZE_INVALID;
|
|
1331
|
+
cp_declarator(cp, &decl);
|
|
1332
|
+
ctypeid = cp_decl_intern(cp, &decl);
|
|
1333
|
+
|
|
1334
|
+
if ((scl & CDF_STATIC)) { /* Static constant in struct namespace. */
|
|
1335
|
+
CType *ct;
|
|
1336
|
+
CTypeID fieldid = cp_decl_constinit(cp, &ct, ctypeid);
|
|
1337
|
+
ctype_get(cp->cts, lastid)->sib = fieldid;
|
|
1338
|
+
lastid = fieldid;
|
|
1339
|
+
ctype_setname(ct, decl.name);
|
|
1340
|
+
} else {
|
|
1341
|
+
CTSize bsz = CTBSZ_FIELD; /* Temp. for layout phase. */
|
|
1342
|
+
CType *ct;
|
|
1343
|
+
CTypeID fieldid = lj_ctype_new(cp->cts, &ct); /* Do this first. */
|
|
1344
|
+
CType *tct = ctype_raw(cp->cts, ctypeid);
|
|
1345
|
+
|
|
1346
|
+
if (decl.bits == CTSIZE_INVALID) { /* Regular field. */
|
|
1347
|
+
if (ctype_isarray(tct->info) && tct->size == CTSIZE_INVALID)
|
|
1348
|
+
lastdecl = 1; /* a[] or a[?] must be the last declared field. */
|
|
1349
|
+
|
|
1350
|
+
/* Accept transparent struct/union/enum. */
|
|
1351
|
+
if (!decl.name) {
|
|
1352
|
+
if (!((ctype_isstruct(tct->info) && !(tct->info & CTF_VLA)) ||
|
|
1353
|
+
ctype_isenum(tct->info)))
|
|
1354
|
+
cp_err_token(cp, CTOK_IDENT);
|
|
1355
|
+
ct->info = CTINFO(CT_ATTRIB, CTATTRIB(CTA_SUBTYPE) + ctypeid);
|
|
1356
|
+
ct->size = ctype_isstruct(tct->info) ?
|
|
1357
|
+
(decl.attr|0x80000000u) : 0; /* For layout phase. */
|
|
1358
|
+
goto add_field;
|
|
1359
|
+
}
|
|
1360
|
+
} else { /* Bitfield. */
|
|
1361
|
+
bsz = decl.bits;
|
|
1362
|
+
if (!ctype_isinteger_or_bool(tct->info) ||
|
|
1363
|
+
(bsz == 0 && decl.name) || 8*tct->size > CTBSZ_MAX ||
|
|
1364
|
+
bsz > ((tct->info & CTF_BOOL) ? 1 : 8*tct->size))
|
|
1365
|
+
cp_errmsg(cp, ':', LJ_ERR_BADVAL);
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
/* Create temporary field for layout phase. */
|
|
1369
|
+
ct->info = CTINFO(CT_FIELD, ctypeid + (bsz << CTSHIFT_BITCSZ));
|
|
1370
|
+
ct->size = decl.attr;
|
|
1371
|
+
if (decl.name) ctype_setname(ct, decl.name);
|
|
1372
|
+
|
|
1373
|
+
add_field:
|
|
1374
|
+
ctype_get(cp->cts, lastid)->sib = fieldid;
|
|
1375
|
+
lastid = fieldid;
|
|
1376
|
+
}
|
|
1377
|
+
if (!cp_opt(cp, ',')) break;
|
|
1378
|
+
cp_decl_reset(&decl);
|
|
1379
|
+
}
|
|
1380
|
+
cp_check(cp, ';');
|
|
1381
|
+
}
|
|
1382
|
+
cp_check(cp, '}');
|
|
1383
|
+
ctype_get(cp->cts, lastid)->sib = 0; /* Drop sib = 1 for empty structs. */
|
|
1384
|
+
cp_decl_attributes(cp, sdecl); /* Layout phase needs postfix attributes. */
|
|
1385
|
+
cp_struct_layout(cp, sid, sdecl->attr);
|
|
1386
|
+
}
|
|
1387
|
+
return sid;
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
/* Parse enum declaration. */
|
|
1391
|
+
static CTypeID cp_decl_enum(CPState *cp, CPDecl *sdecl)
|
|
1392
|
+
{
|
|
1393
|
+
CTypeID eid = cp_struct_name(cp, sdecl, CTINFO(CT_ENUM, CTID_VOID));
|
|
1394
|
+
CTInfo einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_UINT32);
|
|
1395
|
+
CTSize esize = 4; /* Only 32 bit enums are supported. */
|
|
1396
|
+
if (cp_opt(cp, '{')) { /* Enum definition. */
|
|
1397
|
+
CPValue k;
|
|
1398
|
+
CTypeID lastid = eid;
|
|
1399
|
+
k.u32 = 0;
|
|
1400
|
+
k.id = CTID_INT32;
|
|
1401
|
+
do {
|
|
1402
|
+
GCstr *name = cp->str;
|
|
1403
|
+
if (cp->tok != CTOK_IDENT) cp_err_token(cp, CTOK_IDENT);
|
|
1404
|
+
if (cp->val.id) cp_errmsg(cp, 0, LJ_ERR_FFI_REDEF, strdata(name));
|
|
1405
|
+
cp_next(cp);
|
|
1406
|
+
if (cp_opt(cp, '=')) {
|
|
1407
|
+
cp_expr_kint(cp, &k);
|
|
1408
|
+
if (k.id == CTID_UINT32) {
|
|
1409
|
+
/* C99 says that enum constants are always (signed) integers.
|
|
1410
|
+
** But since unsigned constants like 0x80000000 are quite common,
|
|
1411
|
+
** those are left as uint32_t.
|
|
1412
|
+
*/
|
|
1413
|
+
if (k.i32 >= 0) k.id = CTID_INT32;
|
|
1414
|
+
} else {
|
|
1415
|
+
/* OTOH it's common practice and even mandated by some ABIs
|
|
1416
|
+
** that the enum type itself is unsigned, unless there are any
|
|
1417
|
+
** negative constants.
|
|
1418
|
+
*/
|
|
1419
|
+
k.id = CTID_INT32;
|
|
1420
|
+
if (k.i32 < 0) einfo = CTINFO(CT_ENUM, CTALIGN(2) + CTID_INT32);
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
/* Add named enum constant. */
|
|
1424
|
+
{
|
|
1425
|
+
CType *ct;
|
|
1426
|
+
CTypeID constid = lj_ctype_new(cp->cts, &ct);
|
|
1427
|
+
ctype_get(cp->cts, lastid)->sib = constid;
|
|
1428
|
+
lastid = constid;
|
|
1429
|
+
ctype_setname(ct, name);
|
|
1430
|
+
ct->info = CTINFO(CT_CONSTVAL, CTF_CONST|k.id);
|
|
1431
|
+
ct->size = k.u32++;
|
|
1432
|
+
if (k.u32 == 0x80000000u) k.id = CTID_UINT32;
|
|
1433
|
+
lj_ctype_addname(cp->cts, ct, constid);
|
|
1434
|
+
}
|
|
1435
|
+
if (!cp_opt(cp, ',')) break;
|
|
1436
|
+
} while (cp->tok != '}'); /* Trailing ',' is ok. */
|
|
1437
|
+
cp_check(cp, '}');
|
|
1438
|
+
/* Complete enum. */
|
|
1439
|
+
ctype_get(cp->cts, eid)->info = einfo;
|
|
1440
|
+
ctype_get(cp->cts, eid)->size = esize;
|
|
1441
|
+
}
|
|
1442
|
+
return eid;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
/* Parse declaration specifiers. */
|
|
1446
|
+
static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl)
|
|
1447
|
+
{
|
|
1448
|
+
uint32_t cds = 0, sz = 0;
|
|
1449
|
+
CTypeID tdef = 0;
|
|
1450
|
+
|
|
1451
|
+
decl->cp = cp;
|
|
1452
|
+
decl->mode = cp->mode;
|
|
1453
|
+
decl->name = NULL;
|
|
1454
|
+
decl->redir = NULL;
|
|
1455
|
+
decl->attr = 0;
|
|
1456
|
+
decl->fattr = 0;
|
|
1457
|
+
decl->pos = decl->top = 0;
|
|
1458
|
+
decl->stack[0].next = 0;
|
|
1459
|
+
|
|
1460
|
+
for (;;) { /* Parse basic types. */
|
|
1461
|
+
cp_decl_attributes(cp, decl);
|
|
1462
|
+
if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECLFLAG) {
|
|
1463
|
+
uint32_t cbit;
|
|
1464
|
+
if (cp->ct->size) {
|
|
1465
|
+
if (sz) goto end_decl;
|
|
1466
|
+
sz = cp->ct->size;
|
|
1467
|
+
}
|
|
1468
|
+
cbit = (1u << (cp->tok - CTOK_FIRSTDECL));
|
|
1469
|
+
cds = cds | cbit | ((cbit & cds & CDF_LONG) << 1);
|
|
1470
|
+
if (cp->tok >= CTOK_FIRSTSCL) {
|
|
1471
|
+
if (!(scl & cbit)) cp_errmsg(cp, cp->tok, LJ_ERR_FFI_BADSCL);
|
|
1472
|
+
} else if (tdef) {
|
|
1473
|
+
goto end_decl;
|
|
1474
|
+
}
|
|
1475
|
+
cp_next(cp);
|
|
1476
|
+
continue;
|
|
1477
|
+
}
|
|
1478
|
+
if (sz || tdef ||
|
|
1479
|
+
(cds & (CDF_SHORT|CDF_LONG|CDF_SIGNED|CDF_UNSIGNED|CDF_COMPLEX)))
|
|
1480
|
+
break;
|
|
1481
|
+
switch (cp->tok) {
|
|
1482
|
+
case CTOK_STRUCT:
|
|
1483
|
+
tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, 0));
|
|
1484
|
+
continue;
|
|
1485
|
+
case CTOK_UNION:
|
|
1486
|
+
tdef = cp_decl_struct(cp, decl, CTINFO(CT_STRUCT, CTF_UNION));
|
|
1487
|
+
continue;
|
|
1488
|
+
case CTOK_ENUM:
|
|
1489
|
+
tdef = cp_decl_enum(cp, decl);
|
|
1490
|
+
continue;
|
|
1491
|
+
case CTOK_IDENT:
|
|
1492
|
+
if (ctype_istypedef(cp->ct->info)) {
|
|
1493
|
+
tdef = ctype_cid(cp->ct->info); /* Get typedef. */
|
|
1494
|
+
cp_next(cp);
|
|
1495
|
+
continue;
|
|
1496
|
+
}
|
|
1497
|
+
break;
|
|
1498
|
+
case '$':
|
|
1499
|
+
tdef = cp->val.id;
|
|
1500
|
+
cp_next(cp);
|
|
1501
|
+
continue;
|
|
1502
|
+
default:
|
|
1503
|
+
break;
|
|
1504
|
+
}
|
|
1505
|
+
break;
|
|
1506
|
+
}
|
|
1507
|
+
end_decl:
|
|
1508
|
+
|
|
1509
|
+
if ((cds & CDF_COMPLEX)) /* Use predefined complex types. */
|
|
1510
|
+
tdef = sz == 4 ? CTID_COMPLEX_FLOAT : CTID_COMPLEX_DOUBLE;
|
|
1511
|
+
|
|
1512
|
+
if (tdef) {
|
|
1513
|
+
cp_push_type(decl, tdef);
|
|
1514
|
+
} else if ((cds & CDF_VOID)) {
|
|
1515
|
+
cp_push(decl, CTINFO(CT_VOID, (decl->attr & CTF_QUAL)), CTSIZE_INVALID);
|
|
1516
|
+
decl->attr &= ~CTF_QUAL;
|
|
1517
|
+
} else {
|
|
1518
|
+
/* Determine type info and size. */
|
|
1519
|
+
CTInfo info = CTINFO(CT_NUM, (cds & CDF_UNSIGNED) ? CTF_UNSIGNED : 0);
|
|
1520
|
+
if ((cds & CDF_BOOL)) {
|
|
1521
|
+
if ((cds & ~(CDF_SCL|CDF_BOOL|CDF_INT|CDF_SIGNED|CDF_UNSIGNED)))
|
|
1522
|
+
cp_errmsg(cp, 0, LJ_ERR_FFI_INVTYPE);
|
|
1523
|
+
info |= CTF_BOOL;
|
|
1524
|
+
if (!(cds & CDF_SIGNED)) info |= CTF_UNSIGNED;
|
|
1525
|
+
if (!sz) {
|
|
1526
|
+
sz = 1;
|
|
1527
|
+
}
|
|
1528
|
+
} else if ((cds & CDF_FP)) {
|
|
1529
|
+
info = CTINFO(CT_NUM, CTF_FP);
|
|
1530
|
+
if ((cds & CDF_LONG)) sz = sizeof(long double);
|
|
1531
|
+
} else if ((cds & CDF_CHAR)) {
|
|
1532
|
+
if ((cds & (CDF_CHAR|CDF_SIGNED|CDF_UNSIGNED)) == CDF_CHAR)
|
|
1533
|
+
info |= CTF_UCHAR; /* Handle platforms where char is unsigned. */
|
|
1534
|
+
} else if ((cds & CDF_SHORT)) {
|
|
1535
|
+
sz = sizeof(short);
|
|
1536
|
+
} else if ((cds & CDF_LONGLONG)) {
|
|
1537
|
+
sz = 8;
|
|
1538
|
+
} else if ((cds & CDF_LONG)) {
|
|
1539
|
+
info |= CTF_LONG;
|
|
1540
|
+
sz = sizeof(long);
|
|
1541
|
+
} else if (!sz) {
|
|
1542
|
+
if (!(cds & (CDF_SIGNED|CDF_UNSIGNED)))
|
|
1543
|
+
cp_errmsg(cp, cp->tok, LJ_ERR_FFI_DECLSPEC);
|
|
1544
|
+
sz = sizeof(int);
|
|
1545
|
+
}
|
|
1546
|
+
lua_assert(sz != 0);
|
|
1547
|
+
info += CTALIGN(lj_fls(sz)); /* Use natural alignment. */
|
|
1548
|
+
info += (decl->attr & CTF_QUAL); /* Merge qualifiers. */
|
|
1549
|
+
cp_push(decl, info, sz);
|
|
1550
|
+
decl->attr &= ~CTF_QUAL;
|
|
1551
|
+
}
|
|
1552
|
+
decl->specpos = decl->pos;
|
|
1553
|
+
decl->specattr = decl->attr;
|
|
1554
|
+
decl->specfattr = decl->fattr;
|
|
1555
|
+
return (cds & CDF_SCL); /* Return storage class. */
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
/* Parse array declaration. */
|
|
1559
|
+
static void cp_decl_array(CPState *cp, CPDecl *decl)
|
|
1560
|
+
{
|
|
1561
|
+
CTInfo info = CTINFO(CT_ARRAY, 0);
|
|
1562
|
+
CTSize nelem = CTSIZE_INVALID; /* Default size for a[] or a[?]. */
|
|
1563
|
+
cp_decl_attributes(cp, decl);
|
|
1564
|
+
if (cp_opt(cp, '?'))
|
|
1565
|
+
info |= CTF_VLA; /* Create variable-length array a[?]. */
|
|
1566
|
+
else if (cp->tok != ']')
|
|
1567
|
+
nelem = cp_expr_ksize(cp);
|
|
1568
|
+
cp_check(cp, ']');
|
|
1569
|
+
cp_add(decl, info, nelem);
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
/* Parse function declaration. */
|
|
1573
|
+
static void cp_decl_func(CPState *cp, CPDecl *fdecl)
|
|
1574
|
+
{
|
|
1575
|
+
CTSize nargs = 0;
|
|
1576
|
+
CTInfo info = CTINFO(CT_FUNC, 0);
|
|
1577
|
+
CTypeID lastid = 0, anchor = 0;
|
|
1578
|
+
if (cp->tok != ')') {
|
|
1579
|
+
do {
|
|
1580
|
+
CPDecl decl;
|
|
1581
|
+
CTypeID ctypeid, fieldid;
|
|
1582
|
+
CType *ct;
|
|
1583
|
+
if (cp_opt(cp, '.')) { /* Vararg function. */
|
|
1584
|
+
cp_check(cp, '.'); /* Workaround for the minimalistic lexer. */
|
|
1585
|
+
cp_check(cp, '.');
|
|
1586
|
+
info |= CTF_VARARG;
|
|
1587
|
+
break;
|
|
1588
|
+
}
|
|
1589
|
+
cp_decl_spec(cp, &decl, CDF_REGISTER);
|
|
1590
|
+
decl.mode = CPARSE_MODE_DIRECT|CPARSE_MODE_ABSTRACT;
|
|
1591
|
+
cp_declarator(cp, &decl);
|
|
1592
|
+
ctypeid = cp_decl_intern(cp, &decl);
|
|
1593
|
+
ct = ctype_raw(cp->cts, ctypeid);
|
|
1594
|
+
if (ctype_isvoid(ct->info))
|
|
1595
|
+
break;
|
|
1596
|
+
else if (ctype_isrefarray(ct->info))
|
|
1597
|
+
ctypeid = lj_ctype_intern(cp->cts,
|
|
1598
|
+
CTINFO(CT_PTR, CTALIGN_PTR|ctype_cid(ct->info)), CTSIZE_PTR);
|
|
1599
|
+
else if (ctype_isfunc(ct->info))
|
|
1600
|
+
ctypeid = lj_ctype_intern(cp->cts,
|
|
1601
|
+
CTINFO(CT_PTR, CTALIGN_PTR|ctypeid), CTSIZE_PTR);
|
|
1602
|
+
/* Add new parameter. */
|
|
1603
|
+
fieldid = lj_ctype_new(cp->cts, &ct);
|
|
1604
|
+
if (anchor)
|
|
1605
|
+
ctype_get(cp->cts, lastid)->sib = fieldid;
|
|
1606
|
+
else
|
|
1607
|
+
anchor = fieldid;
|
|
1608
|
+
lastid = fieldid;
|
|
1609
|
+
if (decl.name) ctype_setname(ct, decl.name);
|
|
1610
|
+
ct->info = CTINFO(CT_FIELD, ctypeid);
|
|
1611
|
+
ct->size = nargs++;
|
|
1612
|
+
} while (cp_opt(cp, ','));
|
|
1613
|
+
}
|
|
1614
|
+
cp_check(cp, ')');
|
|
1615
|
+
if (cp_opt(cp, '{')) { /* Skip function definition. */
|
|
1616
|
+
int level = 1;
|
|
1617
|
+
cp->mode |= CPARSE_MODE_SKIP;
|
|
1618
|
+
for (;;) {
|
|
1619
|
+
if (cp->tok == '{') level++;
|
|
1620
|
+
else if (cp->tok == '}' && --level == 0) break;
|
|
1621
|
+
else if (cp->tok == CTOK_EOF) cp_err_token(cp, '}');
|
|
1622
|
+
cp_next(cp);
|
|
1623
|
+
}
|
|
1624
|
+
cp->mode &= ~CPARSE_MODE_SKIP;
|
|
1625
|
+
cp->tok = ';'; /* Ok for cp_decl_multi(), error in cp_decl_single(). */
|
|
1626
|
+
}
|
|
1627
|
+
info |= (fdecl->fattr & ~CTMASK_CID);
|
|
1628
|
+
fdecl->fattr = 0;
|
|
1629
|
+
fdecl->stack[cp_add(fdecl, info, nargs)].sib = anchor;
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
/* Parse declarator. */
|
|
1633
|
+
static void cp_declarator(CPState *cp, CPDecl *decl)
|
|
1634
|
+
{
|
|
1635
|
+
if (++cp->depth > CPARSE_MAX_DECLDEPTH) cp_err(cp, LJ_ERR_XLEVELS);
|
|
1636
|
+
|
|
1637
|
+
for (;;) { /* Head of declarator. */
|
|
1638
|
+
if (cp_opt(cp, '*')) { /* Pointer. */
|
|
1639
|
+
CTSize sz;
|
|
1640
|
+
CTInfo info;
|
|
1641
|
+
cp_decl_attributes(cp, decl);
|
|
1642
|
+
sz = CTSIZE_PTR;
|
|
1643
|
+
info = CTINFO(CT_PTR, CTALIGN_PTR);
|
|
1644
|
+
#if LJ_64
|
|
1645
|
+
if (ctype_msizeP(decl->attr) == 4) {
|
|
1646
|
+
sz = 4;
|
|
1647
|
+
info = CTINFO(CT_PTR, CTALIGN(2));
|
|
1648
|
+
}
|
|
1649
|
+
#endif
|
|
1650
|
+
info += (decl->attr & (CTF_QUAL|CTF_REF));
|
|
1651
|
+
decl->attr &= ~(CTF_QUAL|(CTMASK_MSIZEP<<CTSHIFT_MSIZEP));
|
|
1652
|
+
cp_push(decl, info, sz);
|
|
1653
|
+
} else if (cp_opt(cp, '&') || cp_opt(cp, CTOK_ANDAND)) { /* Reference. */
|
|
1654
|
+
decl->attr &= ~(CTF_QUAL|(CTMASK_MSIZEP<<CTSHIFT_MSIZEP));
|
|
1655
|
+
cp_push(decl, CTINFO_REF(0), CTSIZE_PTR);
|
|
1656
|
+
} else {
|
|
1657
|
+
break;
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
if (cp_opt(cp, '(')) { /* Inner declarator. */
|
|
1662
|
+
CPDeclIdx pos;
|
|
1663
|
+
cp_decl_attributes(cp, decl);
|
|
1664
|
+
/* Resolve ambiguity between inner declarator and 1st function parameter. */
|
|
1665
|
+
if ((decl->mode & CPARSE_MODE_ABSTRACT) &&
|
|
1666
|
+
(cp->tok == ')' || cp_istypedecl(cp))) goto func_decl;
|
|
1667
|
+
pos = decl->pos;
|
|
1668
|
+
cp_declarator(cp, decl);
|
|
1669
|
+
cp_check(cp, ')');
|
|
1670
|
+
decl->pos = pos;
|
|
1671
|
+
} else if (cp->tok == CTOK_IDENT) { /* Direct declarator. */
|
|
1672
|
+
if (!(decl->mode & CPARSE_MODE_DIRECT)) cp_err_token(cp, CTOK_EOF);
|
|
1673
|
+
decl->name = cp->str;
|
|
1674
|
+
decl->nameid = cp->val.id;
|
|
1675
|
+
cp_next(cp);
|
|
1676
|
+
} else { /* Abstract declarator. */
|
|
1677
|
+
if (!(decl->mode & CPARSE_MODE_ABSTRACT)) cp_err_token(cp, CTOK_IDENT);
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
for (;;) { /* Tail of declarator. */
|
|
1681
|
+
if (cp_opt(cp, '[')) { /* Array. */
|
|
1682
|
+
cp_decl_array(cp, decl);
|
|
1683
|
+
} else if (cp_opt(cp, '(')) { /* Function. */
|
|
1684
|
+
func_decl:
|
|
1685
|
+
cp_decl_func(cp, decl);
|
|
1686
|
+
} else {
|
|
1687
|
+
break;
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
if ((decl->mode & CPARSE_MODE_FIELD) && cp_opt(cp, ':')) /* Field width. */
|
|
1692
|
+
decl->bits = cp_expr_ksize(cp);
|
|
1693
|
+
|
|
1694
|
+
/* Process postfix attributes. */
|
|
1695
|
+
cp_decl_attributes(cp, decl);
|
|
1696
|
+
cp_push_attributes(decl);
|
|
1697
|
+
|
|
1698
|
+
cp->depth--;
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
/* Parse an abstract type declaration and return it's C type ID. */
|
|
1702
|
+
static CTypeID cp_decl_abstract(CPState *cp)
|
|
1703
|
+
{
|
|
1704
|
+
CPDecl decl;
|
|
1705
|
+
cp_decl_spec(cp, &decl, 0);
|
|
1706
|
+
decl.mode = CPARSE_MODE_ABSTRACT;
|
|
1707
|
+
cp_declarator(cp, &decl);
|
|
1708
|
+
return cp_decl_intern(cp, &decl);
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
/* Handle pragmas. */
|
|
1712
|
+
static void cp_pragma(CPState *cp, BCLine pragmaline)
|
|
1713
|
+
{
|
|
1714
|
+
cp_next(cp);
|
|
1715
|
+
if (cp->tok == CTOK_IDENT &&
|
|
1716
|
+
cp->str->hash == H_(e79b999f,42ca3e85)) { /* pack */
|
|
1717
|
+
cp_next(cp);
|
|
1718
|
+
cp_check(cp, '(');
|
|
1719
|
+
if (cp->tok == CTOK_IDENT) {
|
|
1720
|
+
if (cp->str->hash == H_(738e923c,a1b65954)) { /* push */
|
|
1721
|
+
if (cp->curpack < CPARSE_MAX_PACKSTACK) {
|
|
1722
|
+
cp->packstack[cp->curpack+1] = cp->packstack[cp->curpack];
|
|
1723
|
+
cp->curpack++;
|
|
1724
|
+
}
|
|
1725
|
+
} else if (cp->str->hash == H_(6c71cf27,6c71cf27)) { /* pop */
|
|
1726
|
+
if (cp->curpack > 0) cp->curpack--;
|
|
1727
|
+
} else {
|
|
1728
|
+
cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
|
|
1729
|
+
}
|
|
1730
|
+
cp_next(cp);
|
|
1731
|
+
if (!cp_opt(cp, ',')) goto end_pack;
|
|
1732
|
+
}
|
|
1733
|
+
if (cp->tok == CTOK_INTEGER) {
|
|
1734
|
+
cp->packstack[cp->curpack] = cp->val.u32 ? lj_fls(cp->val.u32) : 0;
|
|
1735
|
+
cp_next(cp);
|
|
1736
|
+
} else {
|
|
1737
|
+
cp->packstack[cp->curpack] = 255;
|
|
1738
|
+
}
|
|
1739
|
+
end_pack:
|
|
1740
|
+
cp_check(cp, ')');
|
|
1741
|
+
} else { /* Ignore all other pragmas. */
|
|
1742
|
+
while (cp->tok != CTOK_EOF && cp->linenumber == pragmaline)
|
|
1743
|
+
cp_next(cp);
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
/* Parse multiple C declarations of types or extern identifiers. */
|
|
1748
|
+
static void cp_decl_multi(CPState *cp)
|
|
1749
|
+
{
|
|
1750
|
+
int first = 1;
|
|
1751
|
+
while (cp->tok != CTOK_EOF) {
|
|
1752
|
+
CPDecl decl;
|
|
1753
|
+
CPscl scl;
|
|
1754
|
+
if (cp_opt(cp, ';')) { /* Skip empty statements. */
|
|
1755
|
+
first = 0;
|
|
1756
|
+
continue;
|
|
1757
|
+
}
|
|
1758
|
+
if (cp->tok == '#') { /* Workaround, since we have no preprocessor, yet. */
|
|
1759
|
+
BCLine pragmaline = cp->linenumber;
|
|
1760
|
+
if (!(cp_next(cp) == CTOK_IDENT &&
|
|
1761
|
+
cp->str->hash == H_(f5e6b4f8,1d509107))) /* pragma */
|
|
1762
|
+
cp_errmsg(cp, cp->tok, LJ_ERR_XSYMBOL);
|
|
1763
|
+
cp_pragma(cp, pragmaline);
|
|
1764
|
+
continue;
|
|
1765
|
+
}
|
|
1766
|
+
scl = cp_decl_spec(cp, &decl, CDF_TYPEDEF|CDF_EXTERN|CDF_STATIC);
|
|
1767
|
+
if ((cp->tok == ';' || cp->tok == CTOK_EOF) &&
|
|
1768
|
+
ctype_istypedef(decl.stack[0].info)) {
|
|
1769
|
+
CTInfo info = ctype_rawchild(cp->cts, &decl.stack[0])->info;
|
|
1770
|
+
if (ctype_isstruct(info) || ctype_isenum(info))
|
|
1771
|
+
goto decl_end; /* Accept empty declaration of struct/union/enum. */
|
|
1772
|
+
}
|
|
1773
|
+
for (;;) {
|
|
1774
|
+
CTypeID ctypeid;
|
|
1775
|
+
cp_declarator(cp, &decl);
|
|
1776
|
+
ctypeid = cp_decl_intern(cp, &decl);
|
|
1777
|
+
if (decl.name && !decl.nameid) { /* NYI: redeclarations are ignored. */
|
|
1778
|
+
CType *ct;
|
|
1779
|
+
CTypeID id;
|
|
1780
|
+
if ((scl & CDF_TYPEDEF)) { /* Create new typedef. */
|
|
1781
|
+
id = lj_ctype_new(cp->cts, &ct);
|
|
1782
|
+
ct->info = CTINFO(CT_TYPEDEF, ctypeid);
|
|
1783
|
+
goto noredir;
|
|
1784
|
+
} else if (ctype_isfunc(ctype_get(cp->cts, ctypeid)->info)) {
|
|
1785
|
+
/* Treat both static and extern function declarations as extern. */
|
|
1786
|
+
ct = ctype_get(cp->cts, ctypeid);
|
|
1787
|
+
/* We always get new anonymous functions (typedefs are copied). */
|
|
1788
|
+
lua_assert(gcref(ct->name) == NULL);
|
|
1789
|
+
id = ctypeid; /* Just name it. */
|
|
1790
|
+
} else if ((scl & CDF_STATIC)) { /* Accept static constants. */
|
|
1791
|
+
id = cp_decl_constinit(cp, &ct, ctypeid);
|
|
1792
|
+
goto noredir;
|
|
1793
|
+
} else { /* External references have extern or no storage class. */
|
|
1794
|
+
id = lj_ctype_new(cp->cts, &ct);
|
|
1795
|
+
ct->info = CTINFO(CT_EXTERN, ctypeid);
|
|
1796
|
+
}
|
|
1797
|
+
if (decl.redir) { /* Add attribute for redirected symbol name. */
|
|
1798
|
+
CType *cta;
|
|
1799
|
+
CTypeID aid = lj_ctype_new(cp->cts, &cta);
|
|
1800
|
+
ct = ctype_get(cp->cts, id); /* Table may have been reallocated. */
|
|
1801
|
+
cta->info = CTINFO(CT_ATTRIB, CTATTRIB(CTA_REDIR));
|
|
1802
|
+
cta->sib = ct->sib;
|
|
1803
|
+
ct->sib = aid;
|
|
1804
|
+
ctype_setname(cta, decl.redir);
|
|
1805
|
+
}
|
|
1806
|
+
noredir:
|
|
1807
|
+
ctype_setname(ct, decl.name);
|
|
1808
|
+
lj_ctype_addname(cp->cts, ct, id);
|
|
1809
|
+
}
|
|
1810
|
+
if (!cp_opt(cp, ',')) break;
|
|
1811
|
+
cp_decl_reset(&decl);
|
|
1812
|
+
}
|
|
1813
|
+
decl_end:
|
|
1814
|
+
if (cp->tok == CTOK_EOF && first) break; /* May omit ';' for 1 decl. */
|
|
1815
|
+
first = 0;
|
|
1816
|
+
cp_check(cp, ';');
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
/* Parse a single C type declaration. */
|
|
1821
|
+
static void cp_decl_single(CPState *cp)
|
|
1822
|
+
{
|
|
1823
|
+
CPDecl decl;
|
|
1824
|
+
cp_decl_spec(cp, &decl, 0);
|
|
1825
|
+
cp_declarator(cp, &decl);
|
|
1826
|
+
cp->val.id = cp_decl_intern(cp, &decl);
|
|
1827
|
+
if (cp->tok != CTOK_EOF) cp_err_token(cp, CTOK_EOF);
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
#undef H_
|
|
1831
|
+
|
|
1832
|
+
/* ------------------------------------------------------------------------ */
|
|
1833
|
+
|
|
1834
|
+
/* Protected callback for C parser. */
|
|
1835
|
+
static TValue *cpcparser(lua_State *L, lua_CFunction dummy, void *ud)
|
|
1836
|
+
{
|
|
1837
|
+
CPState *cp = (CPState *)ud;
|
|
1838
|
+
UNUSED(dummy);
|
|
1839
|
+
cframe_errfunc(L->cframe) = -1; /* Inherit error function. */
|
|
1840
|
+
cp_init(cp);
|
|
1841
|
+
if ((cp->mode & CPARSE_MODE_MULTI))
|
|
1842
|
+
cp_decl_multi(cp);
|
|
1843
|
+
else
|
|
1844
|
+
cp_decl_single(cp);
|
|
1845
|
+
if (cp->param && cp->param != cp->L->top)
|
|
1846
|
+
cp_err(cp, LJ_ERR_FFI_NUMPARAM);
|
|
1847
|
+
lua_assert(cp->depth == 0);
|
|
1848
|
+
return NULL;
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
/* C parser. */
|
|
1852
|
+
int lj_cparse(CPState *cp)
|
|
1853
|
+
{
|
|
1854
|
+
LJ_CTYPE_SAVE(cp->cts);
|
|
1855
|
+
int errcode = lj_vm_cpcall(cp->L, NULL, cp, cpcparser);
|
|
1856
|
+
if (errcode)
|
|
1857
|
+
LJ_CTYPE_RESTORE(cp->cts);
|
|
1858
|
+
cp_cleanup(cp);
|
|
1859
|
+
return errcode;
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
#endif
|