├── .gitignore ├── .travis.yml ├── README.md ├── ffiex-0.2.0-8.rockspec ├── ffiex ├── builder │ ├── gcc.lua │ └── tcc.lua ├── cache │ └── .gitkeep ├── init.lua ├── lcpp.lua ├── parser.lua └── util.lua ├── install.sh ├── install_test.lua ├── launch.lua ├── test.lua ├── test ├── cache.lua ├── cast.lua ├── concat.lua ├── deref.lua ├── expr.lua ├── ffiex.lua ├── ffiex_csrc.lua_ ├── foo.c ├── gcc.lua ├── import.lua ├── import2.lua ├── import3.lua ├── import4.lua ├── lcpp.lua ├── ljtype.lua ├── macro.lua ├── myheaders │ ├── my.h │ ├── pdcurses.h │ └── tcc │ │ ├── README.md │ │ ├── float.h │ │ ├── libtcc.h │ │ ├── stdarg.h │ │ ├── stdbool.h │ │ ├── stddef.h │ │ ├── stdint.h │ │ ├── stdio.h │ │ ├── tcclib.h │ │ └── varargs.h ├── parseheaders.lua ├── parser.lua ├── parser.lua_ ├── pdcurses.lua ├── state.lua └── tcc.lua ├── tmp └── .gitkeep └── travis_install.sh /.gitignore: -------------------------------------------------------------------------------- 1 | ffiex/cache/* 2 | tmp/*.h 3 | **/.DS_Store 4 | .DS_Store 5 | a.out 6 | *.c 7 | tmp.txt 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: lua 2 | 3 | env: 4 | - LUA="" 5 | - LUA="luajit" 6 | 7 | compiler: 8 | - gcc 9 | 10 | before_script: 11 | - sudo mkdir -p /usr/local/share/lua/5.1/ 12 | - sudo chmod -R 777 /usr/local 13 | 14 | script: "sudo bash travis_install.sh && luajit test.lua && sudo bash install.sh" 15 | 16 | branches: 17 | only: 18 | - master 19 | - feature/travis_ci 20 | 21 | install: 22 | - sudo apt-get install -y luarocks 23 | 24 | notifications: 25 | recipients: 26 | - iyatomi+ffiex.test@gmail.com 27 | email: 28 | on_success: change 29 | on_failure: always 30 | 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/umegaya/ffiex.png?branch=master)](https://travis-ci.org/umegaya/ffiex) 2 | 3 | ffiex 4 | ===== 5 | 6 | - extend luajit ffi module to give more affinity to C codes 7 | - can #include typical system C headers (no more manual C definition injection) 8 | - enable to use C sources without pre-build it. 9 | - caution : there is no official support for windows related OS. 10 | 11 | 12 | install 13 | ======= 14 | 15 | - prerequisity 16 | - gcc or tcc (if you want to use csrc API) 17 | - for instance tcc installation, run travis_install.sh at top of this repo. 18 | - clone this repo and run 19 | ``` bash 20 | sudo bash install.sh 21 | ``` 22 | - or you can use [*moonrocks*](http://rocks.moonscript.org/) 23 | ``` bash 24 | moonrocks install ffiex 25 | ``` 26 | 27 | 28 | usage 29 | ===== 30 | 31 | - just replace 1 line where you use luajit ffi module. 32 | ``` lua 33 | local ffi = requie 'ffiex' 34 | ``` 35 | 36 | 37 | update logs 38 | =========== 39 | #### 0.2.0 40 | - [ffi.import(symbols):from(code)](https://github.com/umegaya/ffiex#ffieximportsymbolstablefromcodestring) to support selective cdef from header files 41 | - ffiex.csrc's build backend now pluggable, limited support for tcc (linux only) 42 | - [ffi.newstate()](https://github.com/umegaya/ffiex#stateffi_state--ffiexnewstate) to create isolated parse state object which has its own include search path, macro cache, cdef dependency cache. 43 | - mainly for module writers who want to avoid polluting main ffiex's parsing state by cdef'ing some own header file or adding header search path of module own. 44 | - major refactoring 45 | 46 | #### 0.1.0 47 | - initial release 48 | 49 | 50 | APIs 51 | ==== 52 | 53 | ### ffiex.cdef(input:string) 54 | - same as original ffi.cdef but it apply C preprocessor to input text. yes, not only concept but also source code is based on lcpp (https://github.com/willsteel/lcpp), but do more. lcpp have some flaw when its used for parsing practical header like under /usr/include/, lcpp.lua used in ffiex is originally from lcpp project, but re-written widely so that it able to parse most of header files under /usr/include/*.h (see test/parseheaders.lua. its tested with OSX 10.9, CentOS 6.4, Ubuntu 12.04(travis-CI)). 55 | 56 | ### ffiex.path(path:string, system_path:boolean) 57 | - add header file search path which is used to find #include files by ffiex.cdef. ffiex initializes system header search path and pre-defined macro symbols from following commands 58 | 59 | ``` bash 60 | echo | gcc -v -xc - # search paths 61 | echo | gcc -E -dM - # predefined macros 62 | ``` 63 | 64 | - so you don't need to specify system header search path in gcc-enabled environment. but if gcc-less or need to add search path for your original header files, you can add other search paths like following: 65 | ``` lua 66 | ffi.path("/usr/local/additional_system_headers/", true) -- system header 67 | ffi.path "./your/local/header_file_directory/" -- your local header 68 | ``` 69 | - note: only the path with system_path == false passed to ffiex.csrc's compiler option (-I). 70 | 71 | ### define:number|string|funciton = ffiex.defs.{TABLE_KEY} 72 | - get corresponding value (number/string) for macro definition or lua function that do same things as functional macro, which name is of macro {TABLE_KEY}. 73 | - it cannot process some C system header macro for keeping backword compatibility (like errno or struct stat.st_atime). 74 | because it will replace the ctype's symbol access... (like stat.st_atime => stat.st_atimespec.tv_sec) 75 | 76 | ### ffiex.undef(macro_names:table) 77 | - undef specified macro from lcpp cache. 78 | - *macro_name* should be table which has numerical key and string value for keys 79 | ``` lua 80 | -- example, undef 2 macro symbols 81 | ffi.undef { "MYDEF", "MYDEF2" } 82 | ``` 83 | 84 | ### path:string = ffiex.search(path:string, filename:string, add:boolean) 85 | - find *filename* under *path* and return found path. 86 | - if *filename* is found && *add* is true, call ffiex.path to add searched path. 87 | - it may useful to increase portability when you need to include header which is placed to path like /usr/include/libfoo/1.2.1/foo.h and the part *1.2.1* is vary from users environment. 88 | 89 | ### lib:clib,err:string = ffiex.csrc(name:string, input:string) 90 | - embed c source file into lua code. 91 | - ffi.csrc regards *input* as c source string and try to compile and ffi.load it, then return *lib*, which is clib object corresponding to compiled result (see test/ffiex.csrc.lua for example). otherwise return nil and compile error output *err*. if input is omitted, then name is regared as c source file path. 92 | - input to csrc is parsed by ffiex.lcpp, so all macro declared in input, is accesible from lua code via ffi.defs.{MACRO_NAME}. for this purpose, -D option for ffiex.copt is autometically injected to ffiex.lcpp itself. 93 | - only function symbol which has no static qualifier, will be exported to clib object. 94 | 95 | ### ffiex.copt(opts:table) 96 | - put C compile option which is used by ffiex.csrc. mutiple call of ffiex.copt overwrites previous options. 97 | ``` lua 98 | -- example, apply -O2, -Wall, 2 pre-defined macro for input of ffiex.csrc 99 | ffi.copt { 100 | extra = {"-D_MYDEF", "-D_MYDEF2=101", "-O2", "-Wall"} 101 | } 102 | -- still you can use old style option 103 | ffi.copt {"-D_MYDEF", "-D_MYDEF2=101", "-O2", "-Wall"} 104 | ``` 105 | fully opts format is like following 106 | ``` lua 107 | options = { 108 | -- string "gcc", "tcc" or table or table which implements build backend 109 | cc = <>, 110 | path = { 111 | include = { path1, path2, ... }, 112 | sys_include = { syspath1, syspath2, ... }, 113 | lib = { libpath1, libpath2, ... } 114 | }, 115 | lib = { libname1, libname2, ... }, 116 | extra = { opt1, opt2, ... }, 117 | define = { booldef1, booldef2, ... def1 = val1, def2 = val2 } 118 | } 119 | ``` 120 | 121 | ### ffiex.import(symbols:table):from(code:string) 122 | - parsing *code* and import symbols which has dependency with *symbols*. 123 | - *symbols* are given as table of strings, and *code* has same format which is given to ffiex.cdef, like following. 124 | ``` lua 125 | ffiex.import({"pthread_t", "pthread_create"}):from("#include ") 126 | ``` 127 | - some symbol has multiple meaning (eg. union wait/int wait(int *) in OSX), in this case following rules are applied for deciding actual symbol name. 128 | - single symbol name with no keyword like struct/union/enum, ffiex first try to find function with that name, then struct/union/enum/typename 129 | - if you specify "func" keyword, then ffiex try to search function entry of this name 130 | - if you specify "struct/union/enum/typename", then ffiex try to search struct/union/enum/typename entry of that name 131 | 132 | ``` lua 133 | -- search function which name is "wait", if not found then try union/struct/enum/typename which name is "wait" 134 | ffiex.import({"wait"}):from("#include ") 135 | -- search function which name is "wait" 136 | ffiex.import({"func wait"}):from("#include ") 137 | -- search union which name is "wait" 138 | ffiex.import({"union wait"}):from("#include ") 139 | -- note that if you specify "struct wait", also "union wait" is injected. that is, ffiex ignores difference of struct/union/enum. 140 | ffiex.import({"struct wait"}):from("#include ") 141 | ``` 142 | - ffiex internally caches parsing result of *code*, so you can call ffiex.import(symbols) multiple times for same header file. 143 | 144 | ### ffiex.src_of(symbol:string, recursive:boolean) 145 | - get declaration code of specified *symbol* 146 | - *symbol* is symbol name and has same rules as each element of *symbols* for ffiex.import 147 | - *recursive* specifies whether ffiex should resolve dependency recursively, if true, ffiex traverses dependency chain recursively and list up all dependent symbols of *symbol* 148 | ``` lua 149 | ffiex.cdef("#include ") 150 | ffiex.src_of("pthread_t") --> returns "extern int pthread_join (pthread_t __th, void **__thread_return);" 151 | ffiex.src_of("pthread_t", true) --[[returns " 152 | typedef unsigned long int pthread_t; 153 | extern int pthread_join (pthread_t __th, void **__thread_return); 154 | " 155 | ]] 156 | ``` 157 | 158 | ### state:ffi_state = ffiex.newstate() 159 | - get isolated parsing state object which provides same methods of ffiex. 160 | - *state* has following methods, which equivalent to the same method of ffiex(ffi) 161 | - state:cdef 162 | - state:path 163 | - state:search 164 | - state.defs 165 | - state:csrc 166 | - state:copt 167 | - state:import(...):from(...) 168 | - state:src_of 169 | - state:load 170 | - it is useful for module writer, because header search path and macro/dependency-tree(for ffiex.import) cache are isolated among each state object created by ffiex.newstaet() and ffiex module itself. 171 | - so if each module requires special macro definition or header file path, it never *pollutes* main ffiex module's, as long as you use your own parse state object. 172 | - so I think if you wants to write module which depends on ffiex, you should use ffiex.newstate() instead of calling ffiex.* directly. 173 | 174 | Add own build backend 175 | ===================== 176 | - now ffiex.copts(options) can accept build backend through parameter of *options.cc* 177 | - options.cc could be "gcc" or "tcc", but also you can specify your own build backend module. 178 | - build backend module should be implemented as following: 179 | 180 | ``` lua 181 | -- builder must have new() method to create new builder. 182 | local builder = {} 183 | function builder.new() 184 | return setmetatable({}, {__index = cc}) 185 | end 186 | -- returned builder object has following 5 methods 187 | 188 | 189 | -- initialize. do something for ffi_state object *state* to make this backend work. 190 | function cc:init(state) 191 | end 192 | 193 | -- finalize. cleanup something which is done to *state* in cc:init. 194 | function cc:exit(state) 195 | end 196 | 197 | -- build code, create share object file, and return following: 198 | -- in success : shared object path, nil 199 | -- in failure : nil, error string 200 | function cc:build(code) 201 | end 202 | 203 | -- apply compile option to backend 204 | -- *opts* should be preserved in this module and returnable from cc:get_option 205 | function cc:option(opts) 206 | self.opts = opts 207 | end 208 | 209 | -- return option which preserved at cc:option() 210 | function cc:get_option() 211 | return self.opts 212 | end 213 | 214 | return builder --> you can pass this as parameter of options.cc for ffiex.copts. 215 | ``` 216 | - for more detail, please see ffiex/builder/*.lua. 217 | 218 | 219 | Improvement 220 | =========== 221 | 222 | - (partially solved with #4) able to run on gcc-less environment. I already make some preparation like *ffiex.exconf.cacher* to cache built so files on host side (which should have proper gcc toolchain), but has no good idea for bundling them to final executables yet (for example, into apk or ipa) 223 | 224 | - (solved with #5) reduce memory footprint. because current ffiex import all symbols in #include'd header file, so even unnecessary cdefs all exists on memory. one idea is specify required type or function definition like below. 225 | 226 | 227 | License 228 | ======= 229 | 230 | apache v2 (http://www.apache.org/licenses/LICENSE-2.0) 231 | 232 | 233 | about sponsored 234 | =============== 235 | - [DokyoGames, inc](https://www.facebook.com/DokyoGames) for supporting development of selective cdef feature. 236 | -------------------------------------------------------------------------------- /ffiex-0.2.0-8.rockspec: -------------------------------------------------------------------------------- 1 | package = "ffiex" 2 | version = "0.2.0-8" 3 | source = { 4 | url = "git://github.com/umegaya/ffiex.git", 5 | } 6 | description = { 7 | summary = "extend luajit ffi module to give more affinity to C codes", 8 | detailed = [[ 9 | - extend cdef to parse macro and headers includes 10 | - not only entire header file contents but selective symbols for necessary specified function 11 | - search and add header file path as usual C compiler 12 | - ffi.csrc to add small C source to lua code (gcc, tcc(linux only) supported) 13 | - macro can share between codes in cdef/csrc and lua (except functional macro :P) 14 | ]], 15 | homepage = "https://github.com/umegaya/ffiex", 16 | license = "Apache v2" 17 | } 18 | dependencies = { 19 | "lua >= 5.1", 20 | } 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | ["ffiex"] = "ffiex/init.lua", 25 | ["ffiex.lcpp"] = "ffiex/lcpp.lua", 26 | ["ffiex.parser"] = "ffiex/parser.lua", 27 | ["ffiex.util"] = "ffiex/util.lua", 28 | ["ffiex.builder.gcc"] = "ffiex/builder/gcc.lua", 29 | ["ffiex.builder.tcc"] = "ffiex/builder/tcc.lua", 30 | }, 31 | install = { 32 | lua = { 33 | ["ffiex"] = "ffiex/init.lua", 34 | ["ffiex.lcpp"] = "ffiex/lcpp.lua", 35 | ["ffiex.parser"] = "ffiex/parser.lua", 36 | ["ffiex.util"] = "ffiex/util.lua", 37 | ["ffiex.builder.gcc"] = "ffiex/builder/gcc.lua", 38 | ["ffiex.builder.tcc"] = "ffiex/builder/tcc.lua", 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ffiex/builder/gcc.lua: -------------------------------------------------------------------------------- 1 | local util = require 'ffiex.util' 2 | local cc = {} 3 | local function error_callback(self, msg) 4 | if self.error then 5 | self.error = (self.error .. "\n" .. msg) 6 | else 7 | self.error = msg 8 | end 9 | end 10 | local function clear_option(self) 11 | self.cmdopts = nil 12 | end 13 | --[[ 14 | options = { 15 | path = { 16 | include = { path1, path2, ... }, 17 | sys_include = { syspath1, syspath2, ... }, 18 | lib = { libpath1, libpath2, ... } 19 | }, 20 | lib = { libname1, libname2, ... }, 21 | define = { booldef1, booldef2, ... def1 = val1, def2 = val2 } 22 | } 23 | ]] 24 | local function apply_option(self) 25 | if not self.cmdopts then 26 | local opts = self.opts 27 | local cmdopts = table.concat({"-fPIC", "-O2"}, " ") 28 | if type(opts.extra) == 'table' then 29 | cmdopts = (cmdopts .. " " .. table.concat(opts.extra, " ")) 30 | end 31 | if type(opts.path.include) == 'table' and #(opts.path.include) > 0 then 32 | cmdopts = (cmdopts .. " -I" .. table.concat(opts.path.include, " -I")) 33 | end 34 | if type(opts.path.lib) == 'table' and #(opts.path.lib) > 0 then 35 | cmdopts = (cmdopts .. " -L" .. table.concat(opts.path.lib, " -L")) 36 | end 37 | if type(opts.lib) == 'table' and #(opts.lib) > 0 then 38 | cmdopts = (cmdopts .. " -l" .. table.concat(opts.lib, " -l")) 39 | end 40 | if type(opts.define) == 'table' then 41 | for k,v in pairs(opts.define) do 42 | if type(k) == "number" then 43 | cmdopts = (cmdopts .. " -D" .. v) 44 | else 45 | cmdopts = (cmdopts .. " -D" .. k .. "=" .. v) 46 | end 47 | end 48 | end 49 | self.cmdopts = cmdopts 50 | end 51 | return self.cmdopts 52 | end 53 | 54 | -- define method 55 | local builder = {} 56 | function builder.new() 57 | return setmetatable({}, {__index = cc}) 58 | end 59 | function cc:init(state) 60 | util.add_builtin_defs(state) 61 | util.add_builtin_paths(state) 62 | end 63 | function cc:exit(state) 64 | state:clear_paths(true) 65 | util.clear_builtin_defs(state) 66 | end 67 | function cc:build(code) 68 | local opts = apply_option(self) 69 | local obj = os.tmpname() 70 | -- compile .so 71 | --[=[print(([[gcc -shared -xc - -o %s %s < OMG header not found... 56 | if not no_throw then 57 | local paths = "" 58 | for _,path in ipairs(currentState.searchPath) do 59 | paths = paths .. "\n" .. path 60 | end 61 | error(filename .. ' not found in:' .. paths .. "\n at \n" .. debug.traceback()) 62 | end 63 | return nil 64 | end 65 | 66 | lcpp.compileFile = function (filename, predefines, macro_sources, nxt, _local) 67 | filename, lastTryPath = search_header_file(filename, predefines, nxt, _local) 68 | if ffi.__DEBUG_CDEF__ then 69 | local out = {originalCompileFile(filename, predefines, macro_sources, nxt)} 70 | print('include:'..filename)--.."=>"..out[1]) 71 | return unpack(out) 72 | end 73 | return originalCompileFile(filename, predefines, macro_sources, nxt) 74 | end 75 | 76 | ----------------------- 77 | -- built in macro defs 78 | ----------------------- 79 | local header_name = "__has_include_next%(%s*[\"<]+(.*)[\">]+%s*%)" 80 | local function has_include_next(decl) 81 | local file = decl:match(header_name) 82 | -- print("has_include_next:", file, decl) 83 | return search_header_file(file, currentState.lcpp_defs, true, false, true) ~= nil and "1" or "0" 84 | end 85 | local header_name2 = "__has_include%(%s*[\"<]+(.*)[\">]+%s*%)" 86 | local function has_include(decl) 87 | local file = decl:match(header_name2) 88 | -- print("has_include_next:", file, decl) 89 | return search_header_file(file, currentState.lcpp_defs, false, false, true) ~= nil and "1" or "0" 90 | end 91 | local function __asm(exp) 92 | return exp:gsub("__asm_*%s*%b()", "") 93 | end 94 | 95 | 96 | 97 | ----------------------- 98 | -- utils 99 | ----------------------- 100 | local function replace_table(src, rep) 101 | for k,v in pairs(src) do 102 | src[k] = rep[k] 103 | end 104 | for k,v in pairs(rep) do 105 | src[k] = rep[k] 106 | end 107 | end 108 | 109 | local function macro_to_lua_func(st, macro_source) 110 | return function (...) 111 | local args = {...} 112 | local state = st:expr_processor() 113 | local src = macro_source:gsub("%$(%d+)", function (m) return args[tonumber(m)] end) 114 | local val = state:parseExpr(src) 115 | -- print(val, src) 116 | if type(val) ~= 'string' then 117 | return val 118 | else -- more parse with lua lexer 119 | local f, err = loadstring("return "..val) 120 | if not f then error(err) end 121 | return f() 122 | end 123 | end 124 | end 125 | 126 | -- TODO : merged with ffi.parser 127 | local function generate_cdefs(state, code) 128 | -- matching extern%s+[symbol]%s+[symbol]%b() 129 | local current = 0 130 | local decl = "" 131 | repeat 132 | local _, offset = string.find(code, '\n', current+1, true) 133 | local line = code:sub(current+1, offset):gsub('%b{}', '') 134 | -- print('line = '..line) 135 | -- matching simple function declaration (e.g. void foo(t1 a1, t2 a2)) 136 | local _, count = line:gsub('^%s*([_%a][_%w]*%s+[_%a][_%w]*%b())%s*', function (s) 137 | -- print(s) 138 | decl = (decl .. "extern " .. s .. ";\n") 139 | end) 140 | -- matching function declaration with access specifier 141 | -- (e.g. extern void foo(t1 a1, t2 a2), static void bar()) 142 | -- and not export function declaration contains 'static' specifier 143 | if count <= 0 then 144 | line:gsub('(.*)%s+([_%a][_%w]*%s+[_%a][_%w]*%b())%s*', function (s1, s2) 145 | -- print(s1 .. "|" .. s2) 146 | if not s1:find('static') then 147 | decl = (decl .. "extern " .. s2 .. ";\n") 148 | end 149 | end) 150 | end 151 | current = offset 152 | until not current 153 | -- print('code = ['..code..']') 154 | if #decl > 0 then 155 | -- print('decl = [' .. decl..']') 156 | state:cdef(decl) 157 | end 158 | end 159 | local function parse_stack() 160 | local stack,current = debug.traceback(),0 161 | local ret = {} 162 | -- parse output of debug.traceback() 163 | -- TODO : need to track the spec change of debug.traceback() 164 | repeat 165 | local _, offset = string.find(stack, '\n', current+1, true) 166 | local line = stack:sub(current+1, offset) 167 | local res, count = line:gsub('%s*([^%s:]+):([%d]+).*', function (s1, s2) 168 | table.insert(ret, {file = s1, line = s2}) 169 | end) 170 | current = offset 171 | until not current 172 | return ret 173 | end 174 | local function get_decl_file(name, src, depth) 175 | if not src then -- means external .c file specified with 'name' 176 | return name 177 | end 178 | local traces = parse_stack() 179 | depth = (depth or 1) 180 | for _,tr in ipairs(traces) do 181 | if not tr.file:find('ffiex/init.lua') then 182 | depth = (depth - 1) 183 | end 184 | if depth <= 0 then 185 | return tr.file 186 | end 187 | end 188 | return nil 189 | end 190 | 191 | 192 | 193 | ----------------------- 194 | -- ffi state 195 | ----------------------- 196 | local parser_lib 197 | local ffi_state = {} 198 | function ffi_state.new(try_init_path) 199 | local r = setmetatable({}, {__index = ffi_state}) 200 | r:init(try_init_path) 201 | return r 202 | end 203 | local defs_mt = { 204 | __index = function (t, k) 205 | local st = t["#state"] 206 | local def = st.lcpp_defs[k] 207 | if type(def) == 'number' then 208 | local ok, r = pcall(loadstring, "return " .. def) 209 | if ok and r then 210 | rawset(t, k, r()) 211 | return rawget(t, k) 212 | end 213 | elseif type(def) == 'string' then 214 | local state = st:expr_processor() 215 | local expr = state:parseExpr(def) 216 | rawset(t, k, expr) 217 | return rawget(t, k) 218 | elseif type(def) == 'function' then 219 | def = st.lcpp_macro_sources[k] 220 | if not def then return nil end 221 | def = macro_to_lua_func(st, def) 222 | end 223 | rawset(t, k, def) 224 | return def 225 | end 226 | } 227 | function ffi_state:expr_processor() 228 | if not self.processor then 229 | self.processor = lcpp.init('', {}, {}) 230 | end 231 | self.processor.defines = self.lcpp_defs 232 | self.processor.macro_sources = self.lcpp_macro_sources 233 | return self.processor 234 | end 235 | function ffi_state:init(try_init_path) 236 | self.defs = setmetatable({ ["#state"] = self }, defs_mt) 237 | self.searchPath = {"./"} 238 | self.systemSearchPath = {} 239 | self.localSearchPath = {} 240 | 241 | -- add built in macro here 242 | self.lcpp_defs = { 243 | ["__has_include"] = has_include, 244 | ["__has_include_next"] = has_include_next, 245 | -- i don't know the reason but OSX __asm alias not works for luajit symbol search 246 | ["__asm"] = __asm, -- just return empty string TODO : investigate reason. 247 | } 248 | 249 | -- if gcc is available, try using it for initial builder. 250 | if try_init_path then 251 | local ok, rv = pcall(os.execute, "gcc -v 2>/dev/null") 252 | if ok then 253 | local has_gcc = (rv == 0) 254 | ok, rv = pcall(require, 'ffiex.builder.gcc') 255 | if ok and rv then 256 | local builder = rv.new() 257 | if has_gcc then 258 | builder:init(self) 259 | self.builder = builder 260 | self:copt({ cc = "gcc" }) 261 | else 262 | ok, rv = pcall(builder.init, builder, self) 263 | end 264 | end 265 | end 266 | if not ok then 267 | print('gcc available but fail to initialize gcc builder:'..rv) 268 | end 269 | end 270 | end 271 | -- importer lib 272 | local importer_lib = {} 273 | function importer_lib.new(state, sym) 274 | return setmetatable({state = state, sym = sym}, { __index = importer_lib}) 275 | end 276 | function importer_lib:from(code) 277 | local tree = self.state:parse(code) 278 | 279 | return ffi.native_cdef_with_guard(tree, self.sym) 280 | end 281 | 282 | function ffi_state:import(sym) 283 | return importer_lib.new(self, sym) 284 | end 285 | function ffi_state:parse(decl, tmptree) 286 | if not parser_lib then 287 | parser_lib = require 'ffiex.parser' 288 | end 289 | currentState = self 290 | local output, state = lcpp.compile(decl, self.lcpp_defs, self.lcpp_macro_sources) 291 | --print('output='..output) 292 | local has_ssize_t = output:match('ssize_t;') 293 | self.lcpp_defs = state.defines 294 | self.lcpp_macro_sources = state.macro_sources 295 | if tmptree and self.tree then 296 | tmptree = parser_lib.parse(nil, output) 297 | for _,sym in pairs(tmptree[1]) do 298 | table.insert(self.tree[1], sym) 299 | end 300 | for k,v in pairs(tmptree) do 301 | if not self.tree[k] then self.tree[k] = tmptree[k] end 302 | end 303 | return tmptree, output 304 | else 305 | self.tree = parser_lib.parse(self.tree, output) 306 | return self.tree, output 307 | end 308 | end 309 | function ffi_state:cdef(decl, ...) 310 | local tmp = self:parse(decl, true) 311 | ffi.native_cdef_with_guard(tmp, nil, ...) 312 | end 313 | function ffi_state:define(defs) 314 | for k,v in pairs(defs) do 315 | self.lcpp_defs[k] = v 316 | end 317 | end 318 | function ffi_state:undef(defs) 319 | for i,def in ipairs(defs) do 320 | self.lcpp_defs[def] = nil 321 | end 322 | end 323 | function ffi_state:path(path, system) 324 | if path[#path] ~= '/' then 325 | path = (path .. '/') 326 | end 327 | table.insert(self.searchPath, path) 328 | if system then 329 | table.insert(self.systemSearchPath, path) 330 | else 331 | -- print("add localSerchPath:" .. path) 332 | table.insert(self.localSearchPath, path) 333 | end 334 | end 335 | function ffi_state:clear_paths(system) 336 | local tmp = {} 337 | local removed = system and self.systemSearchPath or self.localSearchPath 338 | for _,s in ipairs(self.searchPath) do 339 | local found 340 | for _,t in ipairs(removed) do 341 | if s == t then 342 | found = true 343 | end 344 | end 345 | if not found then 346 | table.insert(tmp, s) 347 | end 348 | end 349 | replace_table(self.searchPath, tmp) 350 | if system then 351 | replace_table(self.systemSearchPath, {}) 352 | else 353 | replace_table(self.localSearchPath, {}) 354 | end 355 | end 356 | function ffi_state:search(path, file, add) 357 | local p = io.popen(('find %s -name %s'):format(path, file), 'r') 358 | if not p then return nil end 359 | local line 360 | while true do 361 | line = p:read('*l') 362 | if not line then 363 | break -- eof 364 | else 365 | -- if matches find:, log of find itself. 366 | if (not line:match('^find:')) and line:match((file .. '$')) then 367 | break 368 | end 369 | end 370 | end 371 | if line and add then 372 | --print('find path and add to header path:' .. line .. "|" .. line:gsub('^(.*/)[^/]+$', '%1')) 373 | self:path(line:gsub('^(.*/)[^/]+$', '%1')) 374 | end 375 | return line 376 | end 377 | function ffi_state:clear_copt() 378 | local builder = self.builder 379 | if not builder or not builder:get_option() then 380 | return 381 | end 382 | local undefs = {} 383 | if builder:get_option().define then 384 | for k,v in pairs(builder:get_option().define) do 385 | table.insert(undefs, type(k) == 'number' and v or k) 386 | end 387 | end 388 | if builder:get_option().extra then 389 | for _,o in ipairs(builder:get_option().extra) do 390 | local def,val = o:match("-D([_%w]+)=?(.*)") 391 | if def then table.insert(undefs, def) end 392 | end 393 | end 394 | self:undef(undefs) 395 | if builder then 396 | builder:exit(self) 397 | end 398 | self.builder = nil 399 | end 400 | function ffi_state:copt(opts) 401 | if opts[1] and (not opts.extra) then 402 | opts = { extra = opts } 403 | end 404 | self:clear_copt() 405 | local defs = {} 406 | local builder 407 | if opts.cc then 408 | if type(opts.cc) == 'string' then 409 | builder = require ('ffiex.builder.'..opts.cc).new() 410 | elseif type(opts.cc) == 'table' then 411 | builder = opts.cc 412 | else 413 | error("invalid cc:" .. type(opts.cc)) 414 | end 415 | if builder then 416 | builder:init(self) 417 | self.builder = builder 418 | end 419 | else 420 | error("ffi.copt: opts.cc must be specified") 421 | end 422 | if opts.define then 423 | for k,v in pairs(opts.define) do 424 | if type(k) == "number" then 425 | defs[v] = "" 426 | else 427 | defs[k] = v 428 | end 429 | end 430 | end 431 | if opts.extra then 432 | for _,o in ipairs(opts.extra) do 433 | local def,val = o:match("-D([_%w]+)=?(.*)") 434 | if def then 435 | defs[def] = val 436 | end 437 | end 438 | end 439 | self:define(defs) 440 | if not opts.path then 441 | opts.path = {} 442 | end 443 | if type(opts.path.include) ~= 'table' or #opts.path.include <= 0 then 444 | opts.path.include = self.localSearchPath 445 | end 446 | if type(opts.path.sys_include) ~= 'table' or #opts.path.sys_include <= 0 then 447 | opts.path.sys_include = self.systemSearchPath 448 | end 449 | if not opts.cache_callback then 450 | opts.cache_callback = function (name, src, search) 451 | end 452 | end 453 | builder:option(opts) 454 | end 455 | -- compiler object (tcc/gcc is natively supported) 456 | function ffi_state:build(name, code) 457 | -- load source code 458 | if not code then 459 | local f = io.open(name, 'r') 460 | code = f:read('*a') 461 | f:close() 462 | end 463 | -- dummy preprocess to inject macro definition for external use 464 | self:cdef(code) 465 | -- generate cdefs from source code 466 | generate_cdefs(self, code) 467 | return self.builder:build(code) 468 | end 469 | function ffi_state:csrc(name, src, opts) 470 | if opts then 471 | self:copt(opts) 472 | end 473 | local builder = self.builder 474 | assert(builder, "builder not specified. please set opts.cc = 'tcc'/'gcc'/your customized cc table") 475 | local ext 476 | local path = builder:get_option().cache_callback(name, src, get_decl_file(name, src), true) 477 | if not path then 478 | path,ext = self:build(name, src) 479 | end 480 | if path then 481 | local ok, lib = pcall(ffi.load, path) 482 | if ok and lib then 483 | builder:get_option().cache_callback(name, src, get_decl_file(name, src), false) 484 | -- os.remove(path) 485 | return lib,ext 486 | else 487 | -- os.remove(path) 488 | return nil,lib 489 | end 490 | else 491 | return nil,ext 492 | end 493 | end 494 | function ffi_state:load(...) 495 | ffi.load(...) 496 | end 497 | function ffi_state:src_of(symbol, recursive) 498 | symbol = parser_lib.name(self.tree, symbol) 499 | return recursive and 500 | parser_lib.inject(self.tree, {symbol}) or 501 | assert(self.tree[symbol], "no such symbol:"..symbol).cdef 502 | end 503 | 504 | 505 | 506 | ----------------------- 507 | -- ffiex module 508 | ----------------------- 509 | -- already imported symbols (and guard them from dupe) 510 | ffi.imported_csymbols = {} 511 | function ffi.native_cdef_with_guard(tree, symbols_or_ppcode, ...) 512 | local injected = parser_lib.inject(tree, symbols_or_ppcode, ffi.imported_csymbols) 513 | if ffi.__DEBUG_CDEF__ then 514 | print('injected source:[['..injected..']]') 515 | local f = io.open('./tmp.txt', 'w') 516 | f:write(injected) 517 | f:close() 518 | end 519 | ffi.lcpp_cdef_backup(injected, ...) 520 | return injected 521 | end 522 | 523 | -- wrappers of ffi_state object. 524 | local main_ffi_state = ffi_state.new(true) 525 | ffi.main_ffi_state = main_ffi_state 526 | function ffi.path(path, system) 527 | return main_ffi_state:path(path, system) 528 | end 529 | function ffi.clear_paths(system) 530 | return main_ffi_state:clear_paths(system) 531 | end 532 | function ffi.search(path, file, add) 533 | return main_ffi_state:search(path, file, add) 534 | end 535 | function ffi.cdef(decl, ...) 536 | return main_ffi_state:cdef(decl, ...) 537 | end 538 | function ffi.define(defs) 539 | return main_ffi_state:define(defs) 540 | end 541 | function ffi.undef(defs) 542 | return main_ffi_state:undef(defs) 543 | end 544 | ffi.defs = main_ffi_state.defs 545 | function ffi.clear_copt() 546 | return main_ffi_state:clear_copt() 547 | end 548 | function ffi.copt(opts) 549 | return main_ffi_state:copt(opts) 550 | end 551 | function ffi.csrc(name, src, opts) 552 | return main_ffi_state:csrc(name, src, opts) 553 | end 554 | function ffi.import(symbols) 555 | return main_ffi_state:import(symbols) 556 | end 557 | function ffi.newstate(try_init_path) 558 | return ffi_state.new(try_init_path) 559 | end 560 | function ffi.init_cdef_cache() 561 | (require 'ffiex.util').create_builtin_config_cache() 562 | end 563 | function ffi.clear_cdef_cache() 564 | (require 'ffiex.util').clear_builtin_config_cache() 565 | end 566 | 567 | return ffi 568 | -------------------------------------------------------------------------------- /ffiex/parser.lua: -------------------------------------------------------------------------------- 1 | --------------------------------------------------- 2 | -- logger 3 | --------------------------------------------------- 4 | local function log(...) 5 | -- print(...) 6 | end 7 | local function vlog(...) 8 | -- print(...) 9 | end 10 | 11 | 12 | --------------------------------------------------- 13 | -- symbol table 14 | --------------------------------------------------- 15 | --[[ 16 | sym = { 17 | symname1 = { 18 | deps = { dep_sym1, dep_sym2, ... }, 19 | cdef = "string code" 20 | }, 21 | symname2 = { 22 | ... 23 | }, 24 | ... 25 | } 26 | ]] 27 | local function make_sym_dep(sym, name, deps, cdef) 28 | local res = {} 29 | for _,dep in ipairs(deps or {}) do 30 | log(name.." depends on ["..dep.."]") 31 | assert(sym[dep], "["..dep .. "] not predefined") 32 | end 33 | local cdef = cdef:gsub("^%s+", ""):gsub("%s+$", "") 34 | if sym[name] then 35 | log('caution:'..name.." already exist:"..debug.traceback()) 36 | end 37 | table.insert(sym[1], name) 38 | sym[name] = { 39 | name = name, 40 | deps = deps, 41 | cdef = cdef, 42 | prio = #(sym[1]), 43 | } 44 | end 45 | 46 | local function get_real_sym_name(pfx, name) 47 | return pfx.." "..name 48 | end 49 | local function get_func_sym_name(name) 50 | return get_real_sym_name("func", name) 51 | end 52 | local function make_func_dep(sym, name, deps, cdef) 53 | make_sym_dep(sym, get_func_sym_name(name), deps, cdef) 54 | end 55 | 56 | local function make_incomplete_decl(sym, name, cdef) 57 | if sym[name] and (not sym[name].temp) then 58 | log(name .. " already declared as:["..sym[name].cdef.."]") 59 | return 60 | end 61 | table.insert(sym[1], name) 62 | sym[name] = { 63 | name = name, 64 | cdef = cdef, 65 | temp = true, 66 | prio = #(sym[1]), 67 | } 68 | end 69 | 70 | local function has_sym(sym, name) 71 | return sym[name] 72 | end 73 | 74 | local function new_sym_table() 75 | local sym = {[1] = {}} 76 | make_sym_dep(sym, "void", nil, "") 77 | 78 | make_sym_dep(sym, "_Bool", nil, "") 79 | make_sym_dep(sym, "bool", nil, "") 80 | 81 | make_sym_dep(sym, "char", nil, "") 82 | make_sym_dep(sym, "signed char", nil, "") 83 | make_sym_dep(sym, "unsigned char", nil, "") 84 | 85 | make_sym_dep(sym, "int", nil, "") 86 | make_sym_dep(sym, "signed int", nil, "") 87 | make_sym_dep(sym, "unsigned int", nil, "") 88 | 89 | make_sym_dep(sym, "short int", nil, "") 90 | make_sym_dep(sym, "signed short int", nil, "") 91 | make_sym_dep(sym, "unsigned short int", nil, "") 92 | 93 | make_sym_dep(sym, "long int", nil, "") 94 | make_sym_dep(sym, "signed long int", nil, "") 95 | make_sym_dep(sym, "unsigned long int", nil, "") 96 | 97 | make_sym_dep(sym, "long long int", nil, "") 98 | make_sym_dep(sym, "signed long long int", nil, "") 99 | make_sym_dep(sym, "unsigned long long int", nil, "") 100 | 101 | make_sym_dep(sym, "double", nil, "") 102 | make_sym_dep(sym, "long double", nil, "") 103 | make_sym_dep(sym, "float", nil, "") 104 | 105 | make_sym_dep(sym, "__builtin_va_list", nil, "") 106 | 107 | return sym 108 | end 109 | 110 | 111 | --------------------------------------------------- 112 | -- basic elements 113 | --------------------------------------------------- 114 | local TYPEDEF_SYMBOL="typedef" 115 | local SPACE="%s+" 116 | local OPTSPACE="%s*" 117 | local OPT_UNDERSCORE="%_*" 118 | local SPACE_OR_STAR="[%s%*]+" 119 | local OPT_SPACE_OR_STAR="[%s%*]*" 120 | local TYPENAME="[_%w]+" 121 | local OPT_TYPENAME="[_%w]*" 122 | local ALL_REMAINS="[^%;]*" 123 | local ALL_REMAINS_IN_ARG_DECL="[^%,]*" 124 | local VAR_DECL=OPT_SPACE_OR_STAR.."[_%w]+%s*[%[%]%w%s]*" 125 | local BLACKET1="%b()" 126 | local BLACKET2="%b{}" 127 | local MAY_HAVE_ARRAY_BLACKET="[%[%]%w%s]*" 128 | local STRUCTURE_SYMBOL=TYPENAME 129 | local STRUCT_VAR_LIST=BLACKET2 130 | local ARG_VAR_LIST=BLACKET1 131 | local CODE_BLOCK=BLACKET2 132 | local EXT_ATTR_TAG="%$([0-9]+)" -- replace to actual __attribute__(...)/__asm(...)/__declspec(...) 133 | -- combination of extern/static/inline/auto/register/volatile/signed/unsigned/EXT_ATTR_TAG+typename 134 | local QUALIFIER="[_%w%s%$]*[_%w]" 135 | local OPT_QUALIFIER="[_%w%s%$]*[_%w]?" 136 | local QUALIFY_KEYWORD = { 137 | "int", 138 | "char", 139 | "const", 140 | "signed", 141 | "unsigned", 142 | "long long", 143 | "long", 144 | "short", 145 | "struct", 146 | "enum", 147 | "union", 148 | "extern", 149 | "static", 150 | "inline", 151 | "volatile", 152 | "auto", 153 | "register", 154 | } 155 | local QUALIFY_KEYWORD_CAPTURE = { 156 | EXT_ATTR_TAG, 157 | } 158 | local FUNC_TYPE_SYMBOL="%(?"..VAR_DECL..OPTSPACE.."%)?" 159 | local HO_FUNC_TYPE_SYMBOL="%(?"..VAR_DECL..OPTSPACE..ARG_VAR_LIST..OPTSPACE.."%)?" 160 | 161 | local function init_qualifer_keywords() 162 | local tmp = {} 163 | for _,kw in ipairs(QUALIFY_KEYWORD) do 164 | table.insert(tmp, "^"..OPT_UNDERSCORE.."("..kw..")"..OPT_UNDERSCORE) 165 | end 166 | QUALIFY_KEYWORD = tmp 167 | end 168 | init_qualifer_keywords() 169 | 170 | 171 | -- element definition with capture 172 | 173 | --------------------------------------------------- 174 | -- element parser 175 | --------------------------------------------------- 176 | local function match(src, pattern) 177 | local m = {src:find(pattern)} 178 | local s, e = table.remove(m, 1), table.remove(m, 1) 179 | if s and e >= s then 180 | return s, e, m 181 | else 182 | return nil 183 | end 184 | end 185 | 186 | local function restore_src(src, ext_attr_list) 187 | return src:gsub(EXT_ATTR_TAG, function (n) 188 | return ext_attr_list[tonumber(n)] 189 | end) 190 | end 191 | 192 | local MAIN_PATTERN_LIST 193 | local PARSER_MAP 194 | local function common_parser(sym, deps, body, patterns, sep, opaque) 195 | -- trim 196 | body = body:gsub("^%s+", ""):gsub("%s+$", "") 197 | while true do 198 | local found 199 | for _, pattern in ipairs(patterns) do 200 | local s, e, m = match(body, pattern..(sep or "").."%s*") 201 | vlog('try match:', "["..(#body <= 100 and body or body:sub(1, 100).."<...snip...>").."]", s, e, _, pattern) 202 | if s then 203 | found = true 204 | local src = body:sub(s, e) 205 | --print("src="..src:gsub("^%s+", ""):gsub("%s+$", "")) 206 | body = body:sub(e+1) 207 | local cb = PARSER_MAP[patterns][pattern] 208 | log('match result:', pattern, "["..src.."]") 209 | for _,mm in ipairs(m) do 210 | vlog('matches:', _, "["..mm.."]") 211 | end 212 | local symbol = cb(sym, opaque, deps, m, src) 213 | if symbol then 214 | if type(symbol) == "string" then 215 | vlog("match result2:["..tostring(symbol).."]") 216 | table.insert(deps, symbol) 217 | end 218 | end 219 | break 220 | end 221 | end 222 | if not found or (#body <= 0) then 223 | if #body > 0 then 224 | log("no pattern matched:["..body.."]") 225 | end 226 | break 227 | end 228 | end 229 | return sym 230 | end 231 | 232 | local qualifier_patterns = { 233 | "^(long long)"..OPTSPACE, 234 | "^([_%w$]+)"..OPTSPACE, 235 | } 236 | local function common_parse_qualifier(sym, src, ext_attr_list) 237 | local attr = {} 238 | local symbol 239 | local varname 240 | -- trim 241 | src = src:gsub("^%s+", ""):gsub("%s+$", "") 242 | while true do 243 | local found 244 | local s, e, m 245 | -- special treatment for evil "long long" (has space in keyword) 246 | for _,pattern in ipairs(qualifier_patterns) do 247 | s, e, m = match(src, pattern) 248 | if s then break end 249 | end 250 | if s then 251 | src = src:sub(e + 1) 252 | local token = m[1] 253 | for _, kw in ipairs(QUALIFY_KEYWORD) do 254 | s, e, m = match(token, kw) 255 | --print('token and kw:'..token.."|"..kw, s, e, #token, m and m[1]) 256 | if s and (e == #token) then 257 | attr[m[1]] = true 258 | found = true 259 | break 260 | end 261 | end 262 | if not found then 263 | for _, kw in ipairs(QUALIFY_KEYWORD_CAPTURE) do 264 | s, e, m = token:find(kw) 265 | if s then 266 | attr[kw] = ext_attr_list[tostring(m)] 267 | found = true 268 | break 269 | end 270 | end 271 | end 272 | if not found then 273 | if not symbol then 274 | symbol = token 275 | else 276 | -- var name decl also contained in qualifier. 277 | -- it occurs in most cases. eg) long x; 278 | -- its not harmful because we only want to know type dependency, 279 | -- don't need to care about varname. 280 | varname = token 281 | end 282 | end 283 | end 284 | if #src <= 0 then 285 | break 286 | end 287 | end 288 | -- in the case of [long x], symbol will be [x] but actually it means [long int x] 289 | local base_type 290 | for _,kw in ipairs({"char", "int"}) do 291 | if attr[kw] then 292 | log("attr has kw:"..kw) 293 | if symbol and (not base_type) and (not varname) then 294 | varname = symbol 295 | vlog('varname => ', varname) 296 | end 297 | base_type = kw 298 | break 299 | end 300 | end 301 | for _,kw in ipairs({"short", "long", "long long", "unsigned", "signed"}) do 302 | if attr[kw] then 303 | log("attr has kw:"..kw) 304 | if symbol and (not base_type) and (not varname) then 305 | varname = symbol 306 | vlog('varname => ', varname) 307 | end 308 | base_type = kw.." "..(base_type or "int") 309 | end 310 | end 311 | 312 | -- otherwise symbol is actually typename. 313 | vlog('ret:', base_type or symbol, attr, varname) 314 | if base_type then 315 | symbol = base_type 316 | else 317 | for _,kw in ipairs({"struct", "union", "enum"}) do 318 | if attr[kw] then 319 | log("attr has kw:"..kw) 320 | symbol = kw.." "..symbol 321 | break 322 | end 323 | end 324 | end 325 | if not has_sym(sym, symbol) then 326 | make_incomplete_decl(sym, symbol, src) 327 | end 328 | return symbol, attr, varname 329 | end 330 | 331 | local TYPEDECL_PATTERN_LIST 332 | local function common_parse_type_decls(sym, deps, src) 333 | local depslist = {} 334 | common_parser( 335 | sym, 336 | deps, 337 | src:gsub("^%,", ""), 338 | TYPEDECL_PATTERN_LIST, 339 | "%,?", 340 | depslist 341 | ) 342 | return deps, depslist 343 | end 344 | 345 | local STRUCT_PATTERN_LIST 346 | local function common_parse_struct_deps(sym, deps, struct_body, parent_struct) 347 | return common_parser( 348 | sym, 349 | deps, 350 | struct_body:sub(2, -2), 351 | STRUCT_PATTERN_LIST, 352 | "%;", 353 | parent_struct 354 | ) 355 | end 356 | 357 | local ARG_PATTERN_LIST 358 | local function common_parse_argument_deps(sym, deps, args_body) 359 | return common_parser( 360 | sym, 361 | deps, 362 | args_body:sub(2, -2), 363 | ARG_PATTERN_LIST, 364 | "%,?" 365 | ) 366 | end 367 | 368 | 369 | --------------------------------------------------- 370 | -- type or var decl 371 | --------------------------------------------------- 372 | local VAR_DECL_CAPTURE=OPT_SPACE_OR_STAR.. 373 | "([_%w]+)"..OPTSPACE.. 374 | MAY_HAVE_ARRAY_BLACKET 375 | 376 | -- *var[size] 377 | local VAR_DECL_VAR="^".. 378 | VAR_DECL_CAPTURE..OPTSPACE 379 | local function parse_var_decl_var(sym, opaque, deps, matches, src) 380 | table.insert(deps, matches[1]) 381 | end 382 | 383 | -- (*var[size])(...) 384 | local VAR_DECL_VAR_FUNC="^"..OPT_SPACE_OR_STAR.."%(?".. 385 | VAR_DECL_CAPTURE..OPTSPACE.."%)?"..OPTSPACE.. 386 | "("..ARG_VAR_LIST..")"..OPTSPACE 387 | local function parse_var_decl_var_func(sym, opaque, deps, matches, src) 388 | table.insert(deps, matches[1]) 389 | local argdeps = {} 390 | common_parse_argument_deps(sym, argdeps, matches[2]) 391 | opaque[matches[1]] = argdeps 392 | end 393 | 394 | -- (*(*var[size])(...))(...) 395 | local VAR_DECL_VAR_HO_FUNC="^"..OPT_SPACE_OR_STAR.."%(?".. 396 | VAR_DECL_CAPTURE..OPTSPACE.. 397 | "("..ARG_VAR_LIST..")"..OPTSPACE.."%)?"..OPTSPACE.. 398 | "("..ARG_VAR_LIST..")"..OPTSPACE 399 | local function parse_var_decl_var_high_order_func(sym, opaque, deps, matches, src) 400 | table.insert(deps, matches[1]) 401 | local argdeps = {} 402 | common_parse_argument_deps(sym, argdeps, matches[2]) 403 | common_parse_argument_deps(sym, argdeps, matches[3]) 404 | opaque[matches[1]] = argdeps 405 | end 406 | 407 | --------------------------------------------------- 408 | -- typedef 409 | --------------------------------------------------- 410 | -- typedef qualifier *type1_t[size1], *type2_t[size2], ..., *typeN_t[sizeN], 411 | -- *ftype1[fsize1](...), 412 | -- (*(*hoftype[hofsize])(...))(...); (currently upto 2 level higher order function) 413 | local TYPEDEF="^"..TYPEDEF_SYMBOL..SPACE.. 414 | "("..QUALIFIER..")"..OPTSPACE.. 415 | "("..ALL_REMAINS..")"..";" 416 | local function parse_typedef(sym, opaque, deps, matches, src) 417 | src = restore_src(src, opaque) 418 | local typename, attr, varname = common_parse_qualifier(sym, matches[1], opaque) 419 | local typedecls, depslist = common_parse_type_decls(sym, {}, matches[2]) 420 | if varname then 421 | -- first type declarator may contains in qualifier 422 | table.insert(typedecls, varname) 423 | end 424 | for _,typedecl in ipairs(typedecls) do 425 | local depends = depslist[typedecl] 426 | -- predecl is not counted as dependency (because no actual declaration required) 427 | if depends then 428 | table.insert(depends, typename) 429 | else 430 | depends = {typename} 431 | end 432 | if typename == typedecl then 433 | log('typedecl same name as typename:'..typename) 434 | make_incomplete_decl(sym, typename, src) 435 | else 436 | make_sym_dep(sym, typedecl, depends, src) 437 | end 438 | end 439 | end 440 | 441 | -- typedef struct __struct_t {...} *struct1_t[size1], *struct2_t[size2], ..., *structN_t[sizeN]; 442 | -- typedef union __union_t {...} *union1_t[size1], *union2_t[size2], ..., *unionN_t[sizeN]; 443 | -- typedef enum __enum_t {...} *enum1_t[size1], *enum2_t[size2], ..., *enumN_t[sizeN]; 444 | local STRUCTURE_TYPEDEF="^"..TYPEDEF_SYMBOL..SPACE.. 445 | "("..STRUCTURE_SYMBOL..")"..SPACE.. 446 | "("..TYPENAME..")"..OPTSPACE.. 447 | "("..STRUCT_VAR_LIST..")"..OPTSPACE.. 448 | "("..ALL_REMAINS..")"..";" 449 | local function parse_structure_typedef(sym, opaque, deps, matches, src) 450 | src = restore_src(src, opaque) 451 | local typename = get_real_sym_name(matches[1], matches[2]) 452 | local vardeps = {} 453 | if matches[1] == "enum" then 454 | make_sym_dep(sym, typename, {}, src) 455 | else 456 | common_parse_struct_deps(sym, vardeps, matches[3], typename) 457 | make_sym_dep(sym, typename, vardeps, src) 458 | end 459 | local typedecls, depslist = common_parse_type_decls(sym, {}, matches[4]) 460 | for _,typedecl in ipairs(typedecls) do 461 | make_sym_dep(sym, typedecl, {typename}, src) 462 | end 463 | end 464 | 465 | -- typedef struct {...} *struct1_t[size1], *struct2_t[size2], ..., *structN_t[sizeN]; 466 | -- typedef union {...} *union1_t[size1], *union2_t[size2], ..., *unionN_t[sizeN]; 467 | -- typedef enum {...} *enum1_t[size1], *enum2_t[size2], ..., *enumN_t[sizeN]; 468 | local ANON_STRUCTURE_TYPEDEF="^"..TYPEDEF_SYMBOL..SPACE.. 469 | "("..STRUCTURE_SYMBOL..")"..OPTSPACE.. 470 | "("..STRUCT_VAR_LIST..")"..OPTSPACE.. 471 | "("..ALL_REMAINS..")"..";" 472 | local function parse_anon_structure_typedef(sym, opaque, deps, matches, src) 473 | src = restore_src(src, opaque) 474 | local vardeps = {} 475 | if matches[1] ~= "enum" then 476 | common_parse_struct_deps(sym, vardeps, matches[2]) 477 | end 478 | local typedecls, depslist = common_parse_type_decls(sym, {}, matches[3]) 479 | for _,typedecl in ipairs(typedecls) do 480 | make_sym_dep(sym, typedecl, vardeps, src) 481 | end 482 | end 483 | 484 | 485 | --------------------------------------------------- 486 | -- declaration 487 | --------------------------------------------------- 488 | 489 | -- qualifier func(...) qualifier; 490 | -- qualifier (func)(...) qualifier; 491 | local FUNC_DECL_CAPTURE="^".. 492 | "("..QUALIFIER..")"..SPACE_OR_STAR.."%(?"..OPT_SPACE_OR_STAR.. 493 | "("..TYPENAME..")"..OPTSPACE.."%)?"..OPTSPACE.. 494 | "("..ARG_VAR_LIST..")".. 495 | OPT_QUALIFIER 496 | local FUNC_DECL = FUNC_DECL_CAPTURE..";" 497 | local function parse_func_decl(sym, opaque, deps, matches, src) 498 | src = assert(restore_src(src, opaque), "invalid restore src") 499 | local typename, attr = common_parse_qualifier(sym, matches[1], opaque) 500 | local funcdecl = matches[2] 501 | local depends = {} 502 | common_parse_argument_deps(sym, depends, matches[3]) 503 | table.insert(depends, typename) 504 | make_func_dep(sym, funcdecl, depends, src) 505 | end 506 | 507 | -- qualifier (*ho_func(...))(...) qualifier; 508 | local HO_FUNC_DECL_CAPTURE="^".. 509 | "("..QUALIFIER..")"..SPACE_OR_STAR.."%("..OPT_SPACE_OR_STAR.. 510 | "("..OPT_TYPENAME..")"..OPTSPACE.. 511 | "(".."%b()"..")"..OPTSPACE.."%)"..OPTSPACE.. 512 | "("..ARG_VAR_LIST..")".. 513 | OPT_QUALIFIER 514 | local HO_FUNC_DECL = HO_FUNC_DECL_CAPTURE..";" 515 | local function parse_high_order_func_decl(sym, opaque, deps, matches, src) 516 | src = restore_src(src, opaque) 517 | local typename, attr = common_parse_qualifier(sym, matches[1], opaque) 518 | local funcdecl = matches[2] 519 | local depends = {} 520 | common_parse_argument_deps(sym, depends, matches[3]) 521 | common_parse_argument_deps(sym, depends, matches[4]) 522 | table.insert(depends, typename) 523 | make_func_dep(sym, funcdecl, depends, src) 524 | end 525 | 526 | -- qualifier func(...) qualifier { ... }; 527 | local INLINE_FUNC_DECL = FUNC_DECL_CAPTURE .. CODE_BLOCK 528 | local function parse_inline_func_decl(sym, opaque, deps, matches, src) 529 | -- because lj cannot access inline function (I think), no dependency added. 530 | -- src = restore_src(src, opaque) 531 | end 532 | 533 | -- struct struct_t {...}; 534 | -- union union_t {...}; 535 | -- enum enum_t {...}; 536 | local STRUCTURE_DECL="^".. 537 | "("..STRUCTURE_SYMBOL..")"..SPACE.. 538 | "("..TYPENAME..")"..OPTSPACE.. 539 | "("..STRUCT_VAR_LIST..")"..OPT_QUALIFIER..";" 540 | local function parse_structure_decl(sym, opaque, deps, matches, src) 541 | src = restore_src(src, opaque) 542 | local typename, vardeps = get_real_sym_name(matches[1], matches[2]), {} 543 | common_parse_struct_deps(sym, vardeps, matches[3], typename) 544 | make_sym_dep(sym, typename, vardeps, src) 545 | end 546 | 547 | -- enum {...}; 548 | local ANON_STRUCTURE_DECL="^".. 549 | "("..STRUCTURE_SYMBOL..")"..OPTSPACE.. 550 | "("..STRUCT_VAR_LIST..")"..OPTSPACE..";" 551 | local function parse_anon_structure_decl(sym, opaque, deps, matches, src) 552 | -- no new dependency added 553 | -- src = restore_src(src, opaque) 554 | end 555 | 556 | -- struct struct_t; 557 | -- union union_t; 558 | -- enum enum_t; 559 | local STRUCTURE_PREDECL="^".. 560 | "("..STRUCTURE_SYMBOL..")"..SPACE.. 561 | "("..TYPENAME..")"..OPTSPACE..";" 562 | local function parse_structure_predecl(sym, opaque, deps, matches, src) 563 | src = restore_src(src, opaque) 564 | local typename = get_real_sym_name(matches[1], matches[2]) 565 | make_incomplete_decl(sym, typename, src) 566 | end 567 | 568 | -- qualifier *val1[size1], *val2[size2], ..., *valN[sizeN]; 569 | local EXTERN_DECL_CAPTURE="^".. 570 | "("..QUALIFIER..")".. 571 | "("..ALL_REMAINS..")" 572 | local EXTERN_DECL = EXTERN_DECL_CAPTURE .. ";" 573 | local function parse_extern_decl(sym, opaque, deps, matches, src) 574 | -- no new dependency added 575 | -- src = restore_src(src, opaque) 576 | end 577 | 578 | -- qualifier (*fval1)(...) qualifier; 579 | local EXTERN_FUNC_DECL="^".. 580 | "("..QUALIFIER..")".. 581 | "("..FUNC_TYPE_SYMBOL..")".. 582 | OPT_QUALIFIER..";" 583 | local function parse_extern_func_decl(sym, opaque, deps, matches, src) 584 | -- no new dependency added 585 | -- src = restore_src(src, opaque) 586 | end 587 | 588 | 589 | --------------------------------------------------- 590 | -- struct decl 591 | --------------------------------------------------- 592 | -- qualifier *val1[size1], ..., *valN[size2]; 593 | -- qualifier val1:bit1, val2:bit2, ..., valN:bitN; 594 | local STRUCT_VAR_VARIABLE=EXTERN_DECL_CAPTURE 595 | local function parse_struct_var_variable(sym, opaque, deps, matches, src) 596 | -- $1 : qualifier 597 | -- $2 : vardecls 598 | local typename, attr = common_parse_qualifier(sym, matches[1], opaque) 599 | assert(#typename > 0, "invalid qualifier:", matches[1]) 600 | table.insert(deps, typename) 601 | end 602 | 603 | -- qualifier (**fval)(...) qualifier; 604 | local STRUCT_VAR_FUNC=FUNC_DECL_CAPTURE 605 | local function parse_struct_var_func(sym, opaque, deps, matches, src) 606 | local typename, attr = common_parse_qualifier(sym, matches[1], opaque) 607 | local argdeps = {} 608 | common_parse_argument_deps(sym, deps, matches[3]) 609 | table.insert(deps, typename) 610 | end 611 | 612 | -- qualifier (**hofval(...))(...) qualifier; 613 | local STRUCT_VAR_HO_FUNC=HO_FUNC_DECL_CAPTURE 614 | local function parse_struct_var_high_order_func(sym, opaque, deps, matches, src) 615 | local typename, attr = common_parse_qualifier(sym, matches[1], opaque) 616 | local argdeps = {} 617 | common_parse_argument_deps(sym, deps, matches[3]) 618 | common_parse_argument_deps(sym, deps, matches[4]) 619 | table.insert(deps, typename) 620 | end 621 | 622 | -- (struct/union/enum) {...} *val1, *val2, ..., *valN; 623 | local STRUCT_VAR_ANON_STRUCT="^".. 624 | "("..STRUCTURE_SYMBOL..")"..SPACE.. 625 | "("..STRUCT_VAR_LIST..")"..OPT_SPACE_OR_STAR.. 626 | "("..ALL_REMAINS..")" 627 | local function parse_struct_var_anon_struct(sym, opaque, deps, matches, src) 628 | common_parse_struct_deps(sym, deps, matches[2], opaque) 629 | end 630 | 631 | -- (struct/union/enum) typename_t {...} *val1, *val2, ..., *valN; 632 | local STRUCT_VAR_STRUCT="^".. 633 | "("..STRUCTURE_SYMBOL..")"..SPACE.. 634 | "("..TYPENAME..")"..OPTSPACE.. 635 | "("..STRUCT_VAR_LIST..")"..OPTSPACE.. 636 | "("..ALL_REMAINS..")" 637 | local function parse_struct_var_struct(sym, opaque, deps, matches, src) 638 | local vardeps = {} 639 | local typename = get_real_sym_name(matches[1], matches[2]) 640 | common_parse_struct_deps(sym, vardeps, matches[3], opaque) 641 | -- currently, struct declaration in struct cannot be injected (empty string returns) 642 | make_sym_dep(sym, typename, vardeps, "") 643 | table.insert(deps, typename) 644 | end 645 | 646 | 647 | --------------------------------------------------- 648 | -- argument decl 649 | --------------------------------------------------- 650 | -- non_ext_qualifier type_t *val[size], 651 | local ARG_VAR="^".. 652 | "("..QUALIFIER..")".. 653 | "("..ALL_REMAINS_IN_ARG_DECL..")" 654 | local function parse_arg_var(sym, opaque, deps, matches, src) 655 | -- $1 : qualifier 656 | -- $2 : vardecls 657 | local typename, attr = common_parse_qualifier(sym, matches[1], opaque) 658 | assert(typename and #typename > 0, "invalid qualifier:["..matches[1].."]") 659 | table.insert(deps, typename) 660 | end 661 | 662 | -- qualifier retval_t (**fval)(...) qualifier, 663 | local ARG_VAR_FUNC="^".. 664 | "("..QUALIFIER..")"..SPACE_OR_STAR.."%(?"..SPACE_OR_STAR.. 665 | "("..OPT_TYPENAME..")"..OPTSPACE.."%)?"..OPTSPACE.. 666 | "("..ARG_VAR_LIST..")".. 667 | OPT_QUALIFIER 668 | local function parse_arg_var_func(sym, opaque, deps, matches, src) 669 | local typename, attr = common_parse_qualifier(sym, matches[1], opaque) 670 | assert(typename and #typename > 0, "invalid qualifier:["..matches[1].."]") 671 | common_parse_argument_deps(sym, deps, matches[3]) 672 | table.insert(deps, typename) 673 | end 674 | 675 | -- qualifier retval_t ((**fval)(...))(...) qualifier, 676 | local ARG_VAR_HO_FUNC=HO_FUNC_DECL_CAPTURE 677 | local function parse_arg_var_high_order_func(sym, opaque, deps, matches, src) 678 | local typename, attr = common_parse_qualifier(sym, matches[1], opaque) 679 | assert(typename and #typename > 0, "invalid qualifier:["..matches[1].."]") 680 | common_parse_argument_deps(sym, deps, matches[3]) 681 | common_parse_argument_deps(sym, deps, matches[4]) 682 | table.insert(deps, typename) 683 | end 684 | 685 | 686 | --------------------------------------------------- 687 | -- pattern list (define its matching order) 688 | --------------------------------------------------- 689 | MAIN_PATTERN_LIST = { 690 | -- structure contains ; in its declaration, so check before other pattern. 691 | -- to prevent from matching wrongly. 692 | STRUCTURE_TYPEDEF, 693 | ANON_STRUCTURE_TYPEDEF, 694 | STRUCTURE_DECL, 695 | ANON_STRUCTURE_DECL, 696 | TYPEDEF, 697 | INLINE_FUNC_DECL, 698 | HO_FUNC_DECL, 699 | FUNC_DECL, 700 | STRUCTURE_PREDECL, 701 | EXTERN_DECL, 702 | EXTERN_FUNC_DECL, 703 | } 704 | 705 | STRUCT_PATTERN_LIST = { 706 | STRUCT_VAR_HO_FUNC, 707 | STRUCT_VAR_FUNC, 708 | STRUCT_VAR_STRUCT, 709 | STRUCT_VAR_ANON_STRUCT, 710 | STRUCT_VAR_VARIABLE, 711 | } 712 | 713 | ARG_PATTERN_LIST = { 714 | ARG_VAR_HO_FUNC, 715 | ARG_VAR_FUNC, 716 | ARG_VAR, 717 | } 718 | 719 | TYPEDECL_PATTERN_LIST = { 720 | VAR_DECL_VAR_HO_FUNC, 721 | VAR_DECL_VAR_FUNC, 722 | VAR_DECL_VAR, 723 | } 724 | 725 | PARSER_MAP = { 726 | -- main 727 | [MAIN_PATTERN_LIST] = { 728 | [TYPEDEF] = parse_typedef, 729 | [STRUCTURE_TYPEDEF] = parse_structure_typedef, 730 | [ANON_STRUCTURE_TYPEDEF] = parse_anon_structure_typedef, 731 | [FUNC_DECL] = parse_func_decl, 732 | [HO_FUNC_DECL] = parse_high_order_func_decl, 733 | [STRUCTURE_DECL] = parse_structure_decl, 734 | [ANON_STRUCTURE_DECL] = parse_anon_structure_decl, 735 | [STRUCTURE_PREDECL] = parse_structure_predecl, 736 | [EXTERN_DECL] = parse_extern_decl, 737 | [EXTERN_FUNC_DECL] = parse_extern_func_decl, 738 | [INLINE_FUNC_DECL] = parse_inline_func_decl, 739 | }, 740 | -- struct var decl 741 | [STRUCT_PATTERN_LIST] = { 742 | [STRUCT_VAR_VARIABLE] = parse_struct_var_variable, 743 | [STRUCT_VAR_FUNC] = parse_struct_var_func, 744 | [STRUCT_VAR_HO_FUNC] = parse_struct_var_high_order_func, 745 | [STRUCT_VAR_ANON_STRUCT] = parse_struct_var_anon_struct, 746 | [STRUCT_VAR_STRUCT] = parse_struct_var_struct, 747 | }, 748 | -- arg decl 749 | [ARG_PATTERN_LIST] = { 750 | [ARG_VAR] = parse_arg_var, 751 | [ARG_VAR_FUNC] = parse_arg_var_func, 752 | [ARG_VAR_HO_FUNC] = parse_arg_var_high_order_func, 753 | [ARG_VAR_FUNC] = parse_arg_var_func, 754 | }, 755 | -- type decl 756 | [TYPEDECL_PATTERN_LIST] = { 757 | [VAR_DECL_VAR] = parse_var_decl_var, 758 | [VAR_DECL_VAR_FUNC] = parse_var_decl_var_func, 759 | [VAR_DECL_VAR_HO_FUNC] = parse_var_decl_var_high_order_func, 760 | } 761 | } 762 | 763 | --------------------------------------------------- 764 | -- parse main 765 | --------------------------------------------------- 766 | local function parse(tree, code) 767 | local sym = tree or new_sym_table() 768 | local attrs = {} 769 | local function inject_ext(a) 770 | table.insert(attrs, a) 771 | return "$"..#attrs.." " 772 | end 773 | -- parse and replace all __attribute__/__declspec/__asm 774 | code = code:gsub("__attribute__%s*%b()", inject_ext) 775 | :gsub("__declspec%s*%b()", inject_ext) 776 | :gsub("__asm_*%s*%b()", inject_ext) 777 | :gsub("__extension__", "") -- its ignored. 778 | return common_parser( 779 | sym, 780 | {}, 781 | code:gsub("^%s+", ""), 782 | MAIN_PATTERN_LIST, 783 | nil, -- pattern list itself define sep. 784 | attrs 785 | ) 786 | end 787 | 788 | local function traverse_cdef(tree, symbol, injected, depth) 789 | local sym = assert(tree[symbol], "cdef not found:["..symbol.."]") 790 | assert(#sym.name > 0, "invalid sym:"..sym.name) 791 | for _,dep in ipairs(sym.deps or {}) do 792 | if not injected.lookup[dep] then 793 | if not injected.seen[dep] then 794 | injected.seen[dep] = true 795 | traverse_cdef(tree, dep, injected, depth + 1) 796 | end 797 | end 798 | end 799 | if not injected.lookup[symbol] then 800 | injected.lookup[symbol] = true 801 | -- it is possible that multiple symbols defined in same cdef 802 | -- eg) typedef struct A {...} B; >> A and B is declared at the same time, 803 | -- so has same cdef. de-dupe that 804 | if not injected.chunks[sym.cdef] then 805 | injected.chunks[sym.cdef] = true 806 | table.insert(injected.list, sym) 807 | end 808 | end 809 | end 810 | 811 | local function get_name_in_sym(tree, symbol) 812 | local s, e = symbol:find('%s+') 813 | if s then 814 | local pfx = symbol:sub(1, s - 1) 815 | return pfx == "typename" and symbol:sub(e+1) or symbol 816 | else 817 | for _,pfx in ipairs({"struct", "func", "union", "enum"}) do 818 | local fsym = get_real_sym_name(pfx, symbol) 819 | if tree[fsym] then 820 | return fsym 821 | end 822 | end 823 | return symbol 824 | end 825 | end 826 | 827 | local function inject(tree, symbols, already_imported) 828 | local injected = { 829 | lookup = already_imported or {}, 830 | list = {}, 831 | seen = {}, 832 | chunks = {}, 833 | } 834 | if type(symbols) == 'table' then 835 | for _,symbol in ipairs(symbols) do 836 | if not injected.lookup[symbol] then 837 | traverse_cdef(tree, get_name_in_sym(tree, symbol), injected, 0) 838 | end 839 | end 840 | else 841 | for _,k in pairs(tree[1]) do 842 | if not injected.lookup[k] then 843 | -- print('inject:'..k..'['..tree[k].cdef..']') 844 | traverse_cdef(tree, k, injected, 0) 845 | end 846 | end 847 | end 848 | local cdef = "" 849 | table.sort(injected.list, function (e1, e2) return e1.prio < e2.prio end) 850 | for _,sym in ipairs(injected.list) do 851 | log("sym injected:["..sym.name.."]["..sym.cdef.."]") 852 | assert(sym.cdef, "invalid sym no cdef:"..sym.name) 853 | cdef = (cdef .. "\n" .. (sym.cdef or "")) 854 | end 855 | log("cdef injected:[["..cdef.."]]") 856 | return cdef 857 | end 858 | 859 | -- module 860 | return { 861 | parse = parse, 862 | inject = inject, 863 | name = get_name_in_sym, 864 | } 865 | -------------------------------------------------------------------------------- /ffiex/util.lua: -------------------------------------------------------------------------------- 1 | local _M = {} 2 | local ffi = require 'ffi' 3 | 4 | if ffi.os == "Windows" then 5 | _M.PATH_SEPS = "¥" 6 | else 7 | _M.PATH_SEPS = "/" 8 | end 9 | function _M.file_exists(file) 10 | if ffi.os ~= 'Windows' then 11 | return io.popen(([[if [ -e '%s' ]; then echo '1'; else echo '0'; fi]]):format(file)):read(1) == '1' 12 | else 13 | error('unsupported OS') 14 | end 15 | end 16 | function _M.current_path() 17 | local data = debug.getinfo(1) 18 | return data.source:match('@(.+)'.._M.PATH_SEPS..'.+$') 19 | end 20 | local cache_dir = _M.current_path().._M.PATH_SEPS..'cache' 21 | local version_file = cache_dir.._M.PATH_SEPS..'version' 22 | local builtin_paths = cache_dir.._M.PATH_SEPS..'builtin_paths' 23 | local builtin_defs = cache_dir.._M.PATH_SEPS..'builtin_defs' 24 | _M.path = { 25 | version_file = version_file, 26 | builtin_paths = builtin_paths, 27 | builtin_defs = builtin_defs, 28 | } 29 | 30 | -- gcc version cache 31 | function _M.gcc_version() 32 | local r = io.popen('which gcc'):read('*a') 33 | return #r > 0 and io.popen('gcc -v 2>&1'):read('*a') or nil 34 | end 35 | local function create_version_file_cache(v) 36 | v = v or _M.gcc_version() 37 | assert(v, "gcc need to be installed to create cache") 38 | local f = io.open(version_file, 'w') 39 | f:write(v) 40 | f:close() 41 | end 42 | 43 | -- add compiler predefinition 44 | local builtin_defs_cmd = 'echo | gcc -E -dM -' 45 | local function create_builtin_defs_cache() 46 | assert(_M.gcc_version(), "gcc need to be installed to create cache") 47 | os.execute(builtin_defs_cmd..'>'..builtin_defs) 48 | end 49 | function _M.builtin_defs() 50 | if _M.file_exists(version_file) then 51 | local v = _M.gcc_version() 52 | if v and (v ~= io.popen(('cat %s'):format(version_file)):read('*a')) then 53 | create_builtin_defs_cache() 54 | create_version_file_cache(v) 55 | end 56 | return io.popen(([[cat %s]]):format(builtin_defs)) 57 | end 58 | return io.popen(builtin_defs_cmd) 59 | end 60 | function _M.add_builtin_defs(state) 61 | local p = _M.builtin_defs() 62 | local predefs = p:read('*a') 63 | state:cdef(predefs) 64 | p:close() 65 | -- os dependent tweak. 66 | if ffi.os == 'OSX' then 67 | -- luajit cannot parse objective-C code correctly 68 | -- e.g. int atexit_b(void (^)(void)) ; 69 | state:undef({"__BLOCKS__"}) 70 | end 71 | end 72 | function _M.clear_builtin_defs(state) 73 | local p = io.popen(builtin_defs_cmd) 74 | local undefs = {} 75 | while true do 76 | local line = p:read('*l') 77 | if line then 78 | local tmp,cnt = line:gsub('^#define%s+([_%w]+)%s+.*', '%1') 79 | if cnt > 0 then 80 | table.insert(undefs, tmp) 81 | end 82 | else 83 | break 84 | end 85 | end 86 | state:undef(undefs) 87 | p:close() 88 | end 89 | 90 | -- add compiler built in header search path 91 | local builtin_paths_cmd = 'echo | gcc -xc -v - 2>&1 | cat 2>/dev/null' 92 | function create_builtin_paths_cache() 93 | assert(_M.gcc_version(), "gcc need to be installed to create cache") 94 | os.execute(builtin_paths_cmd..'>'..builtin_paths) 95 | end 96 | function _M.builtin_paths() 97 | if _M.file_exists(version_file) then 98 | local v = _M.gcc_version() 99 | if v and (v ~= io.popen(('cat %s'):format(version_file)):read('*a')) then 100 | create_builtin_paths_cache() 101 | create_version_file_cache(v) 102 | end 103 | return io.popen(([[cat %s]]):format(builtin_paths)) 104 | end 105 | return io.popen(builtin_paths_cmd) 106 | end 107 | function _M.add_builtin_paths(state) 108 | local p = _M.builtin_paths() 109 | local search_path_start 110 | while true do 111 | -- TODO : parsing unstructured compiler output. 112 | -- that is not stable way to get search paths. 113 | -- but I cannot find better way than this. 114 | local line = p:read('*l') 115 | if not line then break end 116 | -- print('line = ', line) 117 | if search_path_start then 118 | local tmp,cnt = line:gsub('^%s+(.*)', '%1') 119 | if cnt > 0 then 120 | -- remove unnecessary output of osx clang. 121 | tmp = tmp:gsub(' %(framework directory%)', '') 122 | -- print('builtin_paths:'..tmp) 123 | state:path(tmp, true) 124 | else 125 | break 126 | end 127 | elseif line:find('#include <...>') then 128 | search_path_start = true 129 | end 130 | end 131 | end 132 | function _M.create_builtin_config_cache() 133 | create_version_file_cache() 134 | create_builtin_paths_cache() 135 | create_builtin_defs_cache() 136 | os.execute('chmod -R 766 '..cache_dir) 137 | end 138 | function _M.clear_builtin_config_cache() 139 | os.execute('rm '..cache_dir.._M.PATH_SEPS.."*") 140 | end 141 | 142 | return _M 143 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # install luajit from git HEAD 3 | 4 | luarocks remove ffiex 5 | luarocks pack ffiex*.rockspec 6 | luarocks unpack ffiex*.src.rock 7 | pushd ffiex*/ffiex 8 | luarocks make 9 | popd 10 | OUT=`luajit install_test.lua` 11 | if [ "$?" -ne "0" ]; 12 | then 13 | echo "test fails" 14 | exit -2 15 | fi 16 | rm ffiex-*.src.rock 17 | find . -type d -name "ffiex-*" -exec rm -rf {} \; 18 | if [ "$OUT" -ne "1000" ]; 19 | then 20 | exit -1 21 | fi 22 | echo "install success" 23 | -------------------------------------------------------------------------------- /install_test.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | local lib,ext = ffi.csrc('test', [[ 3 | #include 4 | extern void test(int id) { printf("%d", id); } 5 | ]]) 6 | lib.test(1000) 7 | -------------------------------------------------------------------------------- /launch.lua: -------------------------------------------------------------------------------- 1 | local ok, r = pcall(loadfile, arg[1]) 2 | if ok and r then 3 | ok, r = pcall(r) 4 | if ok and r then 5 | os.exit(0) 6 | else 7 | print('fail to test:'..arg[1], r) 8 | os.exit(-1) 9 | end 10 | else 11 | print('fail to load test:'..arg[1], r) 12 | os.exit(-2) 13 | end 14 | -------------------------------------------------------------------------------- /test.lua: -------------------------------------------------------------------------------- 1 | local dir = io.popen('ls test') 2 | while true do 3 | local file = dir:read() 4 | if not file then break end 5 | file = ('test/' .. file) 6 | if file:find('%.lua$') then 7 | print('----------- test: '..file) 8 | local ok, r = pcall(os.execute, "luajit launch.lua "..file) 9 | if ok and r then 10 | if r ~= 0 then 11 | print('test fails:' .. file .. '|' .. r) 12 | os.exit(-1) 13 | end 14 | else 15 | print('execute test fails:' .. file .. '|' .. tostring(r)) 16 | os.exit(-2) 17 | end 18 | else 19 | print('----------- not test:' .. file) 20 | end 21 | end 22 | print('test finished') 23 | -------------------------------------------------------------------------------- /test/cache.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | local util = require 'ffiex.util' 3 | 4 | ffi.init_cdef_cache() 5 | local v, d, p = io.open(util.path.version_file):read('*a'), 6 | io.open(util.path.builtin_defs):read('*a'), 7 | io.open(util.path.builtin_paths):read('*a') 8 | ffi.clear_cdef_cache() 9 | assert(v == util.gcc_version()) 10 | assert(d == util.builtin_defs():read('*a')) 11 | 12 | return true -------------------------------------------------------------------------------- /test/cast.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | ffi.cdef[[ 3 | #include 4 | #include 5 | ]] 6 | print(ffi.defs.SIOCGIFADDR) 7 | return true -------------------------------------------------------------------------------- /test/concat.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | ffi.cdef [[ 3 | typedef int FT_UInt32; 4 | typedef enum FT_Encoding_ 5 | { 6 | FT_ENCODING_NONE = ( ( (FT_UInt32)(0) << 24 ) | ( (FT_UInt32)(0) << 16 ) | ( (FT_UInt32)(0) << 8 ) | (FT_UInt32)(0) ), 7 | FT_ENCODING_MS_SYMBOL = ( ( (FT_UInt32)("s") << 24 ) | ( (FT_UInt32)("y") << 16 ) | ( (FT_UInt32)("m") << 8 ) | (FT_UInt32)("b") ), 8 | FT_ENCODING_UNICODE = ( ( (FT_UInt32)("u") << 24 ) | ( (FT_UInt32)("n") << 16 ) | ( (FT_UInt32)("i") << 8 ) | (FT_UInt32)("c") ), 9 | FT_ENCODING_SJIS = ( ( (FT_UInt32)("s") << 24 ) | ( (FT_UInt32)("j") << 16 ) | ( (FT_UInt32)("i") << 8 ) | (FT_UInt32)("s") ), 10 | FT_ENCODING_GB2312 = ( ( (FT_UInt32)("g") << 24 ) | ( (FT_UInt32)("b") << 16 ) | ( (FT_UInt32)(" ") << 8 ) | (FT_UInt32)(" ") ), 11 | FT_ENCODING_BIG5 = ( ( (FT_UInt32)("b") << 24 ) | ( (FT_UInt32)("i") << 16 ) | ( (FT_UInt32)("g") << 8 ) | (FT_UInt32)("5") ), 12 | FT_ENCODING_WANSUNG = ( ( (FT_UInt32)("w") << 24 ) | ( (FT_UInt32)("a") << 16 ) | ( (FT_UInt32)("n") << 8 ) | (FT_UInt32)("s") ), 13 | FT_ENCODING_JOHAB = ( ( (FT_UInt32)("j") << 24 ) | ( (FT_UInt32)("o") << 16 ) | ( (FT_UInt32)("h") << 8 ) | (FT_UInt32)("a") ), 14 | FT_ENCODING_MS_SJIS = FT_ENCODING_SJIS, 15 | FT_ENCODING_MS_GB2312 = FT_ENCODING_GB2312, 16 | FT_ENCODING_MS_BIG5 = FT_ENCODING_BIG5, 17 | FT_ENCODING_MS_WANSUNG = FT_ENCODING_WANSUNG, 18 | FT_ENCODING_MS_JOHAB = FT_ENCODING_JOHAB, 19 | FT_ENCODING_ADOBE_STANDARD = ( ( (FT_UInt32)("A") << 24 ) | ( (FT_UInt32)("D") << 16 ) | ( (FT_UInt32)("O") << 8 ) | (FT_UInt32)("B") ), 20 | FT_ENCODING_ADOBE_EXPERT = ( ( (FT_UInt32)("A") << 24 ) | ( (FT_UInt32)("D") << 16 ) | ( (FT_UInt32)("B") << 8 ) | (FT_UInt32)("E") ), 21 | FT_ENCODING_ADOBE_CUSTOM = ( ( (FT_UInt32)("A") << 24 ) | ( (FT_UInt32)("D") << 16 ) | ( (FT_UInt32)("B") << 8 ) | (FT_UInt32)("C") ), 22 | FT_ENCODING_ADOBE_LATIN_1 = ( ( (FT_UInt32)("l") << 24 ) | ( (FT_UInt32)("a") << 16 ) | ( (FT_UInt32)("t") << 8 ) | (FT_UInt32)("1") ), 23 | FT_ENCODING_OLD_LATIN_2 = ( ( (FT_UInt32)("l") << 24 ) | ( (FT_UInt32)("a") << 16 ) | ( (FT_UInt32)("t") << 8 ) | (FT_UInt32)("2") ), 24 | FT_ENCODING_APPLE_ROMAN = ( ( (FT_UInt32)("a") << 24 ) | ( (FT_UInt32)("r") << 16 ) | ( (FT_UInt32)("m") << 8 ) | (FT_UInt32)("n") ) 25 | } FT_Encoding; 26 | int sprintf(char *buf, const char *format, ...); 27 | ]] 28 | 29 | local p = ffi.new('FT_Encoding', "FT_ENCODING_GB2312") 30 | assert(p == 33686018, "invalid enum constant value:"..tostring(p)) 31 | return true 32 | -------------------------------------------------------------------------------- /test/deref.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | local st = ffi.cdef [[ 3 | #define DEREF(p) (*(int *)p) 4 | ]] 5 | local ffi_ptr = ffi.new('int[1]') 6 | ffi_ptr[0] = 111 7 | assert(ffi.defs.DEREF(tostring(ffi.cast('intptr_t', ffi_ptr))) == 111) 8 | 9 | return true 10 | -------------------------------------------------------------------------------- /test/expr.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | 3 | ffi.cdef [[ 4 | #if L'\0' - 1 > 0 5 | #define HOGE "hoge" 6 | #else 7 | #define HOGE "fuga" 8 | #endif 9 | ]] 10 | 11 | assert("fuga" == ffi.defs.HOGE) 12 | 13 | return true 14 | -------------------------------------------------------------------------------- /test/ffiex.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | -- ffi.__DEBUG_CDEF__ = true 3 | 4 | local pt 5 | if ffi.os == 'OSX' then 6 | ffi.search("/Applications/Xcode.app/Contents/Developer/usr", "stdarg.h", true) 7 | pt = ffi.C 8 | elseif ffi.os == 'Linux' then 9 | pt = ffi.load('pthread') 10 | end 11 | 12 | ffi.cdef [[ 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | ]] 20 | 21 | assert(pt.pthread_join) 22 | assert(ffi.C.malloc) 23 | assert(ffi.C.connect) 24 | assert(ffi.C.inet_ntoa) 25 | 26 | ffi.path "/usr/local/include/luajit-2.0" 27 | ffi.path "/Applications/Xcode.app/Contents/Developer/usr/lib/llvm-gcc/4.2.1/include" 28 | ffi.cdef "#include " 29 | 30 | assert(ffi.C.luaL_newstate, "could not parse lauxlib.h correctly") 31 | 32 | return true -------------------------------------------------------------------------------- /test/ffiex_csrc.lua_: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | 3 | return function (builder, setup) 4 | print("----------- test "..builder) 5 | ffi.copt(setup()) 6 | ncall = 0 7 | local lib,ext = ffi.csrc('test', [[ 8 | #if defined(__GNUC__) 9 | #include 10 | #include 11 | #else // use tcc original libc header. 12 | #include 13 | #endif 14 | #include 15 | #include "my.h" 16 | #if defined(_MYDEF) 17 | #define GEN_ID(x, y) (x + y) 18 | #else 19 | #define GEN_ID(x, y) (x * y) 20 | #endif 21 | #define MYID (_MYDEF2) 22 | extern void hello_csrc(int id, char *buffer) { sprintf(buffer, "id:%d", id); } 23 | extern bool gen_id_test(int x, int y, int r) { return r == GEN_ID(x, y); } 24 | void export(int id) { printf("%d", id); } 25 | static inline void not_export(int id) { 26 | printf("it should not export"); 27 | } 28 | ]]) 29 | assert(lib, "build error:"..tostring(ext)) 30 | 31 | local msg = ffi.new("char[256]") 32 | lib.hello_csrc(ffi.defs.MYID, msg) 33 | assert("id:101" == ffi.string(msg)) 34 | lib.hello_csrc(ffi.defs.GEN_ID(10, 20), msg) 35 | assert("id:30" == ffi.string(msg)) 36 | assert(lib.gen_id_test(11, 22, ffi.defs.GEN_ID(11, 22))) 37 | lib.hello_csrc(ffi.defs.MY_MACRO(2), msg) 38 | assert("id:246" == ffi.string(msg)) 39 | assert(lib.export); 40 | local ok, r = pcall(function () 41 | return lib.not_export(100) 42 | end) 43 | assert(not ok); 44 | 45 | local lib2,ext2 = ffi.csrc('./test/foo.c') 46 | assert(lib2.footest(ffi.defs.FOO_ID) == (777 * 2)) 47 | 48 | local lib3,ext3 = ffi.csrc('test2', [[ 49 | void bar(int id) { return id } 50 | ]]) 51 | 52 | assert(not lib3, "should be nil due to compile error") 53 | end 54 | -------------------------------------------------------------------------------- /test/foo.c: -------------------------------------------------------------------------------- 1 | #include "my.h" 2 | #define FOO_ID (777) 3 | int footest(int id) { 4 | return id * 2; 5 | } 6 | -------------------------------------------------------------------------------- /test/gcc.lua: -------------------------------------------------------------------------------- 1 | local tester,err = loadfile('test/ffiex_csrc.lua_') 2 | if tester then 3 | tester()("gcc", function () 4 | if ffi.os == 'Linux' then 5 | ffi.path("/usr/include/linux", true) 6 | end 7 | -- add local path 8 | ffi.path "./test/myheaders" 9 | ffi.cdef [[ 10 | #include 11 | #include 12 | #include 13 | int stat64(const char *path, struct stat *sb); 14 | ]] 15 | ffi.cdef "#include " 16 | 17 | local ncall = 0 18 | return { 19 | cc = "gcc", 20 | extra = {"-D_MYDEF", "-D_MYDEF2=101", "-O2", "-Wall"}, 21 | cache_callback = function (name, code, file, search) 22 | -- print('cacher', name, code, file, search) 23 | local st = ffi.new('struct stat[1]') 24 | if ffi.os == "OSX" then 25 | assert(0 == ffi.C.syscall(ffi.defs.SYS_stat64, file, st), "stat call fails") 26 | print(file..':modified@'..tostring(st[0].st_size).."|"..tostring(st[0].st_mtimespec.tv_sec)) 27 | elseif ffi.os == "Linux" then 28 | assert(0 == ffi.C.syscall(ffi.defs.SYS_stat, file, st), "stat call fails") 29 | print(file..':modified@'..tostring(st[0].st_size).."|"..tostring(st[0].st_mtim.tv_sec)) 30 | else 31 | assert(false, 'unsupported os:'..ffi.os) 32 | end 33 | if ncall < 2 then 34 | assert(name == 'test') 35 | assert(file:find('ffiex.csrc.lua'), "file name wrong:" .. file) 36 | elseif ncall < 4 then 37 | assert(name == './test/foo.c') 38 | assert(file:find('test/foo.c'), "file name wrong:" .. file) 39 | elseif ncall < 6 then 40 | assert(name == 'test2', "name wrong:"..name) 41 | assert(file:find('ffiex.csrc.lua'), "file name wrong:" .. file) 42 | end 43 | if (ncall % 2) == 0 then 44 | assert(search, "search should be true (because search object file from cache)") 45 | elseif (ncall % 2) == 1 then 46 | assert(not search, "search should be false (because caching object file mode)") 47 | end 48 | ncall = (ncall + 1) 49 | end 50 | } 51 | end) 52 | else 53 | print('fail to load tester:', err) 54 | end 55 | return true 56 | -------------------------------------------------------------------------------- /test/import.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | --ffi.__DEBUG_CDEF__ = true 3 | 4 | ffi.import({ 5 | "printf", 6 | "sprintf", 7 | }):from [[ 8 | #include 9 | ]] 10 | 11 | ffi.C.printf("%s is test\n", "test") 12 | 13 | local msg = ffi.new("char[256]") 14 | ffi.C.sprintf(msg, "%d:%d", ffi.new("int", 100), ffi.new("int", 200)) 15 | 16 | assert(ffi.string(msg) == "100:200") 17 | 18 | 19 | local lib 20 | if ffi.os == "OSX" then 21 | lib = ffi.C 22 | elseif ffi.os == "Linux" then 23 | lib = ffi.load("pthread") 24 | else 25 | error("invalid os: " .. ffi.os) 26 | end 27 | ffi.import({ 28 | "pthread_join", 29 | "pthread_create", 30 | "pthread_mutex_t", 31 | }):from [[ 32 | #include 33 | ]] 34 | 35 | assert(lib.pthread_join) 36 | assert(lib.pthread_create) 37 | 38 | return true 39 | -------------------------------------------------------------------------------- /test/import2.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | 3 | ffi.path "/usr/local/include/luajit-2.0" 4 | if ffi.os == 'OSX' then 5 | -- disable all __asm alias (because luajit cannot find aliasing symbols) 6 | ffi.cdef "#define __asm(exp)" 7 | end 8 | local lib 9 | if ffi.os == "OSX" then 10 | lib = ffi.C 11 | elseif ffi.os == "Linux" then 12 | lib = ffi.load("pthread") 13 | else 14 | error("invalid os: " .. ffi.os) 15 | end 16 | local symbols = { 17 | --> from pthread 18 | "pthread_t", "pthread_mutex_t", 19 | "pthread_mutex_lock", "pthread_mutex_unlock", 20 | "pthread_create", "pthread_join", "pthread_self", 21 | "pthread_equal", 22 | --> from luauxlib, lualib 23 | "luaL_newstate", "luaL_openlibs", 24 | "luaL_loadstring", "lua_pcall", "lua_tolstring", 25 | "lua_getfield", "lua_tointeger", 26 | "lua_settop", "lua_close", 27 | --> from time 28 | "nanosleep", 29 | } 30 | ffi.import(symbols):from [[ 31 | #include 32 | #include 33 | #include 34 | #include 35 | ]] 36 | for _,sym in ipairs(symbols) do 37 | if sym:find(".+_t$") then 38 | local ok,ct = pcall(ffi.typeof, sym) 39 | assert(ok, sym .. " not found") 40 | elseif sym:find("^pthread") then 41 | assert(lib[sym], sym .. " not found") 42 | else 43 | assert(ffi.C[sym], sym .. " not found") 44 | end 45 | end 46 | 47 | 48 | return true -------------------------------------------------------------------------------- /test/import3.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | -- ffi.__DEBUG_CDEF__ = true 3 | 4 | local s1, s2 = ffi.newstate(), ffi.newstate() 5 | 6 | s1:copt { cc = "gcc" } 7 | s2:copt { cc = "gcc" } 8 | 9 | s1:import({"nanosleep"}):from [[ 10 | #include 11 | ]] 12 | assert(ffi.imported_csymbols["struct timespec"], "timespec not imported") 13 | if ffi.os == "OSX" then 14 | s2:import({"func kevent"}):from [[ 15 | #include 16 | #include 17 | #include 18 | ]] 19 | 20 | assert(ffi.C.nanosleep) 21 | assert(ffi.C.kevent) 22 | elseif ffi.os == "Linux" then 23 | s2:import({"clock_gettime"}):from [[ 24 | #include 25 | ]] 26 | assert(ffi.C.nanosleep) 27 | local rt = ffi.load("rt") 28 | assert(rt.clock_gettime) 29 | end 30 | 31 | ffi.cdef [[ 32 | #include 33 | ]] 34 | 35 | assert(ffi.C.time) 36 | 37 | return true 38 | -------------------------------------------------------------------------------- /test/import4.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | --ffi.__DEBUG_CDEF__ = true 3 | local C = ffi.C 4 | 5 | ffi.import({"printf", "sprintf"}):from [[ 6 | #include 7 | ]] 8 | 9 | assert(C.printf) 10 | assert(C.sprintf) 11 | local ok, r = pcall(getmetatable(C).__index, C, "fprintf") 12 | assert(not ok) 13 | 14 | 15 | ffi.cdef[[ 16 | #include "./test/myheaders/my.h" 17 | ]] 18 | 19 | assert(ffi.defs.MY_MACRO) 20 | local ok, r = pcall(getmetatable(C).__index, C, "fprintf") 21 | assert(not ok) 22 | 23 | return true -------------------------------------------------------------------------------- /test/lcpp.lua: -------------------------------------------------------------------------------- 1 | local lcpp = require 'ffiex.lcpp' 2 | -- unit test 3 | lcpp.test() 4 | -- other pathological tests 5 | lcpp.compile([[ 6 | #ifndef HOGE 7 | struct var { 8 | void (*__routine)(void *); // Routine to call 9 | void *__arg; // Argument to pass 10 | struct __darwin_pthread_handler_rec *__next; 11 | }; 12 | #endif // HOGE]]) 13 | 14 | return true 15 | -------------------------------------------------------------------------------- /test/ljtype.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | ffi.cdef [[ 3 | typedef wchar_t wchar2_t; 4 | typedef intptr_t intptr2_t; 5 | typedef uintptr_t uintptr2_t; 6 | typedef ptrdiff_t ptrdiff2_t; 7 | typedef size_t size2_t; 8 | ]] 9 | 10 | return true 11 | -------------------------------------------------------------------------------- /test/macro.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | 3 | ffi.cdef[[ 4 | enum { 5 | HOGE = 1, 6 | #define HOGE HOGE 7 | } 8 | ]] 9 | 10 | assert(ffi.defs.HOGE == "HOGE") 11 | 12 | return true -------------------------------------------------------------------------------- /test/myheaders/my.h: -------------------------------------------------------------------------------- 1 | #if !defined(__MY_H__) 2 | #define __MY_H__ 3 | 4 | #define MY_MACRO(x) (x * 123) 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /test/myheaders/pdcurses.h: -------------------------------------------------------------------------------- 1 | /* Public Domain Curses */ 2 | 3 | /* $Id: curses.h,v 1.295 2008/07/15 17:13:25 wmcbrine Exp $ */ 4 | 5 | /*----------------------------------------------------------------------* 6 | * PDCurses * 7 | *----------------------------------------------------------------------*/ 8 | 9 | #ifndef __PDCURSES__ 10 | #define __PDCURSES__ 1 11 | 12 | /*man-start************************************************************** 13 | 14 | PDCurses definitions list: (Only define those needed) 15 | 16 | XCURSES True if compiling for X11. 17 | PDC_RGB True if you want to use RGB color definitions 18 | (Red = 1, Green = 2, Blue = 4) instead of BGR. 19 | PDC_WIDE True if building wide-character support. 20 | PDC_DLL_BUILD True if building a Win32 DLL. 21 | NCURSES_MOUSE_VERSION Use the ncurses mouse API instead 22 | of PDCurses' traditional mouse API. 23 | 24 | PDCurses portable platform definitions list: 25 | 26 | PDC_BUILD Defines API build version. 27 | PDCURSES Enables access to PDCurses-only routines. 28 | XOPEN Always true. 29 | SYSVcurses True if you are compiling for SYSV portability. 30 | BSDcurses True if you are compiling for BSD portability. 31 | 32 | **man-end****************************************************************/ 33 | 34 | #define PDC_BUILD 3401 35 | #define PDCURSES 1 /* PDCurses-only routines */ 36 | #define XOPEN 1 /* X/Open Curses routines */ 37 | #define SYSVcurses 1 /* System V Curses routines */ 38 | #define BSDcurses 1 /* BSD Curses routines */ 39 | #define CHTYPE_LONG 2 /* size of chtype; 1= long (32-bit), 2=int64 */ 40 | 41 | /*----------------------------------------------------------------------*/ 42 | 43 | #include 44 | #include 45 | #include 46 | #include /* Required by X/Open usage below */ 47 | 48 | #ifdef PDC_WIDE 49 | # include 50 | #endif 51 | 52 | #if defined(__cplusplus) || defined(__cplusplus__) || defined(__CPLUSPLUS) 53 | extern "C" 54 | { 55 | # define bool _bool 56 | #endif 57 | 58 | /*---------------------------------------------------------------------- 59 | * 60 | * PDCurses Manifest Constants 61 | * 62 | */ 63 | 64 | #ifndef FALSE 65 | # define FALSE 0 66 | #endif 67 | #ifndef TRUE 68 | # define TRUE 1 69 | #endif 70 | #ifndef NULL 71 | # define NULL (void *)0 72 | #endif 73 | #ifndef ERR 74 | # define ERR (-1) 75 | #endif 76 | #ifndef OK 77 | # define OK 0 78 | #endif 79 | 80 | /*---------------------------------------------------------------------- 81 | * 82 | * PDCurses Type Declarations 83 | * 84 | */ 85 | 86 | //typedef unsigned char bool; /* PDCurses Boolean type */ 87 | 88 | #ifdef CHTYPE_LONG 89 | #if(CHTYPE_LONG >= 2) /* "non-standard" 64-bit chtypes */ 90 | typedef uint64_t chtype; 91 | #else /* "Standard" CHTYPE_LONG case, 32-bit: */ 92 | # if _LP64 93 | typedef unsigned int chtype; 94 | # else 95 | typedef unsigned long chtype; /* 16-bit attr + 16-bit char */ 96 | # endif 97 | # endif 98 | #else 99 | typedef unsigned short chtype; /* 8-bit attr + 8-bit char */ 100 | #endif 101 | 102 | #ifdef PDC_WIDE 103 | typedef chtype cchar_t; 104 | #endif 105 | 106 | typedef chtype attr_t; 107 | 108 | /*---------------------------------------------------------------------- 109 | * 110 | * PDCurses Mouse Interface -- SYSVR4, with extensions 111 | * 112 | */ 113 | 114 | /* Most flavors of PDCurses support three buttons. Win32a supports */ 115 | /* these plus two "extended" buttons. But we'll set this macro to */ 116 | /* six, allowing future versions to support up to nine total buttons. */ 117 | /* (The button states are broken up into two arrays to allow for the */ 118 | /* possibility of backward compatibility to DLLs compiled with only */ 119 | /* three mouse buttons.) */ 120 | 121 | #define PDC_MAX_MOUSE_BUTTONS 9 122 | #define PDC_N_EXTENDED_MOUSE_BUTTONS 6 123 | 124 | typedef struct 125 | { 126 | int x; /* absolute column, 0 based, measured in characters */ 127 | int y; /* absolute row, 0 based, measured in characters */ 128 | short button[3]; /* state of three "normal" buttons */ 129 | int changes; /* flags indicating what has changed with the mouse */ 130 | short xbutton[PDC_N_EXTENDED_MOUSE_BUTTONS]; /* state of ext buttons */ 131 | } MOUSE_STATUS; 132 | 133 | #define BUTTON_RELEASED 0x0000 134 | #define BUTTON_PRESSED 0x0001 135 | #define BUTTON_CLICKED 0x0002 136 | #define BUTTON_DOUBLE_CLICKED 0x0003 137 | #define BUTTON_TRIPLE_CLICKED 0x0004 138 | #define BUTTON_MOVED 0x0005 /* PDCurses */ 139 | #define WHEEL_SCROLLED 0x0006 /* PDCurses */ 140 | #define BUTTON_ACTION_MASK 0x0007 /* PDCurses */ 141 | 142 | #define PDC_BUTTON_SHIFT 0x0008 /* PDCurses */ 143 | #define PDC_BUTTON_CONTROL 0x0010 /* PDCurses */ 144 | #define PDC_BUTTON_ALT 0x0020 /* PDCurses */ 145 | #define BUTTON_MODIFIER_MASK 0x0038 /* PDCurses */ 146 | 147 | #define MOUSE_X_POS (Mouse_status.x) 148 | #define MOUSE_Y_POS (Mouse_status.y) 149 | 150 | /* 151 | * Bits associated with the .changes field: 152 | * 3 2 1 0 153 | * 210987654321098765432109876543210 154 | * 1 <- button 1 has changed 0 155 | * 10 <- button 2 has changed 1 156 | * 100 <- button 3 has changed 2 157 | * 1000 <- mouse has moved 3 158 | * 10000 <- mouse position report 4 159 | * 100000 <- mouse wheel up 5 160 | * 1000000 <- mouse wheel down 6 161 | * 10000000 <- mouse wheel left 7 162 | * 100000000 <- mouse wheel right 8 163 | * 1000000000 <- button 4 has changed 9 164 | * (NOTE: buttons 6 to 10000000000 <- button 5 has changed 10 165 | * 9 aren't implemented 100000000000 <- button 6 has changed 11 166 | * in any flavor of 1000000000000 <- button 7 has changed 12 167 | * PDCurses yet!) 10000000000000 <- button 8 has changed 13 168 | * 100000000000000 <- button 9 has changed 14 169 | */ 170 | 171 | #define PDC_MOUSE_MOVED 0x0008 172 | #define PDC_MOUSE_POSITION 0x0010 173 | #define PDC_MOUSE_WHEEL_UP 0x0020 174 | #define PDC_MOUSE_WHEEL_DOWN 0x0040 175 | #define PDC_MOUSE_WHEEL_LEFT 0x0080 176 | #define PDC_MOUSE_WHEEL_RIGHT 0x0100 177 | 178 | #define A_BUTTON_CHANGED (Mouse_status.changes & 7) 179 | #define MOUSE_MOVED (Mouse_status.changes & PDC_MOUSE_MOVED) 180 | #define MOUSE_POS_REPORT (Mouse_status.changes & PDC_MOUSE_POSITION) 181 | #define BUTTON_CHANGED(x) (Mouse_status.changes & (1 << ((x) - ((x)<4 ? 1 : -5)))) 182 | #define BUTTON_STATUS(x) (Mouse_status.button[(x) - 1]) 183 | #define MOUSE_WHEEL_UP (Mouse_status.changes & PDC_MOUSE_WHEEL_UP) 184 | #define MOUSE_WHEEL_DOWN (Mouse_status.changes & PDC_MOUSE_WHEEL_DOWN) 185 | #define MOUSE_WHEEL_LEFT (Mouse_status.changes & PDC_MOUSE_WHEEL_LEFT) 186 | #define MOUSE_WHEEL_RIGHT (Mouse_status.changes & PDC_MOUSE_WHEEL_RIGHT) 187 | 188 | /* mouse bit-masks */ 189 | 190 | #define BUTTON1_RELEASED 0x00000001L 191 | #define BUTTON1_PRESSED 0x00000002L 192 | #define BUTTON1_CLICKED 0x00000004L 193 | #define BUTTON1_DOUBLE_CLICKED 0x00000008L 194 | #define BUTTON1_TRIPLE_CLICKED 0x00000010L 195 | #define BUTTON1_MOVED 0x00000010L /* PDCurses */ 196 | 197 | #define BUTTON2_RELEASED 0x00000020L 198 | #define BUTTON2_PRESSED 0x00000040L 199 | #define BUTTON2_CLICKED 0x00000080L 200 | #define BUTTON2_DOUBLE_CLICKED 0x00000100L 201 | #define BUTTON2_TRIPLE_CLICKED 0x00000200L 202 | #define BUTTON2_MOVED 0x00000200L /* PDCurses */ 203 | 204 | #define BUTTON3_RELEASED 0x00000400L 205 | #define BUTTON3_PRESSED 0x00000800L 206 | #define BUTTON3_CLICKED 0x00001000L 207 | #define BUTTON3_DOUBLE_CLICKED 0x00002000L 208 | #define BUTTON3_TRIPLE_CLICKED 0x00004000L 209 | #define BUTTON3_MOVED 0x00004000L /* PDCurses */ 210 | 211 | /* For the ncurses-compatible functions only, BUTTON4_PRESSED and 212 | BUTTON5_PRESSED are returned for mouse scroll wheel up and down; 213 | otherwise PDCurses doesn't support buttons 4 and 5... except 214 | as described above for Win32a */ 215 | 216 | #define BUTTON4_RELEASED 0x00008000L 217 | #define BUTTON4_PRESSED 0x00010000L 218 | #define BUTTON4_CLICKED 0x00020000L 219 | #define BUTTON4_DOUBLE_CLICKED 0x00040000L 220 | #define BUTTON4_TRIPLE_CLICKED 0x00080000L 221 | 222 | #define BUTTON5_RELEASED 0x00100000L 223 | #define BUTTON5_PRESSED 0x00200000L 224 | #define BUTTON5_CLICKED 0x00400000L 225 | #define BUTTON5_DOUBLE_CLICKED 0x00800000L 226 | #define BUTTON5_TRIPLE_CLICKED 0x01000000L 227 | 228 | #define MOUSE_WHEEL_SCROLL 0x02000000L /* PDCurses */ 229 | #define BUTTON_MODIFIER_SHIFT 0x04000000L /* PDCurses */ 230 | #define BUTTON_MODIFIER_CONTROL 0x08000000L /* PDCurses */ 231 | #define BUTTON_MODIFIER_ALT 0x10000000L /* PDCurses */ 232 | 233 | #define ALL_MOUSE_EVENTS 0x1fffffffL 234 | #define REPORT_MOUSE_POSITION 0x20000000L 235 | 236 | /* ncurses mouse interface */ 237 | 238 | typedef unsigned long mmask_t; 239 | 240 | typedef struct 241 | { 242 | short id; /* unused, always 0 */ 243 | int x, y, z; /* x, y same as MOUSE_STATUS; z unused */ 244 | mmask_t bstate; /* equivalent to changes + button[], but 245 | in the same format as used for mousemask() */ 246 | } MEVENT; 247 | 248 | #ifdef NCURSES_MOUSE_VERSION 249 | # define BUTTON_SHIFT BUTTON_MODIFIER_SHIFT 250 | # define BUTTON_CONTROL BUTTON_MODIFIER_CONTROL 251 | # define BUTTON_CTRL BUTTON_MODIFIER_CONTROL 252 | # define BUTTON_ALT BUTTON_MODIFIER_ALT 253 | #else 254 | # define BUTTON_SHIFT PDC_BUTTON_SHIFT 255 | # define BUTTON_CONTROL PDC_BUTTON_CONTROL 256 | # define BUTTON_ALT PDC_BUTTON_ALT 257 | #endif 258 | 259 | /*---------------------------------------------------------------------- 260 | * 261 | * PDCurses Structure Definitions 262 | * 263 | */ 264 | 265 | typedef struct _win /* definition of a window */ 266 | { 267 | int _cury; /* current pseudo-cursor */ 268 | int _curx; 269 | int _maxy; /* max window coordinates */ 270 | int _maxx; 271 | int _begy; /* origin on screen */ 272 | int _begx; 273 | int _flags; /* window properties */ 274 | chtype _attrs; /* standard attributes and colors */ 275 | chtype _bkgd; /* background, normally blank */ 276 | bool _clear; /* causes clear at next refresh */ 277 | bool _leaveit; /* leaves cursor where it is */ 278 | bool _scroll; /* allows window scrolling */ 279 | bool _nodelay; /* input character wait flag */ 280 | bool _immed; /* immediate update flag */ 281 | bool _sync; /* synchronise window ancestors */ 282 | bool _use_keypad; /* flags keypad key mode active */ 283 | chtype **_y; /* pointer to line pointer array */ 284 | int *_firstch; /* first changed character in line */ 285 | int *_lastch; /* last changed character in line */ 286 | int _tmarg; /* top of scrolling region */ 287 | int _bmarg; /* bottom of scrolling region */ 288 | int _delayms; /* milliseconds of delay for getch() */ 289 | int _parx, _pary; /* coords relative to parent (0,0) */ 290 | struct _win *_parent; /* subwin's pointer to parent win */ 291 | } WINDOW; 292 | 293 | /* Avoid using the SCREEN struct directly -- use the corresponding 294 | functions if possible. This struct may eventually be made private. */ 295 | 296 | typedef struct 297 | { 298 | bool alive; /* if initscr() called, and not endwin() */ 299 | bool autocr; /* if cr -> lf */ 300 | bool cbreak; /* if terminal unbuffered */ 301 | bool echo; /* if terminal echo */ 302 | bool raw_inp; /* raw input mode (v. cooked input) */ 303 | bool raw_out; /* raw output mode (7 v. 8 bits) */ 304 | bool audible; /* FALSE if the bell is visual */ 305 | bool mono; /* TRUE if current screen is mono */ 306 | bool resized; /* TRUE if TERM has been resized */ 307 | bool orig_attr; /* TRUE if we have the original colors */ 308 | short orig_fore; /* original screen foreground color */ 309 | short orig_back; /* original screen foreground color */ 310 | int cursrow; /* position of physical cursor */ 311 | int curscol; /* position of physical cursor */ 312 | int visibility; /* visibility of cursor */ 313 | int orig_cursor; /* original cursor size */ 314 | int lines; /* new value for LINES */ 315 | int cols; /* new value for COLS */ 316 | unsigned long _trap_mbe; /* trap these mouse button events */ 317 | unsigned long _map_mbe_to_key; /* map mouse buttons to slk */ 318 | int mouse_wait; /* time to wait (in ms) for a 319 | button release after a press, in 320 | order to count it as a click */ 321 | int slklines; /* lines in use by slk_init() */ 322 | WINDOW *slk_winptr; /* window for slk */ 323 | int linesrippedoff; /* lines ripped off via ripoffline() */ 324 | int linesrippedoffontop; /* lines ripped off on 325 | top via ripoffline() */ 326 | int delaytenths; /* 1/10ths second to wait block 327 | getch() for */ 328 | bool _preserve; /* TRUE if screen background 329 | to be preserved */ 330 | int _restore; /* specifies if screen background 331 | to be restored, and how */ 332 | bool save_key_modifiers; /* TRUE if each key modifiers saved 333 | with each key press */ 334 | bool return_key_modifiers; /* TRUE if modifier keys are 335 | returned as "real" keys */ 336 | bool key_code; /* TRUE if last key is a special key; 337 | used internally by get_wch() */ 338 | #ifdef XCURSES 339 | int XcurscrSize; /* size of Xcurscr shared memory block */ 340 | bool sb_on; 341 | int sb_viewport_y; 342 | int sb_viewport_x; 343 | int sb_total_y; 344 | int sb_total_x; 345 | int sb_cur_y; 346 | int sb_cur_x; 347 | #endif 348 | short line_color; /* color of line attributes - default -1 */ 349 | } SCREEN; 350 | 351 | /*---------------------------------------------------------------------- 352 | * 353 | * PDCurses External Variables 354 | * 355 | */ 356 | 357 | #ifdef PDC_DLL_BUILD 358 | # ifdef CURSES_LIBRARY 359 | # define PDCEX __declspec(dllexport) extern 360 | # else 361 | # define PDCEX __declspec(dllimport) 362 | # endif 363 | #else 364 | # define PDCEX extern 365 | #endif 366 | 367 | PDCEX int LINES; /* terminal height */ 368 | PDCEX int COLS; /* terminal width */ 369 | PDCEX WINDOW *stdscr; /* the default screen window */ 370 | PDCEX WINDOW *curscr; /* the current screen image */ 371 | PDCEX SCREEN *SP; /* curses variables */ 372 | PDCEX MOUSE_STATUS Mouse_status; 373 | PDCEX int COLORS; 374 | PDCEX int COLOR_PAIRS; 375 | PDCEX int TABSIZE; 376 | PDCEX chtype acs_map[]; /* alternate character set map */ 377 | PDCEX char ttytype[]; /* terminal name/description */ 378 | 379 | /*man-start************************************************************** 380 | 381 | PDCurses Text Attributes 382 | ======================== 383 | 384 | Originally, PDCurses used a short (16 bits) for its chtype. To include 385 | color, a number of things had to be sacrificed from the strict Unix and 386 | System V support. The main problem was fitting all character attributes 387 | and color into an unsigned char (all 8 bits!). 388 | 389 | Today, PDCurses by default uses a long (32 bits) for its chtype, as in 390 | System V. The short chtype is still available, by undefining CHTYPE_LONG 391 | and rebuilding the library. 392 | 393 | The following is the structure of a win->_attrs chtype: 394 | 395 | short form: 396 | 397 | ------------------------------------------------- 398 | |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0| 399 | ------------------------------------------------- 400 | color number | attrs | character eg 'a' 401 | 402 | The available non-color attributes are bold, reverse and blink. Others 403 | have no effect. The high order char is an index into an array of 404 | physical colors (defined in color.c) -- 32 foreground/background color 405 | pairs (5 bits) plus 3 bits for other attributes. 406 | 407 | long form: 408 | 409 | ---------------------------------------------------------------------------- 410 | |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|..| 3| 2| 1| 0| 411 | ---------------------------------------------------------------------------- 412 | color number | modifiers | character eg 'a' 413 | 414 | The available non-color attributes are bold, underline, invisible, 415 | right-line, left-line, protect, reverse and blink. 256 color pairs (8 416 | bits), 8 bits for other attributes, and 16 bits for character data. 417 | 418 | Note that there is now a "super-long" 64-bit form, available by 419 | defining CHTYPE_LONG to be 2: 420 | 421 | ------------------------------------------------------------------------------- 422 | |63|62|61|60|59|..|34|33|32|31|30|29|28|..|22|21|20|19|18|17|16|..| 3| 2| 1| 0| 423 | ------------------------------------------------------------------------------- 424 | color number | modifiers | character eg 'a' 425 | 426 | 427 | We take five more bits for the character (thus allowing Unicode values 428 | past 64K; UTF-16 can go up to 0x10ffff, requiring 21 bits total), and 429 | four more bits for attributes. Two are currently used as A_OVERLINE and 430 | A_STRIKEOUT; two more are reserved for future use. 31 bits are then used 431 | for color. These are usually just treated as the usual palette 432 | indices, and range from 0 to 255. However, if bit 63 is 433 | set, the remaining 30 bits are interpreted as foreground RGB (first 434 | fifteen bits, five bits for each of the three channels) and background RGB 435 | (same scheme using the remaining 15 bits.) 436 | 437 | **man-end****************************************************************/ 438 | 439 | /*** Video attribute macros ***/ 440 | 441 | #define A_NORMAL (chtype)0 442 | 443 | #ifdef CHTYPE_LONG 444 | 445 | # if(CHTYPE_LONG >= 2) /* 64-bit chtypes */ 446 | # define PDC_CHARTEXT_BITS 21 447 | # define A_CHARTEXT (chtype)( (0x1 << PDC_CHARTEXT_BITS) - 1) 448 | # define A_ALTCHARSET ((chtype)0x001 << PDC_CHARTEXT_BITS) 449 | # define A_RIGHTLINE ((chtype)0x002 << PDC_CHARTEXT_BITS) 450 | # define A_LEFTLINE ((chtype)0x004 << PDC_CHARTEXT_BITS) 451 | # define A_INVIS ((chtype)0x008 << PDC_CHARTEXT_BITS) 452 | # define A_UNDERLINE ((chtype)0x010 << PDC_CHARTEXT_BITS) 453 | # define A_REVERSE ((chtype)0x020 << PDC_CHARTEXT_BITS) 454 | # define A_BLINK ((chtype)0x040 << PDC_CHARTEXT_BITS) 455 | # define A_BOLD ((chtype)0x080 << PDC_CHARTEXT_BITS) 456 | # define A_OVERLINE ((chtype)0x100 << PDC_CHARTEXT_BITS) 457 | # define A_STRIKEOUT ((chtype)0x200 << PDC_CHARTEXT_BITS) 458 | # define A_DIM ((chtype)0x400 << PDC_CHARTEXT_BITS) 459 | #if 0 460 | /* May come up with a use for this bit */ 461 | /* someday; reserved for the future: */ 462 | # define A_FUTURE_2 ((chtype)0x800 << PDC_CHARTEXT_BITS) 463 | #endif 464 | # define PDC_COLOR_SHIFT (PDC_CHARTEXT_BITS + 12) 465 | # define A_COLOR ((chtype)0x7fffffff << PDC_COLOR_SHIFT) 466 | # define A_RGB_COLOR ((chtype)0x40000000 << PDC_COLOR_SHIFT) 467 | # define A_ATTRIBUTES (((chtype)0xfff << PDC_CHARTEXT_BITS) | A_COLOR) 468 | # define A_RGB( rfore, gfore, bfore, rback, gback, bback) \ 469 | (( (((chtype)(bfore) << 25) \ 470 | | ((chtype)(gfore) << 20) \ 471 | | ((chtype)(rfore) << 15) \ 472 | | ((chtype)(bback) << 10) \ 473 | | ((chtype)(gback) << 5) \ 474 | | ((chtype)(rback) )) << PDC_COLOR_SHIFT) | A_RGB_COLOR) 475 | # else /* plain ol' 32-bit chtypes */ 476 | # define A_OVERLINE A_NORMAL 477 | # define A_STRIKEOUT A_NORMAL 478 | # define A_ATTRIBUTES (chtype)0xffff0000 479 | # define A_ALTCHARSET (chtype)0x00010000 480 | # define A_RIGHTLINE (chtype)0x00020000 481 | # define A_LEFTLINE (chtype)0x00040000 482 | # define A_INVIS (chtype)0x00080000 483 | # define A_UNDERLINE (chtype)0x00100000 484 | # define A_REVERSE (chtype)0x00200000 485 | # define A_BLINK (chtype)0x00400000 486 | # define A_BOLD (chtype)0x00800000 487 | # define A_CHARTEXT (chtype)0x0000ffff 488 | # define A_COLOR (chtype)0xff000000 489 | # define A_RGB_COLOR A_NORMAL 490 | # define A_DIM A_NORMAL 491 | # define PDC_COLOR_SHIFT 24 492 | #endif 493 | 494 | 495 | # define A_ITALIC A_INVIS 496 | # define A_PROTECT (A_UNDERLINE | A_LEFTLINE | A_RIGHTLINE) 497 | 498 | #else /* 16-bit chtypes */ 499 | # define A_BOLD (chtype)0x0100 /* X/Open */ 500 | # define A_REVERSE (chtype)0x0200 /* X/Open */ 501 | # define A_BLINK (chtype)0x0400 /* X/Open */ 502 | 503 | # define A_ATTRIBUTES (chtype)0xff00 /* X/Open */ 504 | # define A_CHARTEXT (chtype)0x00ff /* X/Open */ 505 | # define A_COLOR (chtype)0xf800 /* System V */ 506 | 507 | # define A_ALTCHARSET A_NORMAL /* X/Open */ 508 | # define A_PROTECT A_NORMAL /* X/Open */ 509 | # define A_UNDERLINE A_NORMAL /* X/Open */ 510 | 511 | # define A_LEFTLINE A_NORMAL 512 | # define A_RIGHTLINE A_NORMAL 513 | # define A_ITALIC A_NORMAL 514 | # define A_INVIS A_NORMAL 515 | # define A_RGB_COLOR A_NORMAL 516 | # define A_DIM A_NORMAL 517 | 518 | # define PDC_COLOR_SHIFT 11 519 | #endif 520 | 521 | #define A_STANDOUT (A_REVERSE | A_BOLD) /* X/Open */ 522 | 523 | #define CHR_MSK A_CHARTEXT /* Obsolete */ 524 | #define ATR_MSK A_ATTRIBUTES /* Obsolete */ 525 | #define ATR_NRM A_NORMAL /* Obsolete */ 526 | 527 | /* For use with attr_t -- X/Open says, "these shall be distinct", so 528 | this is a non-conforming implementation. */ 529 | 530 | #define WA_NORMAL A_NORMAL 531 | 532 | #define WA_ALTCHARSET A_ALTCHARSET 533 | #define WA_BLINK A_BLINK 534 | #define WA_BOLD A_BOLD 535 | #define WA_DIM A_DIM 536 | #define WA_INVIS A_INVIS 537 | #define WA_LEFT A_LEFTLINE 538 | #define WA_PROTECT A_PROTECT 539 | #define WA_REVERSE A_REVERSE 540 | #define WA_RIGHT A_RIGHTLINE 541 | #define WA_STANDOUT A_STANDOUT 542 | #define WA_UNDERLINE A_UNDERLINE 543 | 544 | #define WA_HORIZONTAL A_NORMAL 545 | #define WA_LOW A_NORMAL 546 | #define WA_TOP A_NORMAL 547 | #define WA_VERTICAL A_NORMAL 548 | 549 | #define WA_ATTRIBUTES A_ATTRIBUTES 550 | 551 | /*** Alternate character set macros ***/ 552 | 553 | /* 'w' = 32-bit chtype; acs_map[] index | A_ALTCHARSET 554 | 'n' = 16-bit chtype; it gets the fallback set because no bit is 555 | available for A_ALTCHARSET */ 556 | 557 | #ifdef CHTYPE_LONG 558 | # define ACS_PICK(w, n) ((chtype)w | A_ALTCHARSET) 559 | #else 560 | # define ACS_PICK(w, n) ((chtype)n) 561 | #endif 562 | 563 | /* VT100-compatible symbols -- box chars */ 564 | 565 | #define ACS_ULCORNER ACS_PICK('l', '+') 566 | #define ACS_LLCORNER ACS_PICK('m', '+') 567 | #define ACS_URCORNER ACS_PICK('k', '+') 568 | #define ACS_LRCORNER ACS_PICK('j', '+') 569 | #define ACS_RTEE ACS_PICK('u', '+') 570 | #define ACS_LTEE ACS_PICK('t', '+') 571 | #define ACS_BTEE ACS_PICK('v', '+') 572 | #define ACS_TTEE ACS_PICK('w', '+') 573 | #define ACS_HLINE ACS_PICK('q', '-') 574 | #define ACS_VLINE ACS_PICK('x', '|') 575 | #define ACS_PLUS ACS_PICK('n', '+') 576 | 577 | /* VT100-compatible symbols -- other */ 578 | 579 | #define ACS_S1 ACS_PICK('o', '-') 580 | #define ACS_S9 ACS_PICK('s', '_') 581 | #define ACS_DIAMOND ACS_PICK('`', '+') 582 | #define ACS_CKBOARD ACS_PICK('a', ':') 583 | #define ACS_DEGREE ACS_PICK('f', '\'') 584 | #define ACS_PLMINUS ACS_PICK('g', '#') 585 | #define ACS_BULLET ACS_PICK('~', 'o') 586 | 587 | /* Teletype 5410v1 symbols -- these are defined in SysV curses, but 588 | are not well-supported by most terminals. Stick to VT100 characters 589 | for optimum portability. */ 590 | 591 | #define ACS_LARROW ACS_PICK(',', '<') 592 | #define ACS_RARROW ACS_PICK('+', '>') 593 | #define ACS_DARROW ACS_PICK('.', 'v') 594 | #define ACS_UARROW ACS_PICK('-', '^') 595 | #define ACS_BOARD ACS_PICK('h', '#') 596 | #define ACS_LANTERN ACS_PICK('i', '*') 597 | #define ACS_BLOCK ACS_PICK('0', '#') 598 | 599 | /* That goes double for these -- undocumented SysV symbols. Don't use 600 | them. */ 601 | 602 | #define ACS_S3 ACS_PICK('p', '-') 603 | #define ACS_S7 ACS_PICK('r', '-') 604 | #define ACS_LEQUAL ACS_PICK('y', '<') 605 | #define ACS_GEQUAL ACS_PICK('z', '>') 606 | #define ACS_PI ACS_PICK('{', 'n') 607 | #define ACS_NEQUAL ACS_PICK('|', '+') 608 | #define ACS_STERLING ACS_PICK('}', 'L') 609 | 610 | /* Box char aliases */ 611 | 612 | #define ACS_BSSB ACS_ULCORNER 613 | #define ACS_SSBB ACS_LLCORNER 614 | #define ACS_BBSS ACS_URCORNER 615 | #define ACS_SBBS ACS_LRCORNER 616 | #define ACS_SBSS ACS_RTEE 617 | #define ACS_SSSB ACS_LTEE 618 | #define ACS_SSBS ACS_BTEE 619 | #define ACS_BSSS ACS_TTEE 620 | #define ACS_BSBS ACS_HLINE 621 | #define ACS_SBSB ACS_VLINE 622 | #define ACS_SSSS ACS_PLUS 623 | 624 | /* cchar_t aliases */ 625 | 626 | #ifdef PDC_WIDE 627 | # define WACS_ULCORNER (&(acs_map['l'])) 628 | # define WACS_LLCORNER (&(acs_map['m'])) 629 | # define WACS_URCORNER (&(acs_map['k'])) 630 | # define WACS_LRCORNER (&(acs_map['j'])) 631 | # define WACS_RTEE (&(acs_map['u'])) 632 | # define WACS_LTEE (&(acs_map['t'])) 633 | # define WACS_BTEE (&(acs_map['v'])) 634 | # define WACS_TTEE (&(acs_map['w'])) 635 | # define WACS_HLINE (&(acs_map['q'])) 636 | # define WACS_VLINE (&(acs_map['x'])) 637 | # define WACS_PLUS (&(acs_map['n'])) 638 | 639 | # define WACS_S1 (&(acs_map['o'])) 640 | # define WACS_S9 (&(acs_map['s'])) 641 | # define WACS_DIAMOND (&(acs_map['`'])) 642 | # define WACS_CKBOARD (&(acs_map['a'])) 643 | # define WACS_DEGREE (&(acs_map['f'])) 644 | # define WACS_PLMINUS (&(acs_map['g'])) 645 | # define WACS_BULLET (&(acs_map['~'])) 646 | 647 | # define WACS_LARROW (&(acs_map[','])) 648 | # define WACS_RARROW (&(acs_map['+'])) 649 | # define WACS_DARROW (&(acs_map['.'])) 650 | # define WACS_UARROW (&(acs_map['-'])) 651 | # define WACS_BOARD (&(acs_map['h'])) 652 | # define WACS_LANTERN (&(acs_map['i'])) 653 | # define WACS_BLOCK (&(acs_map['0'])) 654 | 655 | # define WACS_S3 (&(acs_map['p'])) 656 | # define WACS_S7 (&(acs_map['r'])) 657 | # define WACS_LEQUAL (&(acs_map['y'])) 658 | # define WACS_GEQUAL (&(acs_map['z'])) 659 | # define WACS_PI (&(acs_map['{'])) 660 | # define WACS_NEQUAL (&(acs_map['|'])) 661 | # define WACS_STERLING (&(acs_map['}'])) 662 | 663 | # define WACS_BSSB WACS_ULCORNER 664 | # define WACS_SSBB WACS_LLCORNER 665 | # define WACS_BBSS WACS_URCORNER 666 | # define WACS_SBBS WACS_LRCORNER 667 | # define WACS_SBSS WACS_RTEE 668 | # define WACS_SSSB WACS_LTEE 669 | # define WACS_SSBS WACS_BTEE 670 | # define WACS_BSSS WACS_TTEE 671 | # define WACS_BSBS WACS_HLINE 672 | # define WACS_SBSB WACS_VLINE 673 | # define WACS_SSSS WACS_PLUS 674 | #endif 675 | 676 | /*** Color macros ***/ 677 | 678 | #define COLOR_BLACK 0 679 | 680 | #ifdef PDC_RGB /* RGB */ 681 | # define COLOR_RED 1 682 | # define COLOR_GREEN 2 683 | # define COLOR_BLUE 4 684 | #else /* BGR */ 685 | # define COLOR_BLUE 1 686 | # define COLOR_GREEN 2 687 | # define COLOR_RED 4 688 | #endif 689 | 690 | #define COLOR_CYAN (COLOR_BLUE | COLOR_GREEN) 691 | #define COLOR_MAGENTA (COLOR_RED | COLOR_BLUE) 692 | #define COLOR_YELLOW (COLOR_RED | COLOR_GREEN) 693 | 694 | #define COLOR_WHITE 7 695 | 696 | /*---------------------------------------------------------------------- 697 | * 698 | * Function and Keypad Key Definitions. 699 | * Many are just for compatibility. 700 | * 701 | */ 702 | 703 | #ifdef PDC_WIDE 704 | #define KEY_OFFSET 0xec00 705 | #else 706 | #define KEY_OFFSET 0x100 707 | #endif 708 | 709 | #define KEY_CODE_YES (KEY_OFFSET + 0x00) /* If get_wch() gives a key code */ 710 | 711 | #define KEY_BREAK (KEY_OFFSET + 0x01) /* Not on PC KBD */ 712 | #define KEY_DOWN (KEY_OFFSET + 0x02) /* Down arrow key */ 713 | #define KEY_UP (KEY_OFFSET + 0x03) /* Up arrow key */ 714 | #define KEY_LEFT (KEY_OFFSET + 0x04) /* Left arrow key */ 715 | #define KEY_RIGHT (KEY_OFFSET + 0x05) /* Right arrow key */ 716 | #define KEY_HOME (KEY_OFFSET + 0x06) /* home key */ 717 | #define KEY_BACKSPACE (KEY_OFFSET + 0x07) /* not on pc */ 718 | #define KEY_F0 (KEY_OFFSET + 0x08) /* function keys; 64 reserved */ 719 | 720 | #define KEY_DL (KEY_OFFSET + 0x48) /* delete line */ 721 | #define KEY_IL (KEY_OFFSET + 0x49) /* insert line */ 722 | #define KEY_DC (KEY_OFFSET + 0x4a) /* delete character */ 723 | #define KEY_IC (KEY_OFFSET + 0x4b) /* insert char or enter ins mode */ 724 | #define KEY_EIC (KEY_OFFSET + 0x4c) /* exit insert char mode */ 725 | #define KEY_CLEAR (KEY_OFFSET + 0x4d) /* clear screen */ 726 | #define KEY_EOS (KEY_OFFSET + 0x4e) /* clear to end of screen */ 727 | #define KEY_EOL (KEY_OFFSET + 0x4f) /* clear to end of line */ 728 | #define KEY_SF (KEY_OFFSET + 0x50) /* scroll 1 line forward */ 729 | #define KEY_SR (KEY_OFFSET + 0x51) /* scroll 1 line back (reverse) */ 730 | #define KEY_NPAGE (KEY_OFFSET + 0x52) /* next page */ 731 | #define KEY_PPAGE (KEY_OFFSET + 0x53) /* previous page */ 732 | #define KEY_STAB (KEY_OFFSET + 0x54) /* set tab */ 733 | #define KEY_CTAB (KEY_OFFSET + 0x55) /* clear tab */ 734 | #define KEY_CATAB (KEY_OFFSET + 0x56) /* clear all tabs */ 735 | #define KEY_ENTER (KEY_OFFSET + 0x57) /* enter or send (unreliable) */ 736 | #define KEY_SRESET (KEY_OFFSET + 0x58) /* soft/reset (partial/unreliable) */ 737 | #define KEY_RESET (KEY_OFFSET + 0x59) /* reset/hard reset (unreliable) */ 738 | #define KEY_PRINT (KEY_OFFSET + 0x5a) /* print/copy */ 739 | #define KEY_LL (KEY_OFFSET + 0x5b) /* home down/bottom (lower left) */ 740 | #define KEY_ABORT (KEY_OFFSET + 0x5c) /* abort/terminate key (any) */ 741 | #define KEY_SHELP (KEY_OFFSET + 0x5d) /* short help */ 742 | #define KEY_LHELP (KEY_OFFSET + 0x5e) /* long help */ 743 | #define KEY_BTAB (KEY_OFFSET + 0x5f) /* Back tab key */ 744 | #define KEY_BEG (KEY_OFFSET + 0x60) /* beg(inning) key */ 745 | #define KEY_CANCEL (KEY_OFFSET + 0x61) /* cancel key */ 746 | #define KEY_CLOSE (KEY_OFFSET + 0x62) /* close key */ 747 | #define KEY_COMMAND (KEY_OFFSET + 0x63) /* cmd (command) key */ 748 | #define KEY_COPY (KEY_OFFSET + 0x64) /* copy key */ 749 | #define KEY_CREATE (KEY_OFFSET + 0x65) /* create key */ 750 | #define KEY_END (KEY_OFFSET + 0x66) /* end key */ 751 | #define KEY_EXIT (KEY_OFFSET + 0x67) /* exit key */ 752 | #define KEY_FIND (KEY_OFFSET + 0x68) /* find key */ 753 | #define KEY_HELP (KEY_OFFSET + 0x69) /* help key */ 754 | #define KEY_MARK (KEY_OFFSET + 0x6a) /* mark key */ 755 | #define KEY_MESSAGE (KEY_OFFSET + 0x6b) /* message key */ 756 | #define KEY_MOVE (KEY_OFFSET + 0x6c) /* move key */ 757 | #define KEY_NEXT (KEY_OFFSET + 0x6d) /* next object key */ 758 | #define KEY_OPEN (KEY_OFFSET + 0x6e) /* open key */ 759 | #define KEY_OPTIONS (KEY_OFFSET + 0x6f) /* options key */ 760 | #define KEY_PREVIOUS (KEY_OFFSET + 0x70) /* previous object key */ 761 | #define KEY_REDO (KEY_OFFSET + 0x71) /* redo key */ 762 | #define KEY_REFERENCE (KEY_OFFSET + 0x72) /* ref(erence) key */ 763 | #define KEY_REFRESH (KEY_OFFSET + 0x73) /* refresh key */ 764 | #define KEY_REPLACE (KEY_OFFSET + 0x74) /* replace key */ 765 | #define KEY_RESTART (KEY_OFFSET + 0x75) /* restart key */ 766 | #define KEY_RESUME (KEY_OFFSET + 0x76) /* resume key */ 767 | #define KEY_SAVE (KEY_OFFSET + 0x77) /* save key */ 768 | #define KEY_SBEG (KEY_OFFSET + 0x78) /* shifted beginning key */ 769 | #define KEY_SCANCEL (KEY_OFFSET + 0x79) /* shifted cancel key */ 770 | #define KEY_SCOMMAND (KEY_OFFSET + 0x7a) /* shifted command key */ 771 | #define KEY_SCOPY (KEY_OFFSET + 0x7b) /* shifted copy key */ 772 | #define KEY_SCREATE (KEY_OFFSET + 0x7c) /* shifted create key */ 773 | #define KEY_SDC (KEY_OFFSET + 0x7d) /* shifted delete char key */ 774 | #define KEY_SDL (KEY_OFFSET + 0x7e) /* shifted delete line key */ 775 | #define KEY_SELECT (KEY_OFFSET + 0x7f) /* select key */ 776 | #define KEY_SEND (KEY_OFFSET + 0x80) /* shifted end key */ 777 | #define KEY_SEOL (KEY_OFFSET + 0x81) /* shifted clear line key */ 778 | #define KEY_SEXIT (KEY_OFFSET + 0x82) /* shifted exit key */ 779 | #define KEY_SFIND (KEY_OFFSET + 0x83) /* shifted find key */ 780 | #define KEY_SHOME (KEY_OFFSET + 0x84) /* shifted home key */ 781 | #define KEY_SIC (KEY_OFFSET + 0x85) /* shifted input key */ 782 | 783 | #define KEY_SLEFT (KEY_OFFSET + 0x87) /* shifted left arrow key */ 784 | #define KEY_SMESSAGE (KEY_OFFSET + 0x88) /* shifted message key */ 785 | #define KEY_SMOVE (KEY_OFFSET + 0x89) /* shifted move key */ 786 | #define KEY_SNEXT (KEY_OFFSET + 0x8a) /* shifted next key */ 787 | #define KEY_SOPTIONS (KEY_OFFSET + 0x8b) /* shifted options key */ 788 | #define KEY_SPREVIOUS (KEY_OFFSET + 0x8c) /* shifted prev key */ 789 | #define KEY_SPRINT (KEY_OFFSET + 0x8d) /* shifted print key */ 790 | #define KEY_SREDO (KEY_OFFSET + 0x8e) /* shifted redo key */ 791 | #define KEY_SREPLACE (KEY_OFFSET + 0x8f) /* shifted replace key */ 792 | #define KEY_SRIGHT (KEY_OFFSET + 0x90) /* shifted right arrow */ 793 | #define KEY_SRSUME (KEY_OFFSET + 0x91) /* shifted resume key */ 794 | #define KEY_SSAVE (KEY_OFFSET + 0x92) /* shifted save key */ 795 | #define KEY_SSUSPEND (KEY_OFFSET + 0x93) /* shifted suspend key */ 796 | #define KEY_SUNDO (KEY_OFFSET + 0x94) /* shifted undo key */ 797 | #define KEY_SUSPEND (KEY_OFFSET + 0x95) /* suspend key */ 798 | #define KEY_UNDO (KEY_OFFSET + 0x96) /* undo key */ 799 | 800 | /* PDCurses-specific key definitions -- PC only */ 801 | 802 | #define ALT_0 (KEY_OFFSET + 0x97) 803 | #define ALT_1 (KEY_OFFSET + 0x98) 804 | #define ALT_2 (KEY_OFFSET + 0x99) 805 | #define ALT_3 (KEY_OFFSET + 0x9a) 806 | #define ALT_4 (KEY_OFFSET + 0x9b) 807 | #define ALT_5 (KEY_OFFSET + 0x9c) 808 | #define ALT_6 (KEY_OFFSET + 0x9d) 809 | #define ALT_7 (KEY_OFFSET + 0x9e) 810 | #define ALT_8 (KEY_OFFSET + 0x9f) 811 | #define ALT_9 (KEY_OFFSET + 0xa0) 812 | #define ALT_A (KEY_OFFSET + 0xa1) 813 | #define ALT_B (KEY_OFFSET + 0xa2) 814 | #define ALT_C (KEY_OFFSET + 0xa3) 815 | #define ALT_D (KEY_OFFSET + 0xa4) 816 | #define ALT_E (KEY_OFFSET + 0xa5) 817 | #define ALT_F (KEY_OFFSET + 0xa6) 818 | #define ALT_G (KEY_OFFSET + 0xa7) 819 | #define ALT_H (KEY_OFFSET + 0xa8) 820 | #define ALT_I (KEY_OFFSET + 0xa9) 821 | #define ALT_J (KEY_OFFSET + 0xaa) 822 | #define ALT_K (KEY_OFFSET + 0xab) 823 | #define ALT_L (KEY_OFFSET + 0xac) 824 | #define ALT_M (KEY_OFFSET + 0xad) 825 | #define ALT_N (KEY_OFFSET + 0xae) 826 | #define ALT_O (KEY_OFFSET + 0xaf) 827 | #define ALT_P (KEY_OFFSET + 0xb0) 828 | #define ALT_Q (KEY_OFFSET + 0xb1) 829 | #define ALT_R (KEY_OFFSET + 0xb2) 830 | #define ALT_S (KEY_OFFSET + 0xb3) 831 | #define ALT_T (KEY_OFFSET + 0xb4) 832 | #define ALT_U (KEY_OFFSET + 0xb5) 833 | #define ALT_V (KEY_OFFSET + 0xb6) 834 | #define ALT_W (KEY_OFFSET + 0xb7) 835 | #define ALT_X (KEY_OFFSET + 0xb8) 836 | #define ALT_Y (KEY_OFFSET + 0xb9) 837 | #define ALT_Z (KEY_OFFSET + 0xba) 838 | 839 | #define CTL_LEFT (KEY_OFFSET + 0xbb) /* Control-Left-Arrow */ 840 | #define CTL_RIGHT (KEY_OFFSET + 0xbc) 841 | #define CTL_PGUP (KEY_OFFSET + 0xbd) 842 | #define CTL_PGDN (KEY_OFFSET + 0xbe) 843 | #define CTL_HOME (KEY_OFFSET + 0xbf) 844 | #define CTL_END (KEY_OFFSET + 0xc0) 845 | 846 | #define KEY_A1 (KEY_OFFSET + 0xc1) /* upper left on Virtual keypad */ 847 | #define KEY_A2 (KEY_OFFSET + 0xc2) /* upper middle on Virt. keypad */ 848 | #define KEY_A3 (KEY_OFFSET + 0xc3) /* upper right on Vir. keypad */ 849 | #define KEY_B1 (KEY_OFFSET + 0xc4) /* middle left on Virt. keypad */ 850 | #define KEY_B2 (KEY_OFFSET + 0xc5) /* center on Virt. keypad */ 851 | #define KEY_B3 (KEY_OFFSET + 0xc6) /* middle right on Vir. keypad */ 852 | #define KEY_C1 (KEY_OFFSET + 0xc7) /* lower left on Virt. keypad */ 853 | #define KEY_C2 (KEY_OFFSET + 0xc8) /* lower middle on Virt. keypad */ 854 | #define KEY_C3 (KEY_OFFSET + 0xc9) /* lower right on Vir. keypad */ 855 | 856 | #define PADSLASH (KEY_OFFSET + 0xca) /* slash on keypad */ 857 | #define PADENTER (KEY_OFFSET + 0xcb) /* enter on keypad */ 858 | #define CTL_PADENTER (KEY_OFFSET + 0xcc) /* ctl-enter on keypad */ 859 | #define ALT_PADENTER (KEY_OFFSET + 0xcd) /* alt-enter on keypad */ 860 | #define PADSTOP (KEY_OFFSET + 0xce) /* stop on keypad */ 861 | #define PADSTAR (KEY_OFFSET + 0xcf) /* star on keypad */ 862 | #define PADMINUS (KEY_OFFSET + 0xd0) /* minus on keypad */ 863 | #define PADPLUS (KEY_OFFSET + 0xd1) /* plus on keypad */ 864 | #define CTL_PADSTOP (KEY_OFFSET + 0xd2) /* ctl-stop on keypad */ 865 | #define CTL_PADCENTER (KEY_OFFSET + 0xd3) /* ctl-enter on keypad */ 866 | #define CTL_PADPLUS (KEY_OFFSET + 0xd4) /* ctl-plus on keypad */ 867 | #define CTL_PADMINUS (KEY_OFFSET + 0xd5) /* ctl-minus on keypad */ 868 | #define CTL_PADSLASH (KEY_OFFSET + 0xd6) /* ctl-slash on keypad */ 869 | #define CTL_PADSTAR (KEY_OFFSET + 0xd7) /* ctl-star on keypad */ 870 | #define ALT_PADPLUS (KEY_OFFSET + 0xd8) /* alt-plus on keypad */ 871 | #define ALT_PADMINUS (KEY_OFFSET + 0xd9) /* alt-minus on keypad */ 872 | #define ALT_PADSLASH (KEY_OFFSET + 0xda) /* alt-slash on keypad */ 873 | #define ALT_PADSTAR (KEY_OFFSET + 0xdb) /* alt-star on keypad */ 874 | #define ALT_PADSTOP (KEY_OFFSET + 0xdc) /* alt-stop on keypad */ 875 | #define CTL_INS (KEY_OFFSET + 0xdd) /* ctl-insert */ 876 | #define ALT_DEL (KEY_OFFSET + 0xde) /* alt-delete */ 877 | #define ALT_INS (KEY_OFFSET + 0xdf) /* alt-insert */ 878 | #define CTL_UP (KEY_OFFSET + 0xe0) /* ctl-up arrow */ 879 | #define CTL_DOWN (KEY_OFFSET + 0xe1) /* ctl-down arrow */ 880 | #define CTL_TAB (KEY_OFFSET + 0xe2) /* ctl-tab */ 881 | #define ALT_TAB (KEY_OFFSET + 0xe3) 882 | #define ALT_MINUS (KEY_OFFSET + 0xe4) 883 | #define ALT_EQUAL (KEY_OFFSET + 0xe5) 884 | #define ALT_HOME (KEY_OFFSET + 0xe6) 885 | #define ALT_PGUP (KEY_OFFSET + 0xe7) 886 | #define ALT_PGDN (KEY_OFFSET + 0xe8) 887 | #define ALT_END (KEY_OFFSET + 0xe9) 888 | #define ALT_UP (KEY_OFFSET + 0xea) /* alt-up arrow */ 889 | #define ALT_DOWN (KEY_OFFSET + 0xeb) /* alt-down arrow */ 890 | #define ALT_RIGHT (KEY_OFFSET + 0xec) /* alt-right arrow */ 891 | #define ALT_LEFT (KEY_OFFSET + 0xed) /* alt-left arrow */ 892 | #define ALT_ENTER (KEY_OFFSET + 0xee) /* alt-enter */ 893 | #define ALT_ESC (KEY_OFFSET + 0xef) /* alt-escape */ 894 | #define ALT_BQUOTE (KEY_OFFSET + 0xf0) /* alt-back quote */ 895 | #define ALT_LBRACKET (KEY_OFFSET + 0xf1) /* alt-left bracket */ 896 | #define ALT_RBRACKET (KEY_OFFSET + 0xf2) /* alt-right bracket */ 897 | #define ALT_SEMICOLON (KEY_OFFSET + 0xf3) /* alt-semi-colon */ 898 | #define ALT_FQUOTE (KEY_OFFSET + 0xf4) /* alt-forward quote */ 899 | #define ALT_COMMA (KEY_OFFSET + 0xf5) /* alt-comma */ 900 | #define ALT_STOP (KEY_OFFSET + 0xf6) /* alt-stop */ 901 | #define ALT_FSLASH (KEY_OFFSET + 0xf7) /* alt-forward slash */ 902 | #define ALT_BKSP (KEY_OFFSET + 0xf8) /* alt-backspace */ 903 | #define CTL_BKSP (KEY_OFFSET + 0xf9) /* ctl-backspace */ 904 | #define PAD0 (KEY_OFFSET + 0xfa) /* keypad 0 */ 905 | 906 | #define CTL_PAD0 (KEY_OFFSET + 0xfb) /* ctl-keypad 0 */ 907 | #define CTL_PAD1 (KEY_OFFSET + 0xfc) 908 | #define CTL_PAD2 (KEY_OFFSET + 0xfd) 909 | #define CTL_PAD3 (KEY_OFFSET + 0xfe) 910 | #define CTL_PAD4 (KEY_OFFSET + 0xff) 911 | #define CTL_PAD5 (KEY_OFFSET + 0x100) 912 | #define CTL_PAD6 (KEY_OFFSET + 0x101) 913 | #define CTL_PAD7 (KEY_OFFSET + 0x102) 914 | #define CTL_PAD8 (KEY_OFFSET + 0x103) 915 | #define CTL_PAD9 (KEY_OFFSET + 0x104) 916 | 917 | #define ALT_PAD0 (KEY_OFFSET + 0x105) /* alt-keypad 0 */ 918 | #define ALT_PAD1 (KEY_OFFSET + 0x106) 919 | #define ALT_PAD2 (KEY_OFFSET + 0x107) 920 | #define ALT_PAD3 (KEY_OFFSET + 0x108) 921 | #define ALT_PAD4 (KEY_OFFSET + 0x109) 922 | #define ALT_PAD5 (KEY_OFFSET + 0x10a) 923 | #define ALT_PAD6 (KEY_OFFSET + 0x10b) 924 | #define ALT_PAD7 (KEY_OFFSET + 0x10c) 925 | #define ALT_PAD8 (KEY_OFFSET + 0x10d) 926 | #define ALT_PAD9 (KEY_OFFSET + 0x10e) 927 | 928 | #define CTL_DEL (KEY_OFFSET + 0x10f) /* clt-delete */ 929 | #define ALT_BSLASH (KEY_OFFSET + 0x110) /* alt-back slash */ 930 | #define CTL_ENTER (KEY_OFFSET + 0x111) /* ctl-enter */ 931 | 932 | #define SHF_PADENTER (KEY_OFFSET + 0x112) /* shift-enter on keypad */ 933 | #define SHF_PADSLASH (KEY_OFFSET + 0x113) /* shift-slash on keypad */ 934 | #define SHF_PADSTAR (KEY_OFFSET + 0x114) /* shift-star on keypad */ 935 | #define SHF_PADPLUS (KEY_OFFSET + 0x115) /* shift-plus on keypad */ 936 | #define SHF_PADMINUS (KEY_OFFSET + 0x116) /* shift-minus on keypad */ 937 | #define SHF_UP (KEY_OFFSET + 0x117) /* shift-up on keypad */ 938 | #define SHF_DOWN (KEY_OFFSET + 0x118) /* shift-down on keypad */ 939 | #define SHF_IC (KEY_OFFSET + 0x119) /* shift-insert on keypad */ 940 | #define SHF_DC (KEY_OFFSET + 0x11a) /* shift-delete on keypad */ 941 | 942 | #define KEY_MOUSE (KEY_OFFSET + 0x11b) /* "mouse" key */ 943 | #define KEY_SHIFT_L (KEY_OFFSET + 0x11c) /* Left-shift */ 944 | #define KEY_SHIFT_R (KEY_OFFSET + 0x11d) /* Right-shift */ 945 | #define KEY_CONTROL_L (KEY_OFFSET + 0x11e) /* Left-control */ 946 | #define KEY_CONTROL_R (KEY_OFFSET + 0x11f) /* Right-control */ 947 | #define KEY_ALT_L (KEY_OFFSET + 0x120) /* Left-alt */ 948 | #define KEY_ALT_R (KEY_OFFSET + 0x121) /* Right-alt */ 949 | #define KEY_RESIZE (KEY_OFFSET + 0x122) /* Window resize */ 950 | #define KEY_SUP (KEY_OFFSET + 0x123) /* Shifted up arrow */ 951 | #define KEY_SDOWN (KEY_OFFSET + 0x124) /* Shifted down arrow */ 952 | 953 | /* The following were added 2011 Sep 14, and are */ 954 | /* not returned by most flavors of PDCurses: */ 955 | 956 | #define CTL_SEMICOLON (KEY_OFFSET + 0x125) 957 | #define CTL_EQUAL (KEY_OFFSET + 0x126) 958 | #define CTL_COMMA (KEY_OFFSET + 0x127) 959 | #define CTL_MINUS (KEY_OFFSET + 0x128) 960 | #define CTL_STOP (KEY_OFFSET + 0x129) 961 | #define CTL_FSLASH (KEY_OFFSET + 0x12a) 962 | #define CTL_BQUOTE (KEY_OFFSET + 0x12b) 963 | 964 | #define KEY_APPS (KEY_OFFSET + 0x12c) 965 | #define KEY_SAPPS (KEY_OFFSET + 0x12d) 966 | #define CTL_APPS (KEY_OFFSET + 0x12e) 967 | #define ALT_APPS (KEY_OFFSET + 0x12f) 968 | 969 | #define KEY_PAUSE (KEY_OFFSET + 0x130) 970 | #define KEY_SPAUSE (KEY_OFFSET + 0x131) 971 | #define CTL_PAUSE (KEY_OFFSET + 0x132) 972 | 973 | #define KEY_PRINTSCREEN (KEY_OFFSET + 0x133) 974 | #define ALT_PRINTSCREEN (KEY_OFFSET + 0x134) 975 | #define KEY_SCROLLLOCK (KEY_OFFSET + 0x135) 976 | #define ALT_SCROLLLOCK (KEY_OFFSET + 0x136) 977 | 978 | #define CTL_0 (KEY_OFFSET + 0x137) 979 | #define CTL_1 (KEY_OFFSET + 0x138) 980 | #define CTL_2 (KEY_OFFSET + 0x139) 981 | #define CTL_3 (KEY_OFFSET + 0x13a) 982 | #define CTL_4 (KEY_OFFSET + 0x13b) 983 | #define CTL_5 (KEY_OFFSET + 0x13c) 984 | #define CTL_6 (KEY_OFFSET + 0x13d) 985 | #define CTL_7 (KEY_OFFSET + 0x13e) 986 | #define CTL_8 (KEY_OFFSET + 0x13f) 987 | #define CTL_9 (KEY_OFFSET + 0x140) 988 | 989 | #define KEY_BROWSER_BACK (KEY_OFFSET + 0x141) 990 | #define KEY_SBROWSER_BACK (KEY_OFFSET + 0x142) 991 | #define KEY_CBROWSER_BACK (KEY_OFFSET + 0x143) 992 | #define KEY_ABROWSER_BACK (KEY_OFFSET + 0x144) 993 | #define KEY_BROWSER_FWD (KEY_OFFSET + 0x145) 994 | #define KEY_SBROWSER_FWD (KEY_OFFSET + 0x146) 995 | #define KEY_CBROWSER_FWD (KEY_OFFSET + 0x147) 996 | #define KEY_ABROWSER_FWD (KEY_OFFSET + 0x148) 997 | #define KEY_BROWSER_REF (KEY_OFFSET + 0x149) 998 | #define KEY_SBROWSER_REF (KEY_OFFSET + 0x14A) 999 | #define KEY_CBROWSER_REF (KEY_OFFSET + 0x14B) 1000 | #define KEY_ABROWSER_REF (KEY_OFFSET + 0x14C) 1001 | #define KEY_BROWSER_STOP (KEY_OFFSET + 0x14D) 1002 | #define KEY_SBROWSER_STOP (KEY_OFFSET + 0x14E) 1003 | #define KEY_CBROWSER_STOP (KEY_OFFSET + 0x14F) 1004 | #define KEY_ABROWSER_STOP (KEY_OFFSET + 0x150) 1005 | #define KEY_SEARCH (KEY_OFFSET + 0x151) 1006 | #define KEY_SSEARCH (KEY_OFFSET + 0x152) 1007 | #define KEY_CSEARCH (KEY_OFFSET + 0x153) 1008 | #define KEY_ASEARCH (KEY_OFFSET + 0x154) 1009 | #define KEY_FAVORITES (KEY_OFFSET + 0x155) 1010 | #define KEY_SFAVORITES (KEY_OFFSET + 0x156) 1011 | #define KEY_CFAVORITES (KEY_OFFSET + 0x157) 1012 | #define KEY_AFAVORITES (KEY_OFFSET + 0x158) 1013 | #define KEY_BROWSER_HOME (KEY_OFFSET + 0x159) 1014 | #define KEY_SBROWSER_HOME (KEY_OFFSET + 0x15A) 1015 | #define KEY_CBROWSER_HOME (KEY_OFFSET + 0x15B) 1016 | #define KEY_ABROWSER_HOME (KEY_OFFSET + 0x15C) 1017 | #define KEY_VOLUME_MUTE (KEY_OFFSET + 0x15D) 1018 | #define KEY_SVOLUME_MUTE (KEY_OFFSET + 0x15E) 1019 | #define KEY_CVOLUME_MUTE (KEY_OFFSET + 0x15F) 1020 | #define KEY_AVOLUME_MUTE (KEY_OFFSET + 0x160) 1021 | #define KEY_VOLUME_DOWN (KEY_OFFSET + 0x161) 1022 | #define KEY_SVOLUME_DOWN (KEY_OFFSET + 0x162) 1023 | #define KEY_CVOLUME_DOWN (KEY_OFFSET + 0x163) 1024 | #define KEY_AVOLUME_DOWN (KEY_OFFSET + 0x164) 1025 | #define KEY_VOLUME_UP (KEY_OFFSET + 0x165) 1026 | #define KEY_SVOLUME_UP (KEY_OFFSET + 0x166) 1027 | #define KEY_CVOLUME_UP (KEY_OFFSET + 0x167) 1028 | #define KEY_AVOLUME_UP (KEY_OFFSET + 0x168) 1029 | #define KEY_NEXT_TRACK (KEY_OFFSET + 0x169) 1030 | #define KEY_SNEXT_TRACK (KEY_OFFSET + 0x16A) 1031 | #define KEY_CNEXT_TRACK (KEY_OFFSET + 0x16B) 1032 | #define KEY_ANEXT_TRACK (KEY_OFFSET + 0x16C) 1033 | #define KEY_PREV_TRACK (KEY_OFFSET + 0x16D) 1034 | #define KEY_SPREV_TRACK (KEY_OFFSET + 0x16E) 1035 | #define KEY_CPREV_TRACK (KEY_OFFSET + 0x16F) 1036 | #define KEY_APREV_TRACK (KEY_OFFSET + 0x170) 1037 | #define KEY_MEDIA_STOP (KEY_OFFSET + 0x171) 1038 | #define KEY_SMEDIA_STOP (KEY_OFFSET + 0x172) 1039 | #define KEY_CMEDIA_STOP (KEY_OFFSET + 0x173) 1040 | #define KEY_AMEDIA_STOP (KEY_OFFSET + 0x174) 1041 | #define KEY_PLAY_PAUSE (KEY_OFFSET + 0x175) 1042 | #define KEY_SPLAY_PAUSE (KEY_OFFSET + 0x176) 1043 | #define KEY_CPLAY_PAUSE (KEY_OFFSET + 0x177) 1044 | #define KEY_APLAY_PAUSE (KEY_OFFSET + 0x178) 1045 | #define KEY_LAUNCH_MAIL (KEY_OFFSET + 0x179) 1046 | #define KEY_SLAUNCH_MAIL (KEY_OFFSET + 0x17A) 1047 | #define KEY_CLAUNCH_MAIL (KEY_OFFSET + 0x17B) 1048 | #define KEY_ALAUNCH_MAIL (KEY_OFFSET + 0x17C) 1049 | #define KEY_MEDIA_SELECT (KEY_OFFSET + 0x17D) 1050 | #define KEY_SMEDIA_SELECT (KEY_OFFSET + 0x17E) 1051 | #define KEY_CMEDIA_SELECT (KEY_OFFSET + 0x17F) 1052 | #define KEY_AMEDIA_SELECT (KEY_OFFSET + 0x180) 1053 | #define KEY_LAUNCH_APP1 (KEY_OFFSET + 0x181) 1054 | #define KEY_SLAUNCH_APP1 (KEY_OFFSET + 0x182) 1055 | #define KEY_CLAUNCH_APP1 (KEY_OFFSET + 0x183) 1056 | #define KEY_ALAUNCH_APP1 (KEY_OFFSET + 0x184) 1057 | #define KEY_LAUNCH_APP2 (KEY_OFFSET + 0x185) 1058 | #define KEY_SLAUNCH_APP2 (KEY_OFFSET + 0x186) 1059 | #define KEY_CLAUNCH_APP2 (KEY_OFFSET + 0x187) 1060 | #define KEY_ALAUNCH_APP2 (KEY_OFFSET + 0x188) 1061 | 1062 | #define KEY_MIN KEY_BREAK /* Minimum curses key value */ 1063 | #define KEY_MAX KEY_ALAUNCH_APP2 /* Maximum curses key */ 1064 | 1065 | #define KEY_F(n) (KEY_F0 + (n)) 1066 | 1067 | /*---------------------------------------------------------------------- 1068 | * 1069 | * PDCurses Function Declarations 1070 | * 1071 | */ 1072 | 1073 | /* Standard */ 1074 | 1075 | int addch(const chtype); 1076 | int addchnstr(const chtype *, int); 1077 | int addchstr(const chtype *); 1078 | int addnstr(const char *, int); 1079 | int addstr(const char *); 1080 | int attroff(chtype); 1081 | int attron(chtype); 1082 | int attrset(chtype); 1083 | int attr_get(attr_t *, short *, void *); 1084 | int attr_off(attr_t, void *); 1085 | int attr_on(attr_t, void *); 1086 | int attr_set(attr_t, short, void *); 1087 | int baudrate(void); 1088 | int beep(void); 1089 | int bkgd(chtype); 1090 | void bkgdset(chtype); 1091 | int border(chtype, chtype, chtype, chtype, chtype, chtype, chtype, chtype); 1092 | int box(WINDOW *, chtype, chtype); 1093 | bool can_change_color(void); 1094 | int cbreak(void); 1095 | int chgat(int, attr_t, short, const void *); 1096 | int clearok(WINDOW *, bool); 1097 | int clear(void); 1098 | int clrtobot(void); 1099 | int clrtoeol(void); 1100 | int color_content(short, short *, short *, short *); 1101 | int color_set(short, void *); 1102 | int copywin(const WINDOW *, WINDOW *, int, int, int, int, int, int, int); 1103 | int curs_set(int); 1104 | int def_prog_mode(void); 1105 | int def_shell_mode(void); 1106 | int delay_output(int); 1107 | int delch(void); 1108 | int deleteln(void); 1109 | void delscreen(SCREEN *); 1110 | int delwin(WINDOW *); 1111 | WINDOW *derwin(WINDOW *, int, int, int, int); 1112 | int doupdate(void); 1113 | WINDOW *dupwin(WINDOW *); 1114 | int echochar(const chtype); 1115 | int echo(void); 1116 | int endwin(void); 1117 | char erasechar(void); 1118 | int erase(void); 1119 | void filter(void); 1120 | int flash(void); 1121 | int flushinp(void); 1122 | chtype getbkgd(WINDOW *); 1123 | int getnstr(char *, int); 1124 | int getstr(char *); 1125 | WINDOW *getwin(FILE *); 1126 | int halfdelay(int); 1127 | bool has_colors(void); 1128 | bool has_ic(void); 1129 | bool has_il(void); 1130 | int hline(chtype, int); 1131 | void idcok(WINDOW *, bool); 1132 | int idlok(WINDOW *, bool); 1133 | void immedok(WINDOW *, bool); 1134 | int inchnstr(chtype *, int); 1135 | int inchstr(chtype *); 1136 | chtype inch(void); 1137 | int init_color(short, short, short, short); 1138 | int init_pair(short, short, short); 1139 | WINDOW *initscr(void); 1140 | int innstr(char *, int); 1141 | int insch(chtype); 1142 | int insdelln(int); 1143 | int insertln(void); 1144 | int insnstr(const char *, int); 1145 | int insstr(const char *); 1146 | int instr(char *); 1147 | int intrflush(WINDOW *, bool); 1148 | bool isendwin(void); 1149 | bool is_linetouched(WINDOW *, int); 1150 | bool is_wintouched(WINDOW *); 1151 | char *keyname(int); 1152 | int keypad(WINDOW *, bool); 1153 | char killchar(void); 1154 | int leaveok(WINDOW *, bool); 1155 | char *longname(void); 1156 | int meta(WINDOW *, bool); 1157 | int move(int, int); 1158 | int mvaddch(int, int, const chtype); 1159 | int mvaddchnstr(int, int, const chtype *, int); 1160 | int mvaddchstr(int, int, const chtype *); 1161 | int mvaddnstr(int, int, const char *, int); 1162 | int mvaddstr(int, int, const char *); 1163 | int mvchgat(int, int, int, attr_t, short, const void *); 1164 | int mvcur(int, int, int, int); 1165 | int mvdelch(int, int); 1166 | int mvderwin(WINDOW *, int, int); 1167 | int mvgetch(int, int); 1168 | int mvgetnstr(int, int, char *, int); 1169 | int mvgetstr(int, int, char *); 1170 | int mvhline(int, int, chtype, int); 1171 | chtype mvinch(int, int); 1172 | int mvinchnstr(int, int, chtype *, int); 1173 | int mvinchstr(int, int, chtype *); 1174 | int mvinnstr(int, int, char *, int); 1175 | int mvinsch(int, int, chtype); 1176 | int mvinsnstr(int, int, const char *, int); 1177 | int mvinsstr(int, int, const char *); 1178 | int mvinstr(int, int, char *); 1179 | int mvprintw(int, int, const char *, ...); 1180 | int mvscanw(int, int, const char *, ...); 1181 | int mvvline(int, int, chtype, int); 1182 | int mvwaddchnstr(WINDOW *, int, int, const chtype *, int); 1183 | int mvwaddchstr(WINDOW *, int, int, const chtype *); 1184 | int mvwaddch(WINDOW *, int, int, const chtype); 1185 | int mvwaddnstr(WINDOW *, int, int, const char *, int); 1186 | int mvwaddstr(WINDOW *, int, int, const char *); 1187 | int mvwchgat(WINDOW *, int, int, int, attr_t, short, const void *); 1188 | int mvwdelch(WINDOW *, int, int); 1189 | int mvwgetch(WINDOW *, int, int); 1190 | int mvwgetnstr(WINDOW *, int, int, char *, int); 1191 | int mvwgetstr(WINDOW *, int, int, char *); 1192 | int mvwhline(WINDOW *, int, int, chtype, int); 1193 | int mvwinchnstr(WINDOW *, int, int, chtype *, int); 1194 | int mvwinchstr(WINDOW *, int, int, chtype *); 1195 | chtype mvwinch(WINDOW *, int, int); 1196 | int mvwinnstr(WINDOW *, int, int, char *, int); 1197 | int mvwinsch(WINDOW *, int, int, chtype); 1198 | int mvwinsnstr(WINDOW *, int, int, const char *, int); 1199 | int mvwinsstr(WINDOW *, int, int, const char *); 1200 | int mvwinstr(WINDOW *, int, int, char *); 1201 | int mvwin(WINDOW *, int, int); 1202 | int mvwprintw(WINDOW *, int, int, const char *, ...); 1203 | int mvwscanw(WINDOW *, int, int, const char *, ...); 1204 | int mvwvline(WINDOW *, int, int, chtype, int); 1205 | int napms(int); 1206 | WINDOW *newpad(int, int); 1207 | SCREEN *newterm(const char *, FILE *, FILE *); 1208 | WINDOW *newwin(int, int, int, int); 1209 | int nl(void); 1210 | int nocbreak(void); 1211 | int nodelay(WINDOW *, bool); 1212 | int noecho(void); 1213 | int nonl(void); 1214 | void noqiflush(void); 1215 | int noraw(void); 1216 | int notimeout(WINDOW *, bool); 1217 | int overlay(const WINDOW *, WINDOW *); 1218 | int overwrite(const WINDOW *, WINDOW *); 1219 | int pair_content(short, short *, short *); 1220 | int pechochar(WINDOW *, chtype); 1221 | int pnoutrefresh(WINDOW *, int, int, int, int, int, int); 1222 | int prefresh(WINDOW *, int, int, int, int, int, int); 1223 | int printw(const char *, ...); 1224 | int putwin(WINDOW *, FILE *); 1225 | void qiflush(void); 1226 | int raw(void); 1227 | int redrawwin(WINDOW *); 1228 | int refresh(void); 1229 | int reset_prog_mode(void); 1230 | int reset_shell_mode(void); 1231 | int resetty(void); 1232 | int ripoffline(int, int (*)(WINDOW *, int)); 1233 | int savetty(void); 1234 | int scanw(const char *, ...); 1235 | int scr_dump(const char *); 1236 | int scr_init(const char *); 1237 | int scr_restore(const char *); 1238 | int scr_set(const char *); 1239 | int scrl(int); 1240 | int scroll(WINDOW *); 1241 | int scrollok(WINDOW *, bool); 1242 | SCREEN *set_term(SCREEN *); 1243 | int setscrreg(int, int); 1244 | int slk_attroff(const chtype); 1245 | int slk_attr_off(const attr_t, void *); 1246 | int slk_attron(const chtype); 1247 | int slk_attr_on(const attr_t, void *); 1248 | int slk_attrset(const chtype); 1249 | int slk_attr_set(const attr_t, short, void *); 1250 | int slk_clear(void); 1251 | int slk_color(short); 1252 | int slk_init(int); 1253 | char *slk_label(int); 1254 | int slk_noutrefresh(void); 1255 | int slk_refresh(void); 1256 | int slk_restore(void); 1257 | int slk_set(int, const char *, int); 1258 | int slk_touch(void); 1259 | int standend(void); 1260 | int standout(void); 1261 | int start_color(void); 1262 | WINDOW *subpad(WINDOW *, int, int, int, int); 1263 | WINDOW *subwin(WINDOW *, int, int, int, int); 1264 | int syncok(WINDOW *, bool); 1265 | chtype termattrs(void); 1266 | attr_t term_attrs(void); 1267 | char *termname(void); 1268 | void timeout(int); 1269 | int touchline(WINDOW *, int, int); 1270 | int touchwin(WINDOW *); 1271 | int typeahead(int); 1272 | int untouchwin(WINDOW *); 1273 | void use_env(bool); 1274 | int vidattr(chtype); 1275 | int vid_attr(attr_t, short, void *); 1276 | int vidputs(chtype, int (*)(int)); 1277 | int vid_puts(attr_t, short, void *, int (*)(int)); 1278 | int vline(chtype, int); 1279 | int vw_printw(WINDOW *, const char *, va_list); 1280 | int vwprintw(WINDOW *, const char *, va_list); 1281 | int vw_scanw(WINDOW *, const char *, va_list); 1282 | int vwscanw(WINDOW *, const char *, va_list); 1283 | int waddchnstr(WINDOW *, const chtype *, int); 1284 | int waddchstr(WINDOW *, const chtype *); 1285 | int waddch(WINDOW *, const chtype); 1286 | int waddnstr(WINDOW *, const char *, int); 1287 | int waddstr(WINDOW *, const char *); 1288 | int wattroff(WINDOW *, chtype); 1289 | int wattron(WINDOW *, chtype); 1290 | int wattrset(WINDOW *, chtype); 1291 | int wattr_get(WINDOW *, attr_t *, short *, void *); 1292 | int wattr_off(WINDOW *, attr_t, void *); 1293 | int wattr_on(WINDOW *, attr_t, void *); 1294 | int wattr_set(WINDOW *, attr_t, short, void *); 1295 | void wbkgdset(WINDOW *, chtype); 1296 | int wbkgd(WINDOW *, chtype); 1297 | int wborder(WINDOW *, chtype, chtype, chtype, chtype, 1298 | chtype, chtype, chtype, chtype); 1299 | int wchgat(WINDOW *, int, attr_t, short, const void *); 1300 | int wclear(WINDOW *); 1301 | int wclrtobot(WINDOW *); 1302 | int wclrtoeol(WINDOW *); 1303 | int wcolor_set(WINDOW *, short, void *); 1304 | void wcursyncup(WINDOW *); 1305 | int wdelch(WINDOW *); 1306 | int wdeleteln(WINDOW *); 1307 | int wechochar(WINDOW *, const chtype); 1308 | int werase(WINDOW *); 1309 | int wgetch(WINDOW *); 1310 | int wgetnstr(WINDOW *, char *, int); 1311 | int wgetstr(WINDOW *, char *); 1312 | int whline(WINDOW *, chtype, int); 1313 | int winchnstr(WINDOW *, chtype *, int); 1314 | int winchstr(WINDOW *, chtype *); 1315 | chtype winch(WINDOW *); 1316 | int winnstr(WINDOW *, char *, int); 1317 | int winsch(WINDOW *, chtype); 1318 | int winsdelln(WINDOW *, int); 1319 | int winsertln(WINDOW *); 1320 | int winsnstr(WINDOW *, const char *, int); 1321 | int winsstr(WINDOW *, const char *); 1322 | int winstr(WINDOW *, char *); 1323 | int wmove(WINDOW *, int, int); 1324 | int wnoutrefresh(WINDOW *); 1325 | int wprintw(WINDOW *, const char *, ...); 1326 | int wredrawln(WINDOW *, int, int); 1327 | int wrefresh(WINDOW *); 1328 | int wscanw(WINDOW *, const char *, ...); 1329 | int wscrl(WINDOW *, int); 1330 | int wsetscrreg(WINDOW *, int, int); 1331 | int wstandend(WINDOW *); 1332 | int wstandout(WINDOW *); 1333 | void wsyncdown(WINDOW *); 1334 | void wsyncup(WINDOW *); 1335 | void wtimeout(WINDOW *, int); 1336 | int wtouchln(WINDOW *, int, int, int); 1337 | int wvline(WINDOW *, chtype, int); 1338 | 1339 | /* Wide-character functions */ 1340 | 1341 | #ifdef PDC_WIDE 1342 | int addnwstr(const wchar_t *, int); 1343 | int addwstr(const wchar_t *); 1344 | int add_wch(const cchar_t *); 1345 | int add_wchnstr(const cchar_t *, int); 1346 | int add_wchstr(const cchar_t *); 1347 | int border_set(const cchar_t *, const cchar_t *, const cchar_t *, 1348 | const cchar_t *, const cchar_t *, const cchar_t *, 1349 | const cchar_t *, const cchar_t *); 1350 | int box_set(WINDOW *, const cchar_t *, const cchar_t *); 1351 | int echo_wchar(const cchar_t *); 1352 | int erasewchar(wchar_t *); 1353 | int getbkgrnd(cchar_t *); 1354 | int getcchar(const cchar_t *, wchar_t *, attr_t *, short *, void *); 1355 | int getn_wstr(wint_t *, int); 1356 | int get_wch(wint_t *); 1357 | int get_wstr(wint_t *); 1358 | int hline_set(const cchar_t *, int); 1359 | int innwstr(wchar_t *, int); 1360 | int ins_nwstr(const wchar_t *, int); 1361 | int ins_wch(const cchar_t *); 1362 | int ins_wstr(const wchar_t *); 1363 | int inwstr(wchar_t *); 1364 | int in_wch(cchar_t *); 1365 | int in_wchnstr(cchar_t *, int); 1366 | int in_wchstr(cchar_t *); 1367 | char *key_name(wchar_t); 1368 | int killwchar(wchar_t *); 1369 | int mvaddnwstr(int, int, const wchar_t *, int); 1370 | int mvaddwstr(int, int, const wchar_t *); 1371 | int mvadd_wch(int, int, const cchar_t *); 1372 | int mvadd_wchnstr(int, int, const cchar_t *, int); 1373 | int mvadd_wchstr(int, int, const cchar_t *); 1374 | int mvgetn_wstr(int, int, wint_t *, int); 1375 | int mvget_wch(int, int, wint_t *); 1376 | int mvget_wstr(int, int, wint_t *); 1377 | int mvhline_set(int, int, const cchar_t *, int); 1378 | int mvinnwstr(int, int, wchar_t *, int); 1379 | int mvins_nwstr(int, int, const wchar_t *, int); 1380 | int mvins_wch(int, int, const cchar_t *); 1381 | int mvins_wstr(int, int, const wchar_t *); 1382 | int mvinwstr(int, int, wchar_t *); 1383 | int mvin_wch(int, int, cchar_t *); 1384 | int mvin_wchnstr(int, int, cchar_t *, int); 1385 | int mvin_wchstr(int, int, cchar_t *); 1386 | int mvvline_set(int, int, const cchar_t *, int); 1387 | int mvwaddnwstr(WINDOW *, int, int, const wchar_t *, int); 1388 | int mvwaddwstr(WINDOW *, int, int, const wchar_t *); 1389 | int mvwadd_wch(WINDOW *, int, int, const cchar_t *); 1390 | int mvwadd_wchnstr(WINDOW *, int, int, const cchar_t *, int); 1391 | int mvwadd_wchstr(WINDOW *, int, int, const cchar_t *); 1392 | int mvwgetn_wstr(WINDOW *, int, int, wint_t *, int); 1393 | int mvwget_wch(WINDOW *, int, int, wint_t *); 1394 | int mvwget_wstr(WINDOW *, int, int, wint_t *); 1395 | int mvwhline_set(WINDOW *, int, int, const cchar_t *, int); 1396 | int mvwinnwstr(WINDOW *, int, int, wchar_t *, int); 1397 | int mvwins_nwstr(WINDOW *, int, int, const wchar_t *, int); 1398 | int mvwins_wch(WINDOW *, int, int, const cchar_t *); 1399 | int mvwins_wstr(WINDOW *, int, int, const wchar_t *); 1400 | int mvwin_wch(WINDOW *, int, int, cchar_t *); 1401 | int mvwin_wchnstr(WINDOW *, int, int, cchar_t *, int); 1402 | int mvwin_wchstr(WINDOW *, int, int, cchar_t *); 1403 | int mvwinwstr(WINDOW *, int, int, wchar_t *); 1404 | int mvwvline_set(WINDOW *, int, int, const cchar_t *, int); 1405 | int pecho_wchar(WINDOW *, const cchar_t*); 1406 | int setcchar(cchar_t*, const wchar_t*, const attr_t, short, const void*); 1407 | int slk_wset(int, const wchar_t *, int); 1408 | int unget_wch(const wchar_t); 1409 | int vline_set(const cchar_t *, int); 1410 | int waddnwstr(WINDOW *, const wchar_t *, int); 1411 | int waddwstr(WINDOW *, const wchar_t *); 1412 | int wadd_wch(WINDOW *, const cchar_t *); 1413 | int wadd_wchnstr(WINDOW *, const cchar_t *, int); 1414 | int wadd_wchstr(WINDOW *, const cchar_t *); 1415 | int wbkgrnd(WINDOW *, const cchar_t *); 1416 | void wbkgrndset(WINDOW *, const cchar_t *); 1417 | int wborder_set(WINDOW *, const cchar_t *, const cchar_t *, 1418 | const cchar_t *, const cchar_t *, const cchar_t *, 1419 | const cchar_t *, const cchar_t *, const cchar_t *); 1420 | int wecho_wchar(WINDOW *, const cchar_t *); 1421 | int wgetbkgrnd(WINDOW *, cchar_t *); 1422 | int wgetn_wstr(WINDOW *, wint_t *, int); 1423 | int wget_wch(WINDOW *, wint_t *); 1424 | int wget_wstr(WINDOW *, wint_t *); 1425 | int whline_set(WINDOW *, const cchar_t *, int); 1426 | int winnwstr(WINDOW *, wchar_t *, int); 1427 | int wins_nwstr(WINDOW *, const wchar_t *, int); 1428 | int wins_wch(WINDOW *, const cchar_t *); 1429 | int wins_wstr(WINDOW *, const wchar_t *); 1430 | int winwstr(WINDOW *, wchar_t *); 1431 | int win_wch(WINDOW *, cchar_t *); 1432 | int win_wchnstr(WINDOW *, cchar_t *, int); 1433 | int win_wchstr(WINDOW *, cchar_t *); 1434 | wchar_t *wunctrl(cchar_t *); 1435 | int wvline_set(WINDOW *, const cchar_t *, int); 1436 | #endif 1437 | 1438 | /* Quasi-standard */ 1439 | 1440 | chtype getattrs(WINDOW *); 1441 | int getbegx(WINDOW *); 1442 | int getbegy(WINDOW *); 1443 | int getmaxx(WINDOW *); 1444 | int getmaxy(WINDOW *); 1445 | int getparx(WINDOW *); 1446 | int getpary(WINDOW *); 1447 | int getcurx(WINDOW *); 1448 | int getcury(WINDOW *); 1449 | void traceoff(void); 1450 | void traceon(void); 1451 | char *unctrl(chtype); 1452 | 1453 | int crmode(void); 1454 | int nocrmode(void); 1455 | int draino(int); 1456 | int resetterm(void); 1457 | int fixterm(void); 1458 | int saveterm(void); 1459 | int setsyx(int, int); 1460 | 1461 | int mouse_set(unsigned long); 1462 | int mouse_on(unsigned long); 1463 | int mouse_off(unsigned long); 1464 | int request_mouse_pos(void); 1465 | int map_button(unsigned long); 1466 | void wmouse_position(WINDOW *, int *, int *); 1467 | unsigned long getmouse(void); 1468 | unsigned long getbmap(void); 1469 | 1470 | /* ncurses */ 1471 | 1472 | int assume_default_colors(int, int); 1473 | const char *curses_version(void); 1474 | bool has_key(int); 1475 | int use_default_colors(void); 1476 | int wresize(WINDOW *, int, int); 1477 | 1478 | int mouseinterval(int); 1479 | mmask_t mousemask(mmask_t, mmask_t *); 1480 | bool mouse_trafo(int *, int *, bool); 1481 | int nc_getmouse(MEVENT *); 1482 | int ungetmouse(MEVENT *); 1483 | bool wenclose(const WINDOW *, int, int); 1484 | bool wmouse_trafo(const WINDOW *, int *, int *, bool); 1485 | 1486 | /* PDCurses */ 1487 | 1488 | int addrawch(chtype); 1489 | int insrawch(chtype); 1490 | bool is_termresized(void); 1491 | int mvaddrawch(int, int, chtype); 1492 | int mvdeleteln(int, int); 1493 | int mvinsertln(int, int); 1494 | int mvinsrawch(int, int, chtype); 1495 | int mvwaddrawch(WINDOW *, int, int, chtype); 1496 | int mvwdeleteln(WINDOW *, int, int); 1497 | int mvwinsertln(WINDOW *, int, int); 1498 | int mvwinsrawch(WINDOW *, int, int, chtype); 1499 | int raw_output(bool); 1500 | int resize_term(int, int); 1501 | WINDOW *resize_window(WINDOW *, int, int); 1502 | int waddrawch(WINDOW *, chtype); 1503 | int winsrawch(WINDOW *, chtype); 1504 | char wordchar(void); 1505 | 1506 | #ifdef PDC_WIDE 1507 | wchar_t *slk_wlabel(int); 1508 | #endif 1509 | 1510 | void PDC_debug(const char *, ...); 1511 | int PDC_ungetch(int); 1512 | int PDC_set_blink(bool); 1513 | int PDC_set_line_color(short); 1514 | void PDC_set_title(const char *); 1515 | 1516 | int PDC_clearclipboard(void); 1517 | int PDC_freeclipboard(char *); 1518 | int PDC_getclipboard(char **, long *); 1519 | int PDC_setclipboard(const char *, long); 1520 | 1521 | unsigned long PDC_get_input_fd(void); 1522 | unsigned long PDC_get_key_modifiers(void); 1523 | int PDC_return_key_modifiers(bool); 1524 | int PDC_save_key_modifiers(bool); 1525 | void PDC_set_resize_limits( const int new_min_lines, 1526 | const int new_max_lines, 1527 | const int new_min_cols, 1528 | const int new_max_cols); 1529 | 1530 | WINDOW *Xinitscr(int, char **); 1531 | #ifdef XCURSES 1532 | void XCursesExit(void); 1533 | int sb_init(void); 1534 | int sb_set_horz(int, int, int); 1535 | int sb_set_vert(int, int, int); 1536 | int sb_get_horz(int *, int *, int *); 1537 | int sb_get_vert(int *, int *, int *); 1538 | int sb_refresh(void); 1539 | #endif 1540 | 1541 | /*** Functions defined as macros ***/ 1542 | 1543 | /* getch() and ungetch() conflict with some DOS libraries */ 1544 | 1545 | #define getch() wgetch(stdscr) 1546 | #define ungetch(ch) PDC_ungetch(ch) 1547 | 1548 | #define COLOR_PAIR(n) (((chtype)(n) << PDC_COLOR_SHIFT) & A_COLOR) 1549 | #define PAIR_NUMBER(n) (((n) & A_COLOR) >> PDC_COLOR_SHIFT) 1550 | 1551 | /* These will _only_ work as macros */ 1552 | 1553 | #define getbegyx(w, y, x) (y = getbegy(w), x = getbegx(w)) 1554 | #define getmaxyx(w, y, x) (y = getmaxy(w), x = getmaxx(w)) 1555 | #define getparyx(w, y, x) (y = getpary(w), x = getparx(w)) 1556 | #define getyx(w, y, x) (y = getcury(w), x = getcurx(w)) 1557 | 1558 | #define getsyx(y, x) { if (curscr->_leaveit) (y)=(x)=-1; \ 1559 | else getyx(curscr,(y),(x)); } 1560 | 1561 | #ifdef NCURSES_MOUSE_VERSION 1562 | # define getmouse(x) nc_getmouse(x) 1563 | #endif 1564 | 1565 | /* return codes from PDC_getclipboard() and PDC_setclipboard() calls */ 1566 | 1567 | #define PDC_CLIP_SUCCESS 0 1568 | #define PDC_CLIP_ACCESS_ERROR 1 1569 | #define PDC_CLIP_EMPTY 2 1570 | #define PDC_CLIP_MEMORY_ERROR 3 1571 | 1572 | /* PDCurses key modifier masks */ 1573 | 1574 | #define PDC_KEY_MODIFIER_SHIFT 1 1575 | #define PDC_KEY_MODIFIER_CONTROL 2 1576 | #define PDC_KEY_MODIFIER_ALT 4 1577 | #define PDC_KEY_MODIFIER_NUMLOCK 8 1578 | 1579 | #if defined(__cplusplus) || defined(__cplusplus__) || defined(__CPLUSPLUS) 1580 | # undef bool 1581 | } 1582 | #endif 1583 | 1584 | #endif /* __PDCURSES__ */ 1585 | -------------------------------------------------------------------------------- /test/myheaders/tcc/README.md: -------------------------------------------------------------------------------- 1 | - files here are borrow from [tinycc project](repo.or.cz/w/tinycc.git) 2 | 3 | -------------------------------------------------------------------------------- /test/myheaders/tcc/float.h: -------------------------------------------------------------------------------- 1 | #ifndef _FLOAT_H_ 2 | #define _FLOAT_H_ 3 | 4 | #define FLT_RADIX 2 5 | 6 | /* IEEE float */ 7 | #define FLT_MANT_DIG 24 8 | #define FLT_DIG 6 9 | #define FLT_ROUNDS 1 10 | #define FLT_EPSILON 1.19209290e-07F 11 | #define FLT_MIN_EXP (-125) 12 | #define FLT_MIN 1.17549435e-38F 13 | #define FLT_MIN_10_EXP (-37) 14 | #define FLT_MAX_EXP 128 15 | #define FLT_MAX 3.40282347e+38F 16 | #define FLT_MAX_10_EXP 38 17 | 18 | /* IEEE double */ 19 | #define DBL_MANT_DIG 53 20 | #define DBL_DIG 15 21 | #define DBL_EPSILON 2.2204460492503131e-16 22 | #define DBL_MIN_EXP (-1021) 23 | #define DBL_MIN 2.2250738585072014e-308 24 | #define DBL_MIN_10_EXP (-307) 25 | #define DBL_MAX_EXP 1024 26 | #define DBL_MAX 1.7976931348623157e+308 27 | #define DBL_MAX_10_EXP 308 28 | 29 | /* horrible intel long double */ 30 | #ifdef __i386__ 31 | 32 | #define LDBL_MANT_DIG 64 33 | #define LDBL_DIG 18 34 | #define LDBL_EPSILON 1.08420217248550443401e-19L 35 | #define LDBL_MIN_EXP (-16381) 36 | #define LDBL_MIN 3.36210314311209350626e-4932L 37 | #define LDBL_MIN_10_EXP (-4931) 38 | #define LDBL_MAX_EXP 16384 39 | #define LDBL_MAX 1.18973149535723176502e+4932L 40 | #define LDBL_MAX_10_EXP 4932 41 | 42 | #else 43 | 44 | /* same as IEEE double */ 45 | #define LDBL_MANT_DIG 53 46 | #define LDBL_DIG 15 47 | #define LDBL_EPSILON 2.2204460492503131e-16 48 | #define LDBL_MIN_EXP (-1021) 49 | #define LDBL_MIN 2.2250738585072014e-308 50 | #define LDBL_MIN_10_EXP (-307) 51 | #define LDBL_MAX_EXP 1024 52 | #define LDBL_MAX 1.7976931348623157e+308 53 | #define LDBL_MAX_10_EXP 308 54 | 55 | #endif 56 | 57 | #endif /* _FLOAT_H_ */ 58 | -------------------------------------------------------------------------------- /test/myheaders/tcc/libtcc.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBTCC_H 2 | #define LIBTCC_H 3 | 4 | #ifndef LIBTCCAPI 5 | # define LIBTCCAPI 6 | #endif 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | struct TCCState; 13 | 14 | typedef struct TCCState TCCState; 15 | 16 | /* create a new TCC compilation context */ 17 | LIBTCCAPI TCCState *tcc_new(void); 18 | 19 | /* free a TCC compilation context */ 20 | LIBTCCAPI void tcc_delete(TCCState *s); 21 | 22 | /* set CONFIG_TCCDIR at runtime */ 23 | LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path); 24 | 25 | /* set error/warning display callback */ 26 | LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, 27 | void (*error_func)(void *opaque, const char *msg)); 28 | 29 | /* set options as from command line (multiple supported) */ 30 | LIBTCCAPI int tcc_set_options(TCCState *s, const char *str); 31 | 32 | /*****************************/ 33 | /* preprocessor */ 34 | 35 | /* add include path */ 36 | LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname); 37 | 38 | /* add in system include path */ 39 | LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname); 40 | 41 | /* define preprocessor symbol 'sym'. Can put optional value */ 42 | LIBTCCAPI void tcc_define_symbol(TCCState *s, const char *sym, const char *value); 43 | 44 | /* undefine preprocess symbol 'sym' */ 45 | LIBTCCAPI void tcc_undefine_symbol(TCCState *s, const char *sym); 46 | 47 | /*****************************/ 48 | /* compiling */ 49 | 50 | /* add a file (C file, dll, object, library, ld script). Return -1 if error. */ 51 | LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename); 52 | 53 | /* compile a string containing a C source. Return -1 if error. */ 54 | LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf); 55 | 56 | /*****************************/ 57 | /* linking commands */ 58 | 59 | /* set output type. MUST BE CALLED before any compilation */ 60 | LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type); 61 | #define TCC_OUTPUT_MEMORY 0 /* output will be run in memory (default) */ 62 | #define TCC_OUTPUT_EXE 1 /* executable file */ 63 | #define TCC_OUTPUT_DLL 2 /* dynamic library */ 64 | #define TCC_OUTPUT_OBJ 3 /* object file */ 65 | #define TCC_OUTPUT_PREPROCESS 4 /* only preprocess (used internally) */ 66 | 67 | /* equivalent to -Lpath option */ 68 | LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname); 69 | 70 | /* the library name is the same as the argument of the '-l' option */ 71 | LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname); 72 | 73 | /* add a symbol to the compiled program */ 74 | LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val); 75 | 76 | /* output an executable, library or object file. DO NOT call 77 | tcc_relocate() before. */ 78 | LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename); 79 | 80 | /* link and run main() function and return its value. DO NOT call 81 | tcc_relocate() before. */ 82 | LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv); 83 | 84 | /* do all relocations (needed before using tcc_get_symbol()) */ 85 | LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr); 86 | /* possible values for 'ptr': 87 | - TCC_RELOCATE_AUTO : Allocate and manage memory internally 88 | - NULL : return required memory size for the step below 89 | - memory address : copy code to memory passed by the caller 90 | returns -1 if error. */ 91 | #define TCC_RELOCATE_AUTO (void*)1 92 | 93 | /* return symbol value or NULL if not found */ 94 | LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name); 95 | 96 | #ifdef __cplusplus 97 | } 98 | #endif 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /test/myheaders/tcc/stdarg.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDARG_H 2 | #define _STDARG_H 3 | 4 | #ifdef __x86_64__ 5 | #ifndef _WIN64 6 | 7 | typedef void *va_list; 8 | 9 | va_list __va_start(void *fp); 10 | void *__va_arg(va_list ap, int arg_type, int size); 11 | va_list __va_copy(va_list src); 12 | void __va_end(va_list ap); 13 | 14 | #define va_start(ap, last) ((ap) = __va_start(__builtin_frame_address(0))) 15 | #define va_arg(ap, type) \ 16 | (*(type *)(__va_arg(ap, __builtin_va_arg_types(type), sizeof(type)))) 17 | #define va_copy(dest, src) ((dest) = __va_copy(src)) 18 | #define va_end(ap) __va_end(ap) 19 | 20 | #else /* _WIN64 */ 21 | typedef char *va_list; 22 | #define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+7)&~7) 23 | #define va_arg(ap,type) (ap += (sizeof(type)+7)&~7, *(type *)(ap - ((sizeof(type)+7)&~7))) 24 | #define va_copy(dest, src) (dest) = (src) 25 | #define va_end(ap) 26 | #endif 27 | 28 | #else /* __i386__ */ 29 | typedef char *va_list; 30 | /* only correct for i386 */ 31 | #define va_start(ap,last) ap = ((char *)&(last)) + ((sizeof(last)+3)&~3) 32 | #define va_arg(ap,type) (ap += (sizeof(type)+3)&~3, *(type *)(ap - ((sizeof(type)+3)&~3))) 33 | #define va_copy(dest, src) (dest) = (src) 34 | #define va_end(ap) 35 | #endif 36 | 37 | /* fix a buggy dependency on GCC in libio.h */ 38 | typedef va_list __gnuc_va_list; 39 | #define _VA_LIST_DEFINED 40 | 41 | #endif /* _STDARG_H */ 42 | -------------------------------------------------------------------------------- /test/myheaders/tcc/stdbool.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDBOOL_H 2 | #define _STDBOOL_H 3 | 4 | /* ISOC99 boolean */ 5 | 6 | #define bool _Bool 7 | #define true 1 8 | #define false 0 9 | 10 | #endif /* _STDBOOL_H */ 11 | -------------------------------------------------------------------------------- /test/myheaders/tcc/stddef.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDDEF_H 2 | #define _STDDEF_H 3 | 4 | typedef __SIZE_TYPE__ size_t; 5 | typedef __PTRDIFF_TYPE__ ssize_t; 6 | typedef __WCHAR_TYPE__ wchar_t; 7 | typedef __PTRDIFF_TYPE__ ptrdiff_t; 8 | typedef __PTRDIFF_TYPE__ intptr_t; 9 | typedef __SIZE_TYPE__ uintptr_t; 10 | 11 | #ifndef __int8_t_defined 12 | #define __int8_t_defined 13 | typedef signed char int8_t; 14 | typedef signed short int int16_t; 15 | typedef signed int int32_t; 16 | typedef signed long long int int64_t; 17 | typedef unsigned char uint8_t; 18 | typedef unsigned short int uint16_t; 19 | typedef unsigned int uint32_t; 20 | typedef unsigned long long int uint64_t; 21 | #endif 22 | 23 | #define NULL ((void*)0) 24 | #define offsetof(type, field) ((size_t)&((type *)0)->field) 25 | 26 | void *alloca(size_t size); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /test/myheaders/tcc/stdint.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umegaya/ffiex/4fcf93a6a8165ba047eae52df17621600bfc0dd0/test/myheaders/tcc/stdint.h -------------------------------------------------------------------------------- /test/myheaders/tcc/stdio.h: -------------------------------------------------------------------------------- 1 | #include "tcclib.h" -------------------------------------------------------------------------------- /test/myheaders/tcc/tcclib.h: -------------------------------------------------------------------------------- 1 | /* Simple libc header for TCC 2 | * 3 | * Add any function you want from the libc there. This file is here 4 | * only for your convenience so that you do not need to put the whole 5 | * glibc include files on your floppy disk 6 | */ 7 | #ifndef _TCCLIB_H 8 | #define _TCCLIB_H 9 | 10 | #include 11 | #include 12 | 13 | /* stdlib.h */ 14 | void *calloc(size_t nmemb, size_t size); 15 | void *malloc(size_t size); 16 | void free(void *ptr); 17 | void *realloc(void *ptr, size_t size); 18 | int atoi(const char *nptr); 19 | long int strtol(const char *nptr, char **endptr, int base); 20 | unsigned long int strtoul(const char *nptr, char **endptr, int base); 21 | void exit(int); 22 | 23 | /* stdio.h */ 24 | typedef struct __FILE FILE; 25 | #define EOF (-1) 26 | extern FILE *stdin; 27 | extern FILE *stdout; 28 | extern FILE *stderr; 29 | FILE *fopen(const char *path, const char *mode); 30 | FILE *fdopen(int fildes, const char *mode); 31 | FILE *freopen(const char *path, const char *mode, FILE *stream); 32 | int fclose(FILE *stream); 33 | size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 34 | size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream); 35 | int fgetc(FILE *stream); 36 | char *fgets(char *s, int size, FILE *stream); 37 | int getc(FILE *stream); 38 | int getchar(void); 39 | char *gets(char *s); 40 | int ungetc(int c, FILE *stream); 41 | int fflush(FILE *stream); 42 | 43 | int printf(const char *format, ...); 44 | int fprintf(FILE *stream, const char *format, ...); 45 | int sprintf(char *str, const char *format, ...); 46 | int snprintf(char *str, size_t size, const char *format, ...); 47 | int asprintf(char **strp, const char *format, ...); 48 | int dprintf(int fd, const char *format, ...); 49 | int vprintf(const char *format, va_list ap); 50 | int vfprintf(FILE *stream, const char *format, va_list ap); 51 | int vsprintf(char *str, const char *format, va_list ap); 52 | int vsnprintf(char *str, size_t size, const char *format, va_list ap); 53 | int vasprintf(char **strp, const char *format, va_list ap); 54 | int vdprintf(int fd, const char *format, va_list ap); 55 | 56 | void perror(const char *s); 57 | 58 | /* string.h */ 59 | char *strcat(char *dest, const char *src); 60 | char *strchr(const char *s, int c); 61 | char *strrchr(const char *s, int c); 62 | char *strcpy(char *dest, const char *src); 63 | void *memcpy(void *dest, const void *src, size_t n); 64 | void *memmove(void *dest, const void *src, size_t n); 65 | void *memset(void *s, int c, size_t n); 66 | char *strdup(const char *s); 67 | 68 | /* dlfcn.h */ 69 | #define RTLD_LAZY 0x001 70 | #define RTLD_NOW 0x002 71 | #define RTLD_GLOBAL 0x100 72 | 73 | void *dlopen(const char *filename, int flag); 74 | const char *dlerror(void); 75 | void *dlsym(void *handle, char *symbol); 76 | int dlclose(void *handle); 77 | 78 | #endif /* _TCCLIB_H */ 79 | -------------------------------------------------------------------------------- /test/myheaders/tcc/varargs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file has no copyright assigned and is placed in the Public Domain. 3 | * This file is part of the w64 mingw-runtime package. 4 | * No warranty is given; refer to the file DISCLAIMER within this package. 5 | */ 6 | #ifndef _VARARGS_H 7 | #define _VARARGS_H 8 | 9 | #error "TinyCC no longer implements ." 10 | #error "Revise your code to use ." 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /test/parseheaders.lua: -------------------------------------------------------------------------------- 1 | function try_parse_headers(directory) 2 | local dir = io.popen('ls '..directory) 3 | local ffi = require "ffiex.init" 4 | local blacklist 5 | if ffi.os == "OSX" then 6 | blacklist = { 7 | "cxxabi.h", -- namespace is contained 8 | "nc_tparm.h", -- TPARM_1 declared twice 9 | "standards.h", -- deprecated and cannot used 10 | "tk.h", -- X11/* headers not exist under /usr/include, 11 | "tkDecls.h", -- same as tk.h 12 | "tkIntXlibDecls.h", -- same as tk.h 13 | "tkMacOSX.h", -- same as tk.h 14 | "ucontext.h", -- The deprecated ucontext routines require _XOPEN_SOURCE to be defined 15 | "sys/dtrace_impl.h", -- need KERNEL_BUILD and if it specified, libkern/libkern.h is required (but not provided for normal env) 16 | "sys/ubc.h", -- kern/locks.h is not found and it is not provided 17 | } 18 | elseif ffi.os == "Linux" then 19 | blacklist = { 20 | "complex.h", -- luajit itself will support for it 21 | "cursesapp.h", "cursesf.h", "cursesm.h", "cursesp.h", "cursesw.h", "cursslk.h", -- c++ file 22 | "autosprintf.h", "etip.h", -- c++ file 23 | "link.h", -- missing Elf__ELF_NATIVE_CLASS_Addr 24 | "dialog.h", "dlg_colors.h", "dlg_keys.h", -- refer ncurses/ncurses.h even if its not installed (dlg_config.h wrongly says it is exists) 25 | "driver.h", -- symbolic link to /usr/lib/erlang/user/include/driver.h but only /usr/lib/erlang/user/include/erl_driver.h exists. 26 | "erl_nif_api_funcs.h", -- This file should not be included directly (error in header itself) 27 | "FlexLexer.h", -- c++ header 28 | "ft2build.h", -- try to include but only have freetype2 directory under /usr/include 29 | "pcre_stringpiece.h", "pcre_scanner.h", "pcrecpp.h", "pcrecpparg.h", -- c++ header 30 | "png.h", -- png_structppng_ptr not exist. I think that is typo of "png_structp png_ptr" 31 | "turbojpeg.h", -- luajit cdef cannot process static const int [] 32 | "db_cxx.h", -- c++ header 33 | "gmpxx.h", -- c++ header 34 | "t1libx.h", 35 | } 36 | end 37 | while true do 38 | local file = dir:read() 39 | local basename = file 40 | if not file then break end 41 | local subdir = directory:gsub('/usr/include/', '') 42 | if #subdir > 0 then 43 | file = (subdir .. '/' .. file) 44 | end 45 | -- no arg or arg[1] is this file => full test mode otherwise single file test mode (specify some header name) 46 | if not arg[1] or (arg[1] == file) or (arg[1] == 'test/parseheaders.lua') then 47 | if basename:find('^[^_]+.*%.h$') then 48 | -- print('code:', ('(require "ffiex.init").cdef "#include <%s>"'):format(file)) 49 | local black 50 | if blacklist then 51 | for _,fn in ipairs(blacklist) do 52 | if fn == file then 53 | black = true 54 | end 55 | end 56 | end 57 | if not black then 58 | print('try parse:' .. file) 59 | 60 | local ok, r = pcall(os.execute, ('luajit test/parser.lua_ %s'):format(file)) 61 | --local ok, r = pcall(loadstring, ('(require "ffiex.init").cdef "#include <%s>"'):format(file)) 62 | if ok and r == 0 then 63 | else 64 | print('parse fails:' .. file .. '|' .. tostring(r)) 65 | os.exit(-2) 66 | end 67 | end 68 | else 69 | print('not test:' .. file) 70 | end 71 | end 72 | end 73 | end 74 | 75 | try_parse_headers('/usr/include/arpa') 76 | try_parse_headers('/usr/include/netinet') 77 | try_parse_headers('/usr/include/sys') 78 | try_parse_headers('/usr/include/') 79 | 80 | 81 | print('test finished') 82 | 83 | return true 84 | -------------------------------------------------------------------------------- /test/parser.lua: -------------------------------------------------------------------------------- 1 | local parser = require 'ffiex.parser' 2 | 3 | local function check_dependency(sym, typename, deps, cdef_checker) 4 | typename = parser.name(sym, typename) 5 | local t = assert(sym[typename], typename .. " not exist") 6 | for i,d in ipairs(deps) do 7 | local found 8 | for j,e in ipairs(t.deps) do 9 | if d == e then found = true end 10 | end 11 | assert(found, typename .. " should depend on "..d) 12 | end 13 | if cdef_checker then 14 | assert(cdef_checker(t.cdef), "dependency correct but has invalid source "..typename) 15 | end 16 | end 17 | 18 | local sym 19 | -- test1 20 | sym = parser.parse(nil, [[ 21 | typedef unsigned int volatile *test1_a_t[16], * * test1_b_t ; 22 | typedef unsigned long long register test1_c_t, *test1_d_t ; 23 | struct test1_e_t { int a; }; 24 | typedef struct test1_e_t test1_e_t; 25 | typedef int integer_t; 26 | ]]) 27 | check_dependency(sym, "test1_a_t", {"unsigned int"}) 28 | check_dependency(sym, "test1_b_t", {"unsigned int"}) 29 | check_dependency(sym, "test1_c_t", {"unsigned long long int"}) 30 | check_dependency(sym, "test1_d_t", {"unsigned long long int"}) 31 | check_dependency(sym, "struct test1_e_t", {"int"}) 32 | check_dependency(sym, "typename test1_e_t", {"struct test1_e_t"}) 33 | check_dependency(sym, "integer_t", {"int"}) 34 | 35 | 36 | -- test2 37 | sym = parser.parse(nil, [[ 38 | typedef struct _test2_a_t { 39 | long a; 40 | void *p[16]; 41 | char * * ptr; 42 | } test2_a_t; 43 | typedef enum _test2_b_t { 44 | ENUM1, 45 | ENUM2, 46 | ENUM3, 47 | } test2_b_t; 48 | ]]) 49 | check_dependency(sym, "_test2_a_t", {"long int", "void", "char"}) 50 | check_dependency(sym, "test2_a_t", {"struct _test2_a_t"}) 51 | check_dependency(sym, "test2_b_t", {"enum _test2_b_t"}) 52 | 53 | 54 | -- test3 55 | sym = parser.parse(nil, [[ 56 | typedef struct { 57 | unsigned long a [ 16 ] [ 32 ]; 58 | char *p [ 16 ] [ 32 ]; 59 | } test3_a_t; 60 | typedef enum { 61 | ENUM4, 62 | ENUM5, 63 | ENUM6, 64 | } test3_b_t; 65 | ]]) 66 | check_dependency(sym, "test3_a_t", {"unsigned long int", "char"}) 67 | check_dependency(sym, "test3_b_t", {}) 68 | 69 | 70 | -- test4 71 | sym = parser.parse(nil, [[ 72 | typedef int (*test4_a_t)(char a, short b, unsigned long c); 73 | typedef void *test4_b_t(int *b[]), *test4_c_t, (*test4_d_t(char, signed short))(int, long long); 74 | ]]) 75 | check_dependency(sym, "test4_a_t", {"int", "char", "short int", "unsigned long int"}) 76 | check_dependency(sym, "test4_b_t", {"void", "int"}) 77 | check_dependency(sym, "test4_c_t", {"void"}) 78 | check_dependency(sym, "test4_d_t", {"void", "char", "signed short int", "int", "long long int"}) 79 | 80 | 81 | --test5 82 | sym = parser.parse(nil, [[ 83 | typedef struct _test5_a_t { 84 | void *p; 85 | } test5_a_t; 86 | extern __attribute__(always_inline, hoge(1, 2)) void test5_a_fn(char a, short b, unsigned long c) __attribute__(noreturn, fastcall); 87 | static int (test5_b_fn)(char a, int (*)(short b), void *(*)(unsigned long c)) __asm(hoge); 88 | int *test5_c_fn(struct _test5_a_t *ph1, test5_a_t *ph2); 89 | __declspec(dllimport) void (*test5_d_fn(int, void (*)(int)))(int); 90 | ]]) 91 | check_dependency(sym, "func test5_a_fn", {"void", "char", "short int", "unsigned long int"}, function (cdef) 92 | return cdef:find("__attribute__%(always_inline, hoge%(1, 2%)%)") 93 | end) 94 | check_dependency(sym, "func test5_b_fn", {"int", "char", "short int", "void", "unsigned long int"}, function (cdef) 95 | return cdef:find("__asm%(hoge%)") 96 | end) 97 | check_dependency(sym, "_test5_a_t", {"void"}) 98 | check_dependency(sym, "test5_a_t", {"struct _test5_a_t"}) 99 | check_dependency(sym, "func test5_c_fn", {"struct _test5_a_t", "test5_a_t"}) 100 | check_dependency(sym, "func test5_d_fn", {"void", "int"}, function (cdef) 101 | return cdef:find('__declspec%(dllimport%)') 102 | end) 103 | 104 | 105 | --test6 106 | sym = parser.parse(nil, [[ 107 | typedef struct { 108 | void *p; 109 | volatile int vn; 110 | } test6_a_t; 111 | struct test6_b_t { 112 | test6_a_t *p; 113 | test6_a_t *ap[16]; 114 | }; 115 | 116 | typedef struct { 117 | test6_a_t a, (*fn)(test6_b_t *, int); 118 | int x, y, z; 119 | test6_b_t (*fn2(int, void *(void *)))(char, long); 120 | struct test6_d_t *pd; 121 | 122 | } test6_c_t; 123 | ]]) 124 | check_dependency(sym, "test6_a_t", {"void", "int"}) 125 | check_dependency(sym, "test6_b_t", {"test6_a_t"}) 126 | check_dependency(sym, "test6_c_t", {"test6_a_t", "test6_b_t", "int", "char", "long int", "struct test6_d_t"}) 127 | check_dependency(sym, "test6_d_t", {}) 128 | 129 | return true 130 | -------------------------------------------------------------------------------- /test/parser.lua_: -------------------------------------------------------------------------------- 1 | local ffi = require "ffiex.init" 2 | -- ffi.__DEBUG_CDEF__ = true 3 | local required 4 | local expath 5 | if ffi.os == "OSX" then 6 | expath = { 7 | 8 | } 9 | required = { 10 | ["mpool.h"] = {"db.h"}, -- pgno_t 11 | ["pcap-bpf.h"] = {"sys/types.h"}, -- u_int 12 | ["pcap-namedb.h"] = {"sys/types.h", "pcap/bpf.h"}, -- u_char, bpf_u_int32 13 | ["tclDecls.h"] = {"tcl.h"}, -- EXTERN, CONST84_RETURN 14 | ["tkDecls.h"] = {"tcl.h"}, -- EXTERN, CONST84_RETURN 15 | ["lber.h"] = {"lber_types.h"}, 16 | ["ldif.h"] = {"lber_types.h"}, 17 | ["reboot2.h"] = {"sys/types.h"}, -- ssize_t 18 | ["sys/_select.h"] = {"sys/_types/_fd_def.h"}, 19 | ["sys/acct.h"] = {"i386/types.h", "sys/_types/_uid_t.h", "sys/_types/_gid_t.h", "sys/_types/_dev_t.h"}, 20 | ["sys/acl.h"] = {"i386/types.h", "sys/_types/_uid_t.h", "sys/_types/_gid_t.h", "sys/_types/_dev_t.h"}, 21 | ["sys/gmon.h"] = {"sys/types.h"}, -- u_short 22 | ["sys/kauth.h"] = {"sys/types.h"}, -- u_int8_t 23 | ["sys/kern_control.h"] = {"sys/types.h"}, -- u_int32_t 24 | ["sys/mbuf.h"] = {"sys/types.h"}, -- u_int32_t 25 | ["sys/pipe.h"] = {"sys/types.h"}, -- u_int32_t 26 | ["sys/lctx.h"] = {"sys/_types/_pid_t.h"}, -- pid_t 27 | ["sys/lockf.h"] = {"sys/types.h"}, -- caddr_t 28 | ["sys/posix_sem.h"] = {"sys/types.h", "sys/signal.h", "sys/time.h"}, -- sigset_t, struct timeval 29 | ["sys/posix_shm.h"] = {"sys/types.h", "sys/signal.h", "sys/time.h"}, -- sigset_t, struct timeval 30 | ["sys/proc.h"] = {"sys/types.h", "sys/signal.h", "sys/time.h"}, -- sigset_t, struct timeval 31 | ["sys/ptrace.h"] = {"sys/types.h"}, -- pid_t, caddr_t 32 | ["sys/quota.h"] = {"sys/types.h"}, -- u_int32_t 33 | ["sys/random.h"] = {"sys/types.h"}, -- u_int32_t 34 | ["sys/resourcevar.h"] = {"sys/types.h", "sys/resource.h"}, -- caddr_t, struct rusage 35 | ["sys/socketvar.h"] = {"sys/types.h"}, -- u_quad_t 36 | ["sys/unpcb.h"] = {"sys/types.h", "sys/socketvar.h"}, -- so_gen_t 37 | ["sys/vm.h"] = {"sys/types.h"}, -- caddr_t 38 | ["sys/vstat.h"] = {"sys/mount.h"}, -- fsid_t 39 | ["netinet/bootp.h"] = {"netinet/ip.h", "netinet/ip_icmp.h", "netinet/udp.h"}, -- struct udphdr, struct ip, ICMP_MAXTYPE 40 | ["netinet/icmp_var.h"] = {"netinet/ip.h", "netinet/ip_icmp.h"}, -- ICMP_MAXTYPE 41 | ["netinet/in_pcb.h"] = {"netinet/ip.h", "netinet/ip_icmp.h", "sys/socketvar.h"}, -- ICMP_MAXTYPE, xsocket 42 | ["netinet/in_var.h"] = {"net/if.h"}, -- IFNAMSIZ 43 | ["netinet/ip_icmp.h"] = {"netinet/ip.h"}, -- n_short 44 | ["netinet/tcp_var.h"] = {"sys/socketvar.h", "netinet/tcp.h"}, -- xsocket, tcp_seq 45 | ["netinet/tcpip.h"] = {"net/if.h", "netinet/ip_var.h", "netinet/tcp.h"}, -- struct ipovly, struct tcphdr 46 | ["netinet/udp_var.h"] = {"net/if.h", "netinet/ip_var.h", "netinet/udp.h"}, -- struct ipovly, struct udphdr 47 | } 48 | ffi.cdef "#define XP_NO_X_HEADERS" 49 | ffi.cdef "#define _DNS_SD_LIBDISPATCH (0)" 50 | ffi.cdef "#include " 51 | ffi.cdef "#include " 52 | ffi.cdef "#include " 53 | elseif ffi.os == "Linux" then 54 | expath = { 55 | ["xf86drm.h"] = {"/usr/include/drm"}, -- drm.h 56 | ["xf86drmMode.h"] = {"/usr/include/drm"}, -- drm.h 57 | } 58 | required = { 59 | ["gcrypt-module.h"] = {"gcrypt.h"}, -- gcry_error_code_t 60 | ["kdb.h"] = {"limits.h"}, -- SHRT_MAX 61 | ["term_entry.h"] = {"stdio.h"}, -- FILE 62 | ["evrpc.h"] = {"sys/queue.h"}, -- TAILQ_ENTRY 63 | ["jpegint.h"] = {"stdio.h", "jpeglib.h"}, -- JMETHOD 64 | ["jpeglib.h"] = {"stdio.h"}, -- FILE 65 | ["lber.h"] = {"stdio.h", "lber_types.h"}, -- FILE, ber_len_t 66 | ["ldif.h"] = {"stdio.h", "lber_types.h"}, -- FILE, ber_len_t 67 | ["pngconf.h"] = {"zlib.h"}, -- charf, z_stream 68 | } 69 | ffi.cdef "#include " 70 | end 71 | if required[arg[1]] then 72 | for _,hdr in ipairs(required[arg[1]]) do 73 | print('include ' .. hdr .. ' for ' .. arg[1]) 74 | ffi.cdef (("#include <%s>"):format(hdr)) 75 | end 76 | end 77 | if expath[arg[1]] then 78 | for _,p in ipairs(expath[arg[1]]) do 79 | print('add path ' .. p .. ' for ' .. arg[1]) 80 | ffi.path(p) 81 | end 82 | end 83 | ffi.cdef (("#include <%s>"):format(arg[1])) 84 | -------------------------------------------------------------------------------- /test/pdcurses.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | 3 | local state = ffi.newstate() 4 | -- ffi need to configure for loading tcc header and lib 5 | ffi.path "./test/myheaders/tcc" 6 | state:copt { cc = "tcc" } 7 | state:cdef [[ 8 | //complement missing definition 9 | #if !defined(__SIZE_TYPE__) 10 | #define __SIZE_TYPE__ size_t 11 | #endif 12 | #if !defined(__PTRDIFF_TYPE__) 13 | #define __PTRDIFF_TYPE__ ptrdiff_t 14 | #endif 15 | #if !defined(__WINT_TYPE__) 16 | #define __WINT_TYPE__ wchar_t 17 | #endif 18 | #if !defined(__WCHAR_TYPE__) 19 | #define __WCHAR_TYPE__ wchar_t 20 | #endif 21 | ]] 22 | state:cdef [[ 23 | #if(HOGE) 24 | #define FOO ("foo") 25 | #else 26 | #define FOO ("bar") 27 | #endif 28 | 29 | #ifndef(FUGA) 30 | #define BAR ("bar") 31 | #else 32 | #define BAR ("foo") 33 | #endif 34 | 35 | #ifdef(ZZZ) 36 | #define BAZ ("baz") 37 | #else 38 | #define BAZ ("bazbaz") 39 | #endif 40 | ]] 41 | 42 | print(state.defs.FOO, state.defs.BAR, state.defs.BAZ) 43 | assert(state.defs.FOO == "bar", state.defs.FOO) 44 | assert(state.defs.BAR == "bar", state.defs.BAR) 45 | assert(state.defs.BAZ == "bazbaz", state.defs.BAZ) 46 | 47 | state:path "./test/myheaders" 48 | state:path "./test/myheaders/tcc" 49 | state:cdef [[ #include "pdcurses.h" ]] 50 | 51 | assert(state.defs.CHTYPE_LONG == 2) 52 | 53 | return true 54 | -------------------------------------------------------------------------------- /test/state.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | local state = ffi.newstate() 3 | local fdecl = "__attribute__((noreturn)) void no_return_fn(char *p);" 4 | 5 | state:cdef(( 6 | [[ 7 | #define FOO(x) (x + 1) 8 | %s 9 | ]] 10 | ):format(fdecl) 11 | ) 12 | assert(state.defs.FOO(1) == 2, "invalid macro parse:"..state.defs.FOO(1)) 13 | -- main ffiex still doen't know macro FOO 14 | assert(nil == ffi.defs.FOO, "FOO should not exist:"..tostring(ffi.defs.FOO)) 15 | -- able to define another macro FOO 16 | local src_fdecl = state:src_of("no_return_fn") 17 | assert(src_fdecl:gsub("%s", "") == fdecl:gsub("%s", ""), "invalid src_of:["..src_fdecl.."]") 18 | local src_fdecl2 = state:src_of("no_return_fn", true) 19 | assert(src_fdecl2:gsub("%s", "") == fdecl:gsub("%s", ""), "invalid src_of:["..src_fdecl2.."]") 20 | 21 | ffi.cdef[[ 22 | #define FOO(x) (x + 10) 23 | ]] 24 | assert(ffi.defs.FOO(1) == 11, "wrongly defined macro:"..ffi.defs.FOO(1)) --> 11 25 | 26 | return true -------------------------------------------------------------------------------- /test/tcc.lua: -------------------------------------------------------------------------------- 1 | local ffi = require 'ffiex.init' 2 | -- in 0.9.26, only tcc --run is supported for OSX. 3 | if ffi.os == "OSX" then return true end 4 | local tester, err = loadfile('test/ffiex_csrc.lua_') 5 | if tester then 6 | tester()("tcc", function () 7 | ffi.clear_copt() 8 | ffi.path "./test/myheaders/" 9 | ffi.path "./test/myheaders/tcc/" 10 | return { 11 | cc = "tcc", 12 | extra = {"-D_MYDEF", "-D_MYDEF2=101", "-O2", "-Wall"}, 13 | } 14 | end) 15 | else 16 | print('fail to load tester:'..err) 17 | end 18 | 19 | return true 20 | -------------------------------------------------------------------------------- /tmp/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umegaya/ffiex/4fcf93a6a8165ba047eae52df17621600bfc0dd0/tmp/.gitkeep -------------------------------------------------------------------------------- /travis_install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CHECK=`luajit -v` 4 | if [ "$CHECK" = "" ]; 5 | then 6 | pushd tmp 7 | git clone http://luajit.org/git/luajit-2.0.git 8 | pushd luajit-2.0 9 | make && sudo make install 10 | popd 11 | popd 12 | fi 13 | CHECK=`which tcc` 14 | TCC_VERSION=release_0_9_26 15 | TCC_LIB=libtcc.so 16 | TCC_LIB_NAME=$TCC_LIB.1.0 17 | if [ "$CHECK" = "" ]; 18 | then 19 | pushd tmp 20 | git clone --depth 1 git://repo.or.cz/tinycc.git --branch $TCC_VERSION 21 | pushd tinycc 22 | sudo ./configure && make DISABLE_STATIC=1 && make install 23 | sudo cp $TCC_LIB_NAME /usr/local/lib/ 24 | sudo ln -s /usr/local/lib/$TCC_LIB_NAME /usr/local/lib/$TCC_LIB 25 | sudo sh -c "echo '/usr/local/lib' > /etc/ld.so.conf.d/tcc.conf" 26 | sudo ldconfig 27 | popd 28 | popd 29 | fi 30 | 31 | --------------------------------------------------------------------------------