From e7bbd8256b8c701205389be431bbafd8743c72a9 Mon Sep 17 00:00:00 2001 From: ZyX Date: Fri, 4 Mar 2016 21:55:28 +0300 Subject: eval: Add luaeval function No tests yet, no documentation update, no :lua* stuff, no vim module. converter.c should also work with typval_T, not Object. Known problem: luaeval("1", {}) results in PANIC: unprotected error in call to Lua API (attempt to index a nil value) Ref #3823 --- scripts/gendispatch.lua | 334 ---------------------------- scripts/generate_vim_module.lua | 38 ++++ scripts/genmsgpack.lua | 469 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 507 insertions(+), 334 deletions(-) delete mode 100644 scripts/gendispatch.lua create mode 100644 scripts/generate_vim_module.lua create mode 100644 scripts/genmsgpack.lua (limited to 'scripts') diff --git a/scripts/gendispatch.lua b/scripts/gendispatch.lua deleted file mode 100644 index 45a4f4a4de..0000000000 --- a/scripts/gendispatch.lua +++ /dev/null @@ -1,334 +0,0 @@ -lpeg = require('lpeg') -mpack = require('mpack') - --- lpeg grammar for building api metadata from a set of header files. It --- ignores comments and preprocessor commands and parses a very small subset --- of C prototypes with a limited set of types -P, R, S = lpeg.P, lpeg.R, lpeg.S -C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg - -any = P(1) -- (consume one character) -letter = R('az', 'AZ') + S('_$') -num = R('09') -alpha = letter + num -nl = P('\r\n') + P('\n') -not_nl = any - nl -ws = S(' \t') + nl -fill = ws ^ 0 -c_comment = P('//') * (not_nl ^ 0) -c_preproc = P('#') * (not_nl ^ 0) -typed_container = - (P('ArrayOf(') + P('DictionaryOf(')) * ((any - P(')')) ^ 1) * P(')') -c_id = ( - typed_container + - (letter * (alpha ^ 0)) -) -c_void = P('void') -c_param_type = ( - ((P('Error') * fill * P('*') * fill) * Cc('error')) + - (C(c_id) * (ws ^ 1)) - ) -c_type = (C(c_void) * (ws ^ 1)) + c_param_type -c_param = Ct(c_param_type * C(c_id)) -c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0) -c_params = Ct(c_void + c_param_list) -c_proto = Ct( - Cg(c_type, 'return_type') * Cg(c_id, 'name') * - fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * - Cg(Cc(false), 'async') * - (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) * - (fill * Cg((P('FUNC_API_ASYNC') * Cc(true)), 'async') ^ -1) * - (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) * - (fill * Cg((P('FUNC_API_NOEVAL') * Cc(true)), 'noeval') ^ -1) * - fill * P(';') - ) -grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) - --- we need at least 4 arguments since the last two are output files -assert(#arg >= 3) -functions = {} - -local nvimsrcdir = arg[1] -package.path = nvimsrcdir .. '/?.lua;' .. package.path - --- names of all headers relative to the source root (for inclusion in the --- generated file) -headers = {} - --- output h file with generated dispatch functions -dispatch_outputf = arg[#arg-2] --- output h file with packed metadata -funcs_metadata_outputf = arg[#arg-1] --- output metadata mpack file, for use by other build scripts -mpack_outputf = arg[#arg] - --- set of function names, used to detect duplicates -function_names = {} - --- read each input file, parse and append to the api metadata -for i = 2, #arg - 3 do - local full_path = arg[i] - local parts = {} - for part in string.gmatch(full_path, '[^/]+') do - parts[#parts + 1] = part - end - headers[#headers + 1] = parts[#parts - 1]..'/'..parts[#parts] - - local input = io.open(full_path, 'rb') - local tmp = grammar:match(input:read('*all')) - for i = 1, #tmp do - local fn = tmp[i] - if not fn.noexport then - functions[#functions + 1] = tmp[i] - function_names[fn.name] = true - if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then - -- this function should receive the channel id - fn.receives_channel_id = true - -- remove the parameter since it won't be passed by the api client - table.remove(fn.parameters, 1) - end - if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'error' then - -- function can fail if the last parameter type is 'Error' - fn.can_fail = true - -- remove the error parameter, msgpack has it's own special field - -- for specifying errors - fn.parameters[#fn.parameters] = nil - end - end - end - input:close() -end - -local function shallowcopy(orig) - local copy = {} - for orig_key, orig_value in pairs(orig) do - copy[orig_key] = orig_value - end - return copy -end - -local function startswith(String,Start) - return string.sub(String,1,string.len(Start))==Start -end - --- Export functions under older deprecated names. --- These will be removed eventually. -local deprecated_aliases = require("api.dispatch_deprecated") -for i,f in ipairs(shallowcopy(functions)) do - local ismethod = false - if startswith(f.name, "nvim_") then - if f.since == nil then - print("Function "..f.name.." lacks since field.\n") - os.exit(1) - end - f.since = tonumber(f.since) - if startswith(f.name, "nvim_buf_") then - ismethod = true - elseif startswith(f.name, "nvim_win_") then - ismethod = true - elseif startswith(f.name, "nvim_tabpage_") then - ismethod = true - end - else - f.noeval = true - f.since = 0 - f.deprecated_since = 1 - end - f.method = ismethod - local newname = deprecated_aliases[f.name] - if newname ~= nil then - if function_names[newname] then - -- duplicate - print("Function "..f.name.." has deprecated alias\n" - ..newname.." which has a separate implementation.\n".. - "Please remove it from src/nvim/api/dispatch_deprecated.lua") - os.exit(1) - end - local newf = shallowcopy(f) - newf.name = newname - if newname == "ui_try_resize" then - -- The return type was incorrectly set to Object in 0.1.5. - -- Keep it that way for clients that rely on this. - newf.return_type = "Object" - end - newf.impl_name = f.name - newf.noeval = true - newf.since = 0 - newf.deprecated_since = 1 - functions[#functions+1] = newf - end -end - --- don't expose internal attributes like "impl_name" in public metadata -exported_attributes = {'name', 'parameters', 'return_type', 'method', - 'since', 'deprecated_since'} -exported_functions = {} -for _,f in ipairs(functions) do - local f_exported = {} - for _,attr in ipairs(exported_attributes) do - f_exported[attr] = f[attr] - end - exported_functions[#exported_functions+1] = f_exported -end - - -funcs_metadata_output = io.open(funcs_metadata_outputf, 'wb') -funcs_metadata_output:write([[ -static const uint8_t funcs_metadata[] = { -]]) - --- serialize the API metadata using msgpack and embed into the resulting --- binary for easy querying by clients -packed_exported_functions = mpack.pack(exported_functions) -for i = 1, #packed_exported_functions do - funcs_metadata_output:write(string.byte(packed_exported_functions, i)..', ') - if i % 10 == 0 then - funcs_metadata_output:write('\n ') - end -end -funcs_metadata_output:write([[ -}; -]]) -funcs_metadata_output:close() - --- start building the dispatch wrapper output -output = io.open(dispatch_outputf, 'wb') - -local function real_type(type) - local rv = type - if typed_container:match(rv) then - if rv:match('Array') then - rv = 'Array' - else - rv = 'Dictionary' - end - end - return rv -end - --- start the handler functions. Visit each function metadata to build the --- handler function with code generated for validating arguments and calling to --- the real API. -for i = 1, #functions do - local fn = functions[i] - if fn.impl_name == nil then - local args = {} - - output:write('Object handle_'..fn.name..'(uint64_t channel_id, Array args, Error *error)') - output:write('\n{') - output:write('\n Object ret = NIL;') - -- Declare/initialize variables that will hold converted arguments - for j = 1, #fn.parameters do - local param = fn.parameters[j] - local converted = 'arg_'..j - output:write('\n '..param[1]..' '..converted..';') - end - output:write('\n') - output:write('\n if (args.size != '..#fn.parameters..') {') - output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);') - output:write('\n error->set = true;') - output:write('\n goto cleanup;') - output:write('\n }\n') - - -- Validation/conversion for each argument - for j = 1, #fn.parameters do - local converted, convert_arg, param, arg - param = fn.parameters[j] - converted = 'arg_'..j - local rt = real_type(param[1]) - if rt ~= 'Object' then - if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') then - -- Buffer, Window, and Tabpage have a specific type, but are stored in integer - output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..' && args.items['..(j - 1)..'].data.integer >= 0) {') - output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') - else - output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..') {') - output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..rt:lower()..';') - end - if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') or rt:match('^Boolean$') then - -- accept nonnegative integers for Booleans, Buffers, Windows and Tabpages - output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeInteger && args.items['..(j - 1)..'].data.integer >= 0) {') - output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') - end - output:write('\n } else {') - output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong type for argument '..j..', expecting '..param[1]..'");') - output:write('\n error->set = true;') - output:write('\n goto cleanup;') - output:write('\n }\n') - else - output:write('\n '..converted..' = args.items['..(j - 1)..'];\n') - end - - args[#args + 1] = converted - end - - -- function call - local call_args = table.concat(args, ', ') - output:write('\n ') - if fn.return_type ~= 'void' then - -- has a return value, prefix the call with a declaration - output:write(fn.return_type..' rv = ') - end - - -- write the function name and the opening parenthesis - output:write(fn.name..'(') - - if fn.receives_channel_id then - -- if the function receives the channel id, pass it as first argument - if #args > 0 or fn.can_fail then - output:write('channel_id, '..call_args) - else - output:write('channel_id') - end - else - output:write(call_args) - end - - if fn.can_fail then - -- if the function can fail, also pass a pointer to the local error object - if #args > 0 then - output:write(', error);\n') - else - output:write('error);\n') - end - -- and check for the error - output:write('\n if (error->set) {') - output:write('\n goto cleanup;') - output:write('\n }\n') - else - output:write(');\n') - end - - if fn.return_type ~= 'void' then - output:write('\n ret = '..string.upper(real_type(fn.return_type))..'_OBJ(rv);') - end - output:write('\n\ncleanup:'); - - output:write('\n return ret;\n}\n\n'); - end -end - --- Generate a function that initializes method names with handler functions -output:write([[ -void msgpack_rpc_init_method_table(void) -{ - methods = map_new(String, MsgpackRpcRequestHandler)(); - -]]) - -for i = 1, #functions do - local fn = functions[i] - output:write(' msgpack_rpc_add_method_handler('.. - '(String) {.data = "'..fn.name..'", '.. - '.size = sizeof("'..fn.name..'") - 1}, '.. - '(MsgpackRpcRequestHandler) {.fn = handle_'.. (fn.impl_name or fn.name).. - ', .async = '..tostring(fn.async)..'});\n') - -end - -output:write('\n}\n\n') -output:close() - -mpack_output = io.open(mpack_outputf, 'wb') -mpack_output:write(mpack.pack(functions)) -mpack_output:close() diff --git a/scripts/generate_vim_module.lua b/scripts/generate_vim_module.lua new file mode 100644 index 0000000000..954f1c38be --- /dev/null +++ b/scripts/generate_vim_module.lua @@ -0,0 +1,38 @@ +assert(#arg == 2) + +module_file = arg[1] +target_file = arg[2] + +module = io.open(module_file, 'r') +target = io.open(target_file, 'w') + +target:write('#include \n\n') +target:write('static const uint8_t vim_module[] = {\n') + +num_bytes = 0 +MAX_NUM_BYTES = 15 -- 78 / 5: maximum number of bytes on one line +target:write(' ') + +increase_num_bytes = function() + num_bytes = num_bytes + 1 + if num_bytes == MAX_NUM_BYTES then + num_bytes = 0 + target:write('\n ') + end +end + +for line in module:lines() do + for i = 1,string.len(line) do + byte = string.byte(line, i) + assert(byte ~= 0) + target:write(string.format(' %3u,', byte)) + increase_num_bytes() + end + target:write(string.format(' %3u,', string.byte('\n', 1))) + increase_num_bytes() +end + +target:write(' 0};\n') + +module:close() +target:close() diff --git a/scripts/genmsgpack.lua b/scripts/genmsgpack.lua new file mode 100644 index 0000000000..dd3caab5e4 --- /dev/null +++ b/scripts/genmsgpack.lua @@ -0,0 +1,469 @@ +lpeg = require('lpeg') +mpack = require('mpack') + +-- lpeg grammar for building api metadata from a set of header files. It +-- ignores comments and preprocessor commands and parses a very small subset +-- of C prototypes with a limited set of types +P, R, S = lpeg.P, lpeg.R, lpeg.S +C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg + +any = P(1) -- (consume one character) +letter = R('az', 'AZ') + S('_$') +num = R('09') +alpha = letter + num +nl = P('\r\n') + P('\n') +not_nl = any - nl +ws = S(' \t') + nl +fill = ws ^ 0 +c_comment = P('//') * (not_nl ^ 0) +c_preproc = P('#') * (not_nl ^ 0) +typed_container = + (P('ArrayOf(') + P('DictionaryOf(')) * ((any - P(')')) ^ 1) * P(')') +c_id = ( + typed_container + + (letter * (alpha ^ 0)) +) +c_void = P('void') +c_param_type = ( + ((P('Error') * fill * P('*') * fill) * Cc('error')) + + (C(c_id) * (ws ^ 1)) + ) +c_type = (C(c_void) * (ws ^ 1)) + c_param_type +c_param = Ct(c_param_type * C(c_id)) +c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0) +c_params = Ct(c_void + c_param_list) +c_proto = Ct( + Cg(c_type, 'return_type') * Cg(c_id, 'name') * + fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * + Cg(Cc(false), 'async') * + (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) * + (fill * Cg((P('FUNC_API_ASYNC') * Cc(true)), 'async') ^ -1) * + (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) * + (fill * Cg((P('FUNC_API_NOEVAL') * Cc(true)), 'noeval') ^ -1) * + fill * P(';') + ) +grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) + +-- we need at least 4 arguments since the last two are output files +if arg[1] == '--help' then + print('Usage: genmsgpack.lua args') + print('Args: 1: source directory') + print(' 2: dispatch output file (dispatch_wrappers.generated.h)') + print(' 3: functions metadata output file (funcs_metadata.generated.h)') + print(' 4: API metadata output file (api_metadata.mpack)') + print(' 5: lua C bindings output file (msgpack_lua_c_bindings.generated.c)') + print(' rest: C files where API functions are defined') +end +assert(#arg >= 4) +functions = {} + +local nvimsrcdir = arg[1] +package.path = nvimsrcdir .. '/?.lua;' .. package.path + +-- names of all headers relative to the source root (for inclusion in the +-- generated file) +headers = {} + +-- output h file with generated dispatch functions +dispatch_outputf = arg[2] +-- output h file with packed metadata +funcs_metadata_outputf = arg[3] +-- output metadata mpack file, for use by other build scripts +mpack_outputf = arg[4] +lua_c_bindings_outputf = arg[5] + +-- set of function names, used to detect duplicates +function_names = {} + +-- read each input file, parse and append to the api metadata +for i = 6, #arg do + local full_path = arg[i] + local parts = {} + for part in string.gmatch(full_path, '[^/]+') do + parts[#parts + 1] = part + end + headers[#headers + 1] = parts[#parts - 1]..'/'..parts[#parts] + + local input = io.open(full_path, 'rb') + local tmp = grammar:match(input:read('*all')) + for i = 1, #tmp do + local fn = tmp[i] + if not fn.noexport then + functions[#functions + 1] = tmp[i] + function_names[fn.name] = true + if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then + -- this function should receive the channel id + fn.receives_channel_id = true + -- remove the parameter since it won't be passed by the api client + table.remove(fn.parameters, 1) + end + if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'error' then + -- function can fail if the last parameter type is 'Error' + fn.can_fail = true + -- remove the error parameter, msgpack has it's own special field + -- for specifying errors + fn.parameters[#fn.parameters] = nil + end + end + end + input:close() +end + +local function shallowcopy(orig) + local copy = {} + for orig_key, orig_value in pairs(orig) do + copy[orig_key] = orig_value + end + return copy +end + +local function startswith(String,Start) + return string.sub(String,1,string.len(Start))==Start +end + +-- Export functions under older deprecated names. +-- These will be removed eventually. +local deprecated_aliases = require("api.dispatch_deprecated") +for i,f in ipairs(shallowcopy(functions)) do + local ismethod = false + if startswith(f.name, "nvim_") then + if f.since == nil then + print("Function "..f.name.." lacks since field.\n") + os.exit(1) + end + f.since = tonumber(f.since) + if startswith(f.name, "nvim_buf_") then + ismethod = true + elseif startswith(f.name, "nvim_win_") then + ismethod = true + elseif startswith(f.name, "nvim_tabpage_") then + ismethod = true + end + else + f.noeval = true + f.since = 0 + f.deprecated_since = 1 + end + f.method = ismethod + local newname = deprecated_aliases[f.name] + if newname ~= nil then + if function_names[newname] then + -- duplicate + print("Function "..f.name.." has deprecated alias\n" + ..newname.." which has a separate implementation.\n".. + "Please remove it from src/nvim/api/dispatch_deprecated.lua") + os.exit(1) + end + local newf = shallowcopy(f) + newf.name = newname + if newname == "ui_try_resize" then + -- The return type was incorrectly set to Object in 0.1.5. + -- Keep it that way for clients that rely on this. + newf.return_type = "Object" + end + newf.impl_name = f.name + newf.noeval = true + newf.since = 0 + newf.deprecated_since = 1 + functions[#functions+1] = newf + end +end + +-- don't expose internal attributes like "impl_name" in public metadata +exported_attributes = {'name', 'parameters', 'return_type', 'method', + 'since', 'deprecated_since'} +exported_functions = {} +for _,f in ipairs(functions) do + local f_exported = {} + for _,attr in ipairs(exported_attributes) do + f_exported[attr] = f[attr] + end + exported_functions[#exported_functions+1] = f_exported +end + + +funcs_metadata_output = io.open(funcs_metadata_outputf, 'wb') +funcs_metadata_output:write([[ +static const uint8_t funcs_metadata[] = { +]]) + +-- serialize the API metadata using msgpack and embed into the resulting +-- binary for easy querying by clients +packed_exported_functions = mpack.pack(exported_functions) +for i = 1, #packed_exported_functions do + funcs_metadata_output:write(string.byte(packed_exported_functions, i)..', ') + if i % 10 == 0 then + funcs_metadata_output:write('\n ') + end +end +funcs_metadata_output:write([[ +}; +]]) +funcs_metadata_output:close() + +-- start building the dispatch wrapper output +output = io.open(dispatch_outputf, 'wb') + +local function real_type(type) + local rv = type + if typed_container:match(rv) then + if rv:match('Array') then + rv = 'Array' + else + rv = 'Dictionary' + end + end + return rv +end + +-- start the handler functions. Visit each function metadata to build the +-- handler function with code generated for validating arguments and calling to +-- the real API. +for i = 1, #functions do + local fn = functions[i] + if fn.impl_name == nil then + local args = {} + + output:write('Object handle_'..fn.name..'(uint64_t channel_id, Array args, Error *error)') + output:write('\n{') + output:write('\n Object ret = NIL;') + -- Declare/initialize variables that will hold converted arguments + for j = 1, #fn.parameters do + local param = fn.parameters[j] + local converted = 'arg_'..j + output:write('\n '..param[1]..' '..converted..';') + end + output:write('\n') + output:write('\n if (args.size != '..#fn.parameters..') {') + output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);') + output:write('\n error->set = true;') + output:write('\n goto cleanup;') + output:write('\n }\n') + + -- Validation/conversion for each argument + for j = 1, #fn.parameters do + local converted, convert_arg, param, arg + param = fn.parameters[j] + converted = 'arg_'..j + local rt = real_type(param[1]) + if rt ~= 'Object' then + if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') then + -- Buffer, Window, and Tabpage have a specific type, but are stored in integer + output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..' && args.items['..(j - 1)..'].data.integer >= 0) {') + output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') + else + output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..') {') + output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..rt:lower()..';') + end + if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') or rt:match('^Boolean$') then + -- accept nonnegative integers for Booleans, Buffers, Windows and Tabpages + output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeInteger && args.items['..(j - 1)..'].data.integer >= 0) {') + output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') + end + output:write('\n } else {') + output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong type for argument '..j..', expecting '..param[1]..'");') + output:write('\n error->set = true;') + output:write('\n goto cleanup;') + output:write('\n }\n') + else + output:write('\n '..converted..' = args.items['..(j - 1)..'];\n') + end + + args[#args + 1] = converted + end + + -- function call + local call_args = table.concat(args, ', ') + output:write('\n ') + if fn.return_type ~= 'void' then + -- has a return value, prefix the call with a declaration + output:write(fn.return_type..' rv = ') + end + + -- write the function name and the opening parenthesis + output:write(fn.name..'(') + + if fn.receives_channel_id then + -- if the function receives the channel id, pass it as first argument + if #args > 0 or fn.can_fail then + output:write('channel_id, '..call_args) + else + output:write('channel_id') + end + else + output:write(call_args) + end + + if fn.can_fail then + -- if the function can fail, also pass a pointer to the local error object + if #args > 0 then + output:write(', error);\n') + else + output:write('error);\n') + end + -- and check for the error + output:write('\n if (error->set) {') + output:write('\n goto cleanup;') + output:write('\n }\n') + else + output:write(');\n') + end + + if fn.return_type ~= 'void' then + output:write('\n ret = '..string.upper(real_type(fn.return_type))..'_OBJ(rv);') + end + output:write('\n\ncleanup:'); + + output:write('\n return ret;\n}\n\n'); + end +end + +-- Generate a function that initializes method names with handler functions +output:write([[ +void msgpack_rpc_init_method_table(void) +{ + methods = map_new(String, MsgpackRpcRequestHandler)(); + +]]) + +for i = 1, #functions do + local fn = functions[i] + output:write(' msgpack_rpc_add_method_handler('.. + '(String) {.data = "'..fn.name..'", '.. + '.size = sizeof("'..fn.name..'") - 1}, '.. + '(MsgpackRpcRequestHandler) {.fn = handle_'.. (fn.impl_name or fn.name).. + ', .async = '..tostring(fn.async)..'});\n') + +end + +output:write('\n}\n\n') +output:close() + +mpack_output = io.open(mpack_outputf, 'wb') +mpack_output:write(mpack.pack(functions)) +mpack_output:close() + +local function include_headers(output, headers) + for i = 1, #headers do + if headers[i]:sub(-12) ~= '.generated.h' then + output:write('\n#include "nvim/'..headers[i]..'"') + end + end +end + +local function write_shifted_output(output, str) + str = str:gsub('\n ', '\n') + str = str:gsub('^ ', '') + str = str:gsub(' +$', '') + output:write(str) +end + +-- start building lua output +output = io.open(lua_c_bindings_outputf, 'wb') + +output:write([[ +#include +#include +#include + +#include "nvim/func_attr.h" +#include "nvim/api/private/defs.h" +#include "nvim/viml/executor/converter.h" +]]) +include_headers(output, headers) +output:write('\n') + +lua_c_functions = {} + +local function process_function(fn) + lua_c_function_name = ('nlua_msgpack_%s'):format(fn.name) + write_shifted_output(output, string.format([[ + + static int %s(lua_State *lstate) + { + Error err = {.set = false}; + ]], lua_c_function_name)) + lua_c_functions[#lua_c_functions + 1] = { + binding=lua_c_function_name, + api=fn.name + } + cparams = '' + for j, param in ipairs(fn.parameters) do + cparam = string.format('arg%u', j) + if param[1]:match('^ArrayOf') then + param_type = 'Array' + else + param_type = param[1] + end + write_shifted_output(output, string.format([[ + %s %s = nlua_pop_%s(lstate, &err); + if (err.set) { + lua_pushstring(lstate, err.msg); + return lua_error(lstate); + } + ]], param[1], cparam, param_type)) + cparams = cparams .. cparam .. ', ' + end + if fn.receives_channel_id then + cparams = 'INTERNAL_CALL, ' .. cparams + end + if fn.can_fail then + cparams = cparams .. '&err' + else + cparams = cparams:gsub(', $', '') + end + local name = fn.impl_name or fn.name + if fn.return_type ~= 'void' then + if fn.return_type:match('^ArrayOf') then + return_type = 'Array' + else + return_type = fn.return_type + end + write_shifted_output(output, string.format([[ + %s ret = %s(%s); + if (err.set) { + lua_pushstring(lstate, err.msg); + return lua_error(lstate); + } + nlua_push_%s(lstate, ret); + return 1; + ]], fn.return_type, name, cparams, return_type)) + else + write_shifted_output(output, string.format([[ + %s(%s); + if (err.set) { + lua_pushstring(lstate, err.msg); + return lua_error(lstate); + } + return 0; + ]], name, cparams)) + end + write_shifted_output(output, [[ + } + ]]) +end + +for _, fn in ipairs(functions) do + if not fn.noeval then + process_function(fn) + end +end + +output:write(string.format([[ +void nlua_add_api_functions(lua_State *lstate) + FUNC_ATTR_NONNULL_ALL +{ + lua_createtable(lstate, 0, %u); +]], #lua_c_functions)) +for _, func in ipairs(lua_c_functions) do + output:write(string.format([[ + lua_pushcfunction(lstate, &%s); + lua_setfield(lstate, -2, "%s"); + ]], func.binding, func.api)) +end +output:write([[ + lua_setfield(lstate, -2, "api"); +} +]]) + +output:close() -- cgit From ba2f615cd40d5d809d1a141c7b098e3bd22ff7bb Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 16 Jul 2016 02:26:04 +0300 Subject: functests: Test for error conditions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During testing found the following bugs: 1. msgpack-gen.lua script is completely unprepared for Float values either in return type or in arguments. Specifically: 1. At the time of writing relevant code FLOAT_OBJ did not exist as well as FLOATING_OBJ, but it would be used by msgpack-gen.lua should return type be Float. I added FLOATING_OBJ macros later because did not know that msgpack-gen.lua uses these _OBJ macros, otherwise it would be FLOAT_OBJ. 2. msgpack-gen.lua should use .data.floating in place of .data.float. But it did not expect that .data subattribute may have name different from lowercased type name. 2. vim_replace_termcodes returned its argument as-is if it receives an empty string (as well as _vim_id*() functions did). But if something in returned argument lives in an allocated memory such action will cause double free: once when freeing arguments, then when freeing return value. It did not cause problems yet because msgpack bindings return empty string as {NULL, 0} and nothing was actually allocated. 3. New code in msgpack-gen.lua popped arguments in reversed order, making lua bindings’ signatures be different from API ones. --- scripts/genmsgpack.lua | 58 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 18 deletions(-) (limited to 'scripts') diff --git a/scripts/genmsgpack.lua b/scripts/genmsgpack.lua index dd3caab5e4..d47d637548 100644 --- a/scripts/genmsgpack.lua +++ b/scripts/genmsgpack.lua @@ -216,6 +216,14 @@ local function real_type(type) return rv end +local function attr_name(rt) + if rt == 'Float' then + return 'floating' + else + return rt:lower() + end +end + -- start the handler functions. Visit each function metadata to build the -- handler function with code generated for validating arguments and calling to -- the real API. @@ -253,7 +261,7 @@ for i = 1, #functions do output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') else output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..') {') - output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..rt:lower()..';') + output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..attr_name(rt)..';') end if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') or rt:match('^Boolean$') then -- accept nonnegative integers for Booleans, Buffers, Windows and Tabpages @@ -368,6 +376,7 @@ output:write([[ #include "nvim/func_attr.h" #include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" #include "nvim/viml/executor/converter.h" ]]) include_headers(output, headers) @@ -382,27 +391,35 @@ local function process_function(fn) static int %s(lua_State *lstate) { Error err = {.set = false}; - ]], lua_c_function_name)) + if (lua_gettop(lstate) != %i) { + api_set_error(&err, Validation, "Expected %i argument%s"); + lua_pushstring(lstate, err.msg); + return lua_error(lstate); + } + ]], lua_c_function_name, #fn.parameters, #fn.parameters, + (#fn.parameters == 1) and '' or 's')) lua_c_functions[#lua_c_functions + 1] = { binding=lua_c_function_name, api=fn.name } - cparams = '' - for j, param in ipairs(fn.parameters) do + local cparams = '' + local free_code = {} + for j = #fn.parameters,1,-1 do + param = fn.parameters[j] cparam = string.format('arg%u', j) - if param[1]:match('^ArrayOf') then - param_type = 'Array' - else - param_type = param[1] - end + param_type = real_type(param[1]) + lc_param_type = param_type:lower() write_shifted_output(output, string.format([[ - %s %s = nlua_pop_%s(lstate, &err); + const %s %s = nlua_pop_%s(lstate, &err); + if (err.set) { + %s lua_pushstring(lstate, err.msg); return lua_error(lstate); } - ]], param[1], cparam, param_type)) - cparams = cparams .. cparam .. ', ' + ]], param[1], cparam, param_type, table.concat(free_code, '\n '))) + free_code[#free_code + 1] = ('api_free_%s(%s);'):format(lc_param_type, cparam) + cparams = cparam .. ', ' .. cparams end if fn.receives_channel_id then cparams = 'INTERNAL_CALL, ' .. cparams @@ -412,7 +429,7 @@ local function process_function(fn) else cparams = cparams:gsub(', $', '') end - local name = fn.impl_name or fn.name + free_at_exit_code = table.concat(free_code, '\n ') if fn.return_type ~= 'void' then if fn.return_type:match('^ArrayOf') then return_type = 'Array' @@ -420,23 +437,27 @@ local function process_function(fn) return_type = fn.return_type end write_shifted_output(output, string.format([[ - %s ret = %s(%s); + const %s ret = %s(%s); + %s if (err.set) { lua_pushstring(lstate, err.msg); return lua_error(lstate); } nlua_push_%s(lstate, ret); + api_free_%s(ret); return 1; - ]], fn.return_type, name, cparams, return_type)) + ]], fn.return_type, fn.name, cparams, free_at_exit_code, return_type, + return_type:lower())) else write_shifted_output(output, string.format([[ %s(%s); + %s if (err.set) { lua_pushstring(lstate, err.msg); return lua_error(lstate); } return 0; - ]], name, cparams)) + ]], fn.name, cparams, free_at_exit_code)) end write_shifted_output(output, [[ } @@ -457,11 +478,12 @@ void nlua_add_api_functions(lua_State *lstate) ]], #lua_c_functions)) for _, func in ipairs(lua_c_functions) do output:write(string.format([[ + lua_pushcfunction(lstate, &%s); - lua_setfield(lstate, -2, "%s"); - ]], func.binding, func.api)) + lua_setfield(lstate, -2, "%s");]], func.binding, func.api)) end output:write([[ + lua_setfield(lstate, -2, "api"); } ]]) -- cgit From 5c1b9a0d2af86461f56f0d27ed275456921f6187 Mon Sep 17 00:00:00 2001 From: ZyX Date: Fri, 20 Jan 2017 23:06:22 +0300 Subject: api: Reserve more numbers for internal calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reasoning; currently INTERNAL_CALL is mostly used to determine whether it is needed to deal with NL-used-as-NUL problem. This code is useful for nvim_… API calls done from VimL, but not for API calls done from lua, yet lua needs to supply something as channel_id. --- scripts/genmsgpack.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/genmsgpack.lua b/scripts/genmsgpack.lua index d47d637548..aed56b29eb 100644 --- a/scripts/genmsgpack.lua +++ b/scripts/genmsgpack.lua @@ -422,7 +422,7 @@ local function process_function(fn) cparams = cparam .. ', ' .. cparams end if fn.receives_channel_id then - cparams = 'INTERNAL_CALL, ' .. cparams + cparams = 'LUA_INTERNAL_CALL, ' .. cparams end if fn.can_fail then cparams = cparams .. '&err' -- cgit From 600bee9d4fa22ab914175a9edf82bb3503f47cda Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 21 Jan 2017 00:59:13 +0300 Subject: genmsgpack: Include error source in error messages --- scripts/genmsgpack.lua | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'scripts') diff --git a/scripts/genmsgpack.lua b/scripts/genmsgpack.lua index aed56b29eb..2a7cb4bacf 100644 --- a/scripts/genmsgpack.lua +++ b/scripts/genmsgpack.lua @@ -393,8 +393,7 @@ local function process_function(fn) Error err = {.set = false}; if (lua_gettop(lstate) != %i) { api_set_error(&err, Validation, "Expected %i argument%s"); - lua_pushstring(lstate, err.msg); - return lua_error(lstate); + return luaL_error(lstate, "%%s", err.msg); } ]], lua_c_function_name, #fn.parameters, #fn.parameters, (#fn.parameters == 1) and '' or 's')) @@ -414,8 +413,7 @@ local function process_function(fn) if (err.set) { %s - lua_pushstring(lstate, err.msg); - return lua_error(lstate); + return luaL_error(lstate, "%%s", err.msg); } ]], param[1], cparam, param_type, table.concat(free_code, '\n '))) free_code[#free_code + 1] = ('api_free_%s(%s);'):format(lc_param_type, cparam) @@ -440,8 +438,7 @@ local function process_function(fn) const %s ret = %s(%s); %s if (err.set) { - lua_pushstring(lstate, err.msg); - return lua_error(lstate); + return luaL_error(lstate, "%%s", err.msg); } nlua_push_%s(lstate, ret); api_free_%s(ret); @@ -453,8 +450,7 @@ local function process_function(fn) %s(%s); %s if (err.set) { - lua_pushstring(lstate, err.msg); - return lua_error(lstate); + return luaL_error(lstate, "%%s", err.msg); } return 0; ]], fn.name, cparams, free_at_exit_code)) @@ -465,7 +461,7 @@ local function process_function(fn) end for _, fn in ipairs(functions) do - if not fn.noeval then + if not fn.noeval or fn.name:sub(1, 4) == '_vim' then process_function(fn) end end -- cgit From 6b4a51f7ea49a6ef8305831e8d96b2a7cc4ba5f3 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 22 Jan 2017 04:34:26 +0300 Subject: scripts: Make generate_vim_module more generic --- scripts/gencharblob.lua | 48 +++++++++++++++++++++++++++++++++++++++++ scripts/generate_vim_module.lua | 38 -------------------------------- 2 files changed, 48 insertions(+), 38 deletions(-) create mode 100644 scripts/gencharblob.lua delete mode 100644 scripts/generate_vim_module.lua (limited to 'scripts') diff --git a/scripts/gencharblob.lua b/scripts/gencharblob.lua new file mode 100644 index 0000000000..d860375e26 --- /dev/null +++ b/scripts/gencharblob.lua @@ -0,0 +1,48 @@ +if arg[1] == '--help' then + print('Usage:') + print(' gencharblob.lua source target varname') + print('') + print('Generates C file with big uint8_t blob.') + print('Blob will be stored in a static const array named varname.') + os.exit() +end + +assert(#arg == 3) + +local source_file = arg[1] +local target_file = arg[2] +local varname = arg[3] + +source = io.open(source_file, 'r') +target = io.open(target_file, 'w') + +target:write('#include \n\n') +target:write(('static const uint8_t %s[] = {\n'):format(varname)) + +num_bytes = 0 +MAX_NUM_BYTES = 15 -- 78 / 5: maximum number of bytes on one line +target:write(' ') + +increase_num_bytes = function() + num_bytes = num_bytes + 1 + if num_bytes == MAX_NUM_BYTES then + num_bytes = 0 + target:write('\n ') + end +end + +for line in source:lines() do + for i = 1,string.len(line) do + byte = string.byte(line, i) + assert(byte ~= 0) + target:write(string.format(' %3u,', byte)) + increase_num_bytes() + end + target:write(string.format(' %3u,', string.byte('\n', 1))) + increase_num_bytes() +end + +target:write(' 0};\n') + +source:close() +target:close() diff --git a/scripts/generate_vim_module.lua b/scripts/generate_vim_module.lua deleted file mode 100644 index 954f1c38be..0000000000 --- a/scripts/generate_vim_module.lua +++ /dev/null @@ -1,38 +0,0 @@ -assert(#arg == 2) - -module_file = arg[1] -target_file = arg[2] - -module = io.open(module_file, 'r') -target = io.open(target_file, 'w') - -target:write('#include \n\n') -target:write('static const uint8_t vim_module[] = {\n') - -num_bytes = 0 -MAX_NUM_BYTES = 15 -- 78 / 5: maximum number of bytes on one line -target:write(' ') - -increase_num_bytes = function() - num_bytes = num_bytes + 1 - if num_bytes == MAX_NUM_BYTES then - num_bytes = 0 - target:write('\n ') - end -end - -for line in module:lines() do - for i = 1,string.len(line) do - byte = string.byte(line, i) - assert(byte ~= 0) - target:write(string.format(' %3u,', byte)) - increase_num_bytes() - end - target:write(string.format(' %3u,', string.byte('\n', 1))) - increase_num_bytes() -end - -target:write(' 0};\n') - -module:close() -target:close() -- cgit From f74322b9a5695d2a3bf31e1da05197d700b94c76 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 28 Jan 2017 00:46:58 +0300 Subject: gendeclarations: Save where declaration is comping from --- scripts/gendeclarations.lua | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/gendeclarations.lua b/scripts/gendeclarations.lua index ff69b18ae4..6358ea4778 100755 --- a/scripts/gendeclarations.lua +++ b/scripts/gendeclarations.lua @@ -188,23 +188,29 @@ local footer = [[ local non_static = header local static = header -local filepattern = '^#%a* %d+ "[^"]-/?([^"/]+)"' +local filepattern = '^#%a* (%d+) "[^"]-/?([^"/]+)"' local curfile init = 0 curfile = nil neededfile = fname:match('[^/]+$') +local declline = 0 +local declendpos = 0 while init ~= nil do init = text:find('\n', init) if init == nil then break end init = init + 1 + declline = declline + 1 if text:sub(init, init) == '#' then - file = text:match(filepattern, init) + local line, file = text:match(filepattern, init) if file ~= nil then curfile = file end + declline = tonumber(line) - 1 + elseif init < declendpos then + -- Skipping over declaration elseif curfile == neededfile then s = init e = pattern:match(text, init) @@ -225,13 +231,15 @@ while init ~= nil do declaration = declaration:gsub(' ?(%*+) ?', ' %1') declaration = declaration:gsub(' ?(FUNC_ATTR_)', ' %1') declaration = declaration:gsub(' $', '') - declaration = declaration .. ';\n' + declaration = declaration .. ';' + declaration = declaration .. ' // ' .. curfile .. ':' .. declline + declaration = declaration .. '\n' if text:sub(s, s + 5) == 'static' then static = static .. declaration else non_static = non_static .. declaration end - init = e + declendpos = e end end end -- cgit From c470fc32a8c96fb153b779489c22b8e86003e9f0 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 28 Jan 2017 00:52:27 +0300 Subject: gendeclarations: Also save information about directory --- scripts/gendeclarations.lua | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/gendeclarations.lua b/scripts/gendeclarations.lua index 6358ea4778..5d5939f7d1 100755 --- a/scripts/gendeclarations.lua +++ b/scripts/gendeclarations.lua @@ -188,14 +188,15 @@ local footer = [[ local non_static = header local static = header -local filepattern = '^#%a* (%d+) "[^"]-/?([^"/]+)"' +local filepattern = '^#%a* (%d+) "([^"]-)/?([^"/]+)"' local curfile -init = 0 -curfile = nil -neededfile = fname:match('[^/]+$') +local init = 0 +local curfile = nil +local neededfile = fname:match('[^/]+$') local declline = 0 local declendpos = 0 +local curdir = nil while init ~= nil do init = text:find('\n', init) if init == nil then @@ -204,11 +205,17 @@ while init ~= nil do init = init + 1 declline = declline + 1 if text:sub(init, init) == '#' then - local line, file = text:match(filepattern, init) + local line, dir, file = text:match(filepattern, init) if file ~= nil then curfile = file end declline = tonumber(line) - 1 + local curdir_start = dir:find('src/nvim/') + if curdir_start ~= nil then + curdir = dir:sub(curdir_start + #('src/nvim/')) + else + curdir = dir + end elseif init < declendpos then -- Skipping over declaration elseif curfile == neededfile then @@ -232,7 +239,8 @@ while init ~= nil do declaration = declaration:gsub(' ?(FUNC_ATTR_)', ' %1') declaration = declaration:gsub(' $', '') declaration = declaration .. ';' - declaration = declaration .. ' // ' .. curfile .. ':' .. declline + declaration = declaration .. (' // %s/%s:%u'):format( + curdir, curfile, declline) declaration = declaration .. '\n' if text:sub(s, s + 5) == 'static' then static = static .. declaration -- cgit From 52c7066f4b546419a1838b41e68a5d1650ac498e Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 28 Jan 2017 01:07:18 +0300 Subject: gendeclarations: Handle case when text did not match --- scripts/gendeclarations.lua | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/gendeclarations.lua b/scripts/gendeclarations.lua index 5d5939f7d1..3f948b91df 100755 --- a/scripts/gendeclarations.lua +++ b/scripts/gendeclarations.lua @@ -208,13 +208,15 @@ while init ~= nil do local line, dir, file = text:match(filepattern, init) if file ~= nil then curfile = file - end - declline = tonumber(line) - 1 - local curdir_start = dir:find('src/nvim/') - if curdir_start ~= nil then - curdir = dir:sub(curdir_start + #('src/nvim/')) + declline = tonumber(line) - 1 + local curdir_start = dir:find('src/nvim/') + if curdir_start ~= nil then + curdir = dir:sub(curdir_start + #('src/nvim/')) + else + curdir = dir + end else - curdir = dir + declline = declline - 1 end elseif init < declendpos then -- Skipping over declaration -- cgit From ae4adcc70735a89bffb110bcf9d5a993b0786c4d Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 28 Jan 2017 03:47:15 +0300 Subject: gendeclarations: Make declarations generator work with macros funcs Now it checks functions also after every semicolon and closing figure brace, possibly preceded by whitespaces (tabs and spaces). This should make messing with declarations in macros not needed. --- scripts/gendeclarations.lua | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'scripts') diff --git a/scripts/gendeclarations.lua b/scripts/gendeclarations.lua index 3f948b91df..e999e53e4a 100755 --- a/scripts/gendeclarations.lua +++ b/scripts/gendeclarations.lua @@ -69,17 +69,18 @@ local word = branch( right_word ) ) +local inline_comment = concat( + lit('/*'), + any_amount(concat( + neg_look_ahead(lit('*/')), + any_character + )), + lit('*/') +) local spaces = any_amount(branch( s, -- Comments are really handled by preprocessor, so the following is not needed - concat( - lit('/*'), - any_amount(concat( - neg_look_ahead(lit('*/')), - any_character - )), - lit('*/') - ), + inline_comment, concat( lit('//'), any_amount(concat( @@ -110,6 +111,7 @@ local typ = one_or_more(typ_part) local typ_id = two_or_more(typ_part) local arg = typ_id -- argument name is swallowed by typ local pattern = concat( + any_amount(branch(set(' ', '\t'), inline_comment)), typ_id, -- return type with function name spaces, lit('('), @@ -197,17 +199,22 @@ local neededfile = fname:match('[^/]+$') local declline = 0 local declendpos = 0 local curdir = nil +local is_needed_file = false while init ~= nil do - init = text:find('\n', init) + init = text:find('[\n;}]', init) if init == nil then break end + local init_is_nl = text:sub(init, init) == '\n' init = init + 1 - declline = declline + 1 - if text:sub(init, init) == '#' then + if init_is_nl and is_needed_file then + declline = declline + 1 + end + if init_is_nl and text:sub(init, init) == '#' then local line, dir, file = text:match(filepattern, init) if file ~= nil then curfile = file + is_needed_file = (curfile == neededfile) declline = tonumber(line) - 1 local curdir_start = dir:find('src/nvim/') if curdir_start ~= nil then @@ -220,7 +227,7 @@ while init ~= nil do end elseif init < declendpos then -- Skipping over declaration - elseif curfile == neededfile then + elseif is_needed_file then s = init e = pattern:match(text, init) if e ~= nil then @@ -240,11 +247,12 @@ while init ~= nil do declaration = declaration:gsub(' ?(%*+) ?', ' %1') declaration = declaration:gsub(' ?(FUNC_ATTR_)', ' %1') declaration = declaration:gsub(' $', '') + declaration = declaration:gsub('^ ', '') declaration = declaration .. ';' declaration = declaration .. (' // %s/%s:%u'):format( curdir, curfile, declline) declaration = declaration .. '\n' - if text:sub(s, s + 5) == 'static' then + if declaration:sub(1, 6) == 'static' then static = static .. declaration else non_static = non_static .. declaration -- cgit From f98a3d85ed2f34a62300097fd30b393a3b3be393 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 11 Apr 2017 01:09:36 +0300 Subject: lua: Move files from src/nvim/viml/executor to src/nvim/lua --- scripts/genmsgpack.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/genmsgpack.lua b/scripts/genmsgpack.lua index 2a7cb4bacf..c3b3f42618 100644 --- a/scripts/genmsgpack.lua +++ b/scripts/genmsgpack.lua @@ -377,7 +377,7 @@ output:write([[ #include "nvim/func_attr.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" -#include "nvim/viml/executor/converter.h" +#include "nvim/lua/converter.h" ]]) include_headers(output, headers) output:write('\n') -- cgit From 7d0fc179e689ca12f647166b8687928a7a65e380 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Tue, 11 Apr 2017 23:56:18 +0300 Subject: genmsgpack: Do not export functions with __ --- scripts/genmsgpack.lua | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/genmsgpack.lua b/scripts/genmsgpack.lua index c3b3f42618..9018ac8576 100644 --- a/scripts/genmsgpack.lua +++ b/scripts/genmsgpack.lua @@ -127,7 +127,9 @@ local deprecated_aliases = require("api.dispatch_deprecated") for i,f in ipairs(shallowcopy(functions)) do local ismethod = false if startswith(f.name, "nvim_") then - if f.since == nil then + if startswith(f.name, "nvim__") then + f.since = -1 + elseif f.since == nil then print("Function "..f.name.." lacks since field.\n") os.exit(1) end @@ -174,11 +176,13 @@ exported_attributes = {'name', 'parameters', 'return_type', 'method', 'since', 'deprecated_since'} exported_functions = {} for _,f in ipairs(functions) do - local f_exported = {} - for _,attr in ipairs(exported_attributes) do - f_exported[attr] = f[attr] + if not startswith(f.name, "nvim__") then + local f_exported = {} + for _,attr in ipairs(exported_attributes) do + f_exported[attr] = f[attr] + end + exported_functions[#exported_functions+1] = f_exported end - exported_functions[#exported_functions+1] = f_exported end -- cgit From 8dc3eca49ba4203fb28ae4d70f3bfac35442199a Mon Sep 17 00:00:00 2001 From: Patrick Jackson Date: Mon, 24 Apr 2017 03:39:48 -0700 Subject: api/dispatch: Mark generated functions table readonly (#6576) --- scripts/geneval.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/geneval.lua b/scripts/geneval.lua index b1ba76296c..b17ecb1a0c 100644 --- a/scripts/geneval.lua +++ b/scripts/geneval.lua @@ -41,6 +41,7 @@ funcsdata:close() gperfpipe:write([[ %language=ANSI-C %global-table +%readonly-tables %define initializer-suffix ,0,0,NULL,NULL %define word-array-name functions %define hash-function-name hash_internal_func_gperf -- cgit From 0df1b6655be5385c9cbb70dca1c042c6447ec50b Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sat, 29 Apr 2017 16:56:40 +0200 Subject: doc: Removed t_XX options/keycodes. (#6616) Closes #4482 TODO: revisit find_key_option_len() --- scripts/vim-patch.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index 3ade90a65b..3b083e7b83 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -136,7 +136,7 @@ preprocess_patch() { 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\S*\<\%('${na_src}'\)@norm! d/\v(^diff)|%$ ' +w +q "$file" # Remove channel.txt, netbeans.txt, os_*.txt, todo.txt, version*.txt, tags - local na_doc='channel\.txt\|netbeans\.txt\|os_\w\+\.txt\|todo\.txt\|version\d\.txt\|tags' + local na_doc='channel\.txt\|netbeans\.txt\|os_\w\+\.txt\|term\.txt\|todo\.txt\|version\d\.txt\|tags' 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/doc/\<\%('${na_doc}'\)\>@norm! d/\v(^diff)|%$ ' +w +q "$file" # Remove "Last change ..." changes in doc files. -- cgit From 97126bfa020f714d78e5e6f82b59c697ce7dd467 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 30 Apr 2017 09:16:11 +0200 Subject: api: deprecate obsolete nvim_buf_get_number function --- scripts/gendispatch.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'scripts') diff --git a/scripts/gendispatch.lua b/scripts/gendispatch.lua index 0ee3ae6475..c0291c55d3 100644 --- a/scripts/gendispatch.lua +++ b/scripts/gendispatch.lua @@ -37,6 +37,8 @@ c_proto = Ct( fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * Cg(Cc(false), 'async') * (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) * + (fill * Cg((P('FUNC_API_DEPRECATED_SINCE(') * C(num ^ 1)) * P(')'), + 'deprecated_since') ^ -1) * (fill * Cg((P('FUNC_API_ASYNC') * Cc(true)), 'async') ^ -1) * (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) * (fill * Cg((P('FUNC_API_NOEVAL') * Cc(true)), 'noeval') ^ -1) * @@ -122,6 +124,10 @@ for i,f in ipairs(shallowcopy(functions)) do os.exit(1) end f.since = tonumber(f.since) + if f.deprecated_since ~= nil then + f.deprecated_since = tonumber(f.deprecated_since) + end + if startswith(f.name, "nvim_buf_") then ismethod = true elseif startswith(f.name, "nvim_win_") then -- cgit From 9a1b144054a7f0eaa31c17df91a3879b61d9748a Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 1 May 2017 21:04:13 +0200 Subject: scripts/release.sh --- scripts/release.sh | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/release.sh b/scripts/release.sh index dac5e9b177..692b46e921 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -18,6 +18,8 @@ set -e set -u set -o pipefail +USE_CURRENT_COMMIT=${1:-no} + __sed=$( [ "$(uname)" = Darwin ] && echo 'sed -E' || echo 'sed -r' ) cd "$(git rev-parse --show-toplevel)" @@ -51,15 +53,18 @@ echo "Release version: ${__VERSION}" $__sed -i.bk 's/(NVIM_VERSION_PRERELEASE) "-dev"/\1 ""/' CMakeLists.txt if grep '(NVIM_API_PRERELEASE true)' CMakeLists.txt > /dev/null; then $__sed -i.bk 's/(NVIM_API_PRERELEASE) true/\1 false/' CMakeLists.txt - cp build/funcs_data.mpack test/functional/fixtures/api_level_$__API_LEVEL.mpack + build/bin/nvim --api-info > test/functional/fixtures/api_level_$__API_LEVEL.mpack git add test/functional/fixtures/api_level_$__API_LEVEL.mpack fi -echo "Building changelog since ${__LAST_TAG}..." -__CHANGELOG="$(./scripts/git-log-pretty-since.sh "$__LAST_TAG" 'vim-patch:\S')" +if ! test "$USE_CURRENT_COMMIT" = 'use-current-commit' ; then + echo "Building changelog since ${__LAST_TAG}..." + __CHANGELOG="$(./scripts/git-log-pretty-since.sh "$__LAST_TAG" 'vim-patch:\S')" + + git add CMakeLists.txt + git commit --edit -m "${__RELEASE_MSG} ${__CHANGELOG}" +fi -git add CMakeLists.txt -git commit --edit -m "${__RELEASE_MSG} ${__CHANGELOG}" git tag --sign -a v"${__VERSION}" -m "NVIM v${__VERSION}" $__sed -i.bk 's/(NVIM_VERSION_PRERELEASE) ""/\1 "-dev"/' CMakeLists.txt -- cgit From bcc97afbd258c8608e73ff7765c33fe5da713fb9 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 2 May 2017 01:54:21 +0300 Subject: pvscheck: Do not use `test x` [ci skip] --- scripts/pvscheck.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index 32d63646aa..6e95358aa8 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -135,16 +135,16 @@ do_recheck() { main() { local PVS_URL="http://files.viva64.com/pvs-studio-6.14.21446.1-x86_64.tgz" - if test "x$1" = "x--help" ; then + if test "$1" = "--help" ; then help return fi set -x - if test "x$1" = "x--patch" ; then + if test "$1" = "--patch" ; then shift - if test "x$1" = "x--only-build" ; then + if test "$1" = "--only-build" ; then shift patch_sources --only-build else @@ -154,7 +154,7 @@ main() { fi local recheck= - if test "x$1" = "x--recheck" ; then + if test "$1" = "--recheck" ; then recheck=1 shift fi @@ -162,7 +162,7 @@ main() { local tgt="${1:-$PWD/../neovim-pvs}" local branch="${2:-master}" - if test "x$recheck" = "x" ; then + if test -z "$recheck" ; then do_check "$tgt" "$branch" else do_recheck "$tgt" -- cgit From 7fc3cccfaabf8f576af73a21d7538257df4d41ed Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 2 May 2017 01:54:44 +0300 Subject: pvscheck: Update pvs-studio URL [ci skip] --- scripts/pvscheck.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index 6e95358aa8..c8928dc266 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -133,7 +133,7 @@ do_recheck() { } main() { - local PVS_URL="http://files.viva64.com/pvs-studio-6.14.21446.1-x86_64.tgz" + local PVS_URL="http://files.viva64.com/pvs-studio-6.15.21741.1-x86_64.tgz" if test "$1" = "--help" ; then help -- cgit From 15d39022abc3eb3d086b33977b9dec9972aab8e1 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 2 May 2017 02:08:16 +0300 Subject: pvscheck: Add --pvs key to pvscheck.sh [ci skip] --- scripts/pvscheck.sh | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index c8928dc266..2af38d7711 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -10,10 +10,17 @@ get_jobs_num() { help() { echo 'Usage:' - echo ' pvscheck.sh [target-directory [branch]]' - echo ' pvscheck.sh [--recheck] [target-directory]' + echo ' pvscheck.sh [--pvs URL] [target-directory [branch]]' + echo ' pvscheck.sh [--pvs URL] [--recheck] [target-directory]' echo ' pvscheck.sh --patch [--only-build]' echo + echo ' --pvs: Use the specified URL as a path to pvs-studio archive.' + echo ' By default latest tested version is used.' + echo + echo ' May use `--pvs detect` to try detecting latest version.' + echo ' That assumes certain viva64.com site properties and' + echo ' may be broken by the site update.' + echo echo ' --patch: patch sources in the current directory.' echo ' Does not patch already patched files.' echo ' Does not run analysis.' @@ -38,10 +45,12 @@ EOF } install_pvs() { + local pvs_url="$1" + mkdir pvs-studio cd pvs-studio - curl -o pvs-studio.tar.gz "$PVS_URL" + curl -L -o pvs-studio.tar.gz "$pvs_url" tar xzf pvs-studio.tar.gz rm pvs-studio.tar.gz local pvsdir="$(find . -maxdepth 1 -mindepth 1)" @@ -108,14 +117,15 @@ run_analysis() { } do_check() { - local tgt="${1}" - local branch="${2}" + local tgt="$1" + local branch="$2" + local pvs_url="$3" git clone --branch="$branch" . "$tgt" cd "$tgt" - install_pvs + install_pvs "$pvs_url" create_compile_commands @@ -132,8 +142,13 @@ do_recheck() { run_analysis } +detect_url() { + curl -L 'https://www.viva64.com/en/pvs-studio-download-linux/' \ + | grep -o 'https\{0,1\}://[^"<>]\{1,\}/pvs-studio[^/"<>]*\.tgz' +} + main() { - local PVS_URL="http://files.viva64.com/pvs-studio-6.15.21741.1-x86_64.tgz" + local pvs_url="http://files.viva64.com/pvs-studio-6.15.21741.1-x86_64.tgz" if test "$1" = "--help" ; then help @@ -142,6 +157,15 @@ main() { set -x + if test "$1" = "--pvs" ; then + shift + pvs_url="$1" ; shift + + if test "$pvs_url" = "detect" ; then + pvs_url="$(detect_url)" + fi + fi + if test "$1" = "--patch" ; then shift if test "$1" = "--only-build" ; then @@ -163,7 +187,7 @@ main() { local branch="${2:-master}" if test -z "$recheck" ; then - do_check "$tgt" "$branch" + do_check "$tgt" "$branch" "$pvs_url" else do_recheck "$tgt" fi -- cgit From 4cb61aa7428128283c45ee3ca90f01c4805c8148 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 2 May 2017 17:56:30 +0300 Subject: pvscheck: Create getopts_long implementation Needed as argument list is growing large and I absolutely do not find short options provided by getopts being particularly readable for unfamiliar commands. [ci skip] --- scripts/pvscheck.sh | 258 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 212 insertions(+), 46 deletions(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index 2af38d7711..51ecaf0c46 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -1,5 +1,8 @@ #!/bin/sh set -e +# Note: -u causes problems with posh, it barks at “undefined” $@ when no +# arguments provided. +test -z "$POSH_VERSION" && set -u get_jobs_num() { local num="$(cat /proc/cpuinfo | grep -c "^processor")" @@ -36,6 +39,178 @@ help() { echo ' Default: master.' } +getopts_error() { + printf '%s\n' "$1" >&2 + echo 'return 1' + return 1 +} + +# Usage `eval "$(getopts_long long_defs -- positionals_defs -- "$@")"` +# +# long_defs: list of pairs of arguments like `longopt action`. +# positionals_defs: list of arguments like `action`. +# +# `action` is a space-separated commands: +# +# store_const [const] [varname] [default] +# Store constant [const] (default 1) (note: eval’ed) if argument is present +# (long options only). Assumes long option accepts no arguments. +# store [varname] [default] +# Store value. Assumes long option needs an argument. +# run {func} [varname] [default] +# Run function {func} and store its output to the [varname]. Assumes no +# arguments accepted (long options only). +# modify {func} [varname] [default] +# Like run, but assumes a single argument, passed to function {func} as $1. +# +# All actions stores empty value if neither [varname] nor [default] are +# present. [default] is evaled by top-level `eval`, so be careful. Also note +# that no arguments may contain spaces, including [default] and [const]. +getopts_long() { + local positional= + local opt_bases="" + while test $# -gt 0 ; do + local arg="$1" ; shift + local opt_base= + local act= + local opt_name= + if test -z "$positional" ; then + if test "$arg" = "--" ; then + positional=0 + continue + fi + act="$1" ; shift + opt_name="$(echo "$arg" | tr '-' '_')" + opt_base="longopt_$opt_name" + else + if test "$arg" = "--" ; then + break + fi + : $(( positional+=1 )) + act="$arg" + opt_name="arg_$positional" + opt_base="positional_$positional" + fi + opt_bases="$opt_bases $opt_base" + eval "local varname_$opt_base=$opt_name" + local i=0 + for act_subarg in $act ; do + eval "local act_$(( i+=1 ))_$opt_base=\"\$act_subarg\"" + done + done + # Process options + local positional=0 + local force_positional= + while test $# -gt 0 ; do + local argument="$1" ; shift + local opt_base= + local has_equal= + local equal_arg= + local is_positional= + if test "$argument" = "--" ; then + force_positional=1 + continue + elif test -z "$force_positional" && test "${argument#--}" != "$argument" + then + local opt_name="${argument#--}" + local opt_name_striparg="${opt_name%%=*}" + if test "$opt_name" = "$opt_name_striparg" ; then + has_equal=0 + else + has_equal=1 + equal_arg="${argument#*=}" + opt_name="$opt_name_striparg" + fi + # Use trailing x to prevent stripping newlines + opt_name="$(printf '%sx' "$opt_name" | tr '-' '_')" + opt_name="${opt_name%x}" + if test -n "$(printf '%sx' "$opt_name" | tr -d 'a-z_')" ; then + getopts_error "Option contains invalid characters: $opt_name" + fi + opt_base="longopt_$opt_name" + else + : $(( positional+=1 )) + opt_base="positional_$positional" + is_positional=1 + fi + if test -n "$opt_base" ; then + eval "local occurred_$opt_base=1" + + eval "local act_1=\"\$act_1_$opt_base\"" + eval "local varname=\"\$varname_$opt_base\"" + local need_val= + local func= + case "$act_1" in + (store_const) + eval "local const=\"\${act_2_${opt_base}:-1}\"" + eval "local varname=\"\${act_3_${opt_base}:-$varname}\"" + printf 'local %s=%s\n' "$varname" "$const" + ;; + (store) + eval "varname=\"\${act_2_${opt_base}:-$varname}\"" + need_val=1 + ;; + (run) + eval "func=\"\${act_2_${opt_base}}\"" + eval "varname=\"\${act_3_${opt_base}:-$varname}\"" + printf 'local %s="$(%s)"\n' "$varname" "$func" + ;; + (modify) + eval "func=\"\${act_2_${opt_base}}\"" + eval "varname=\"\${act_3_${opt_base}:-$varname}\"" + need_val=1 + ;; + esac + if test -n "$need_val" ; then + local val= + if test -z "$is_positional" ; then + if test $has_equal = 1 ; then + val="$equal_arg" + else + if test $# -eq 0 ; then + getopts_error "Missing argument for $opt_name" + fi + val="$1" ; shift + fi + else + val="$argument" + fi + local escaped_val="'$(printf "%s" "$val" | sed "s/'/'\\\\''/g")'" + case "$act_1" in + (store) + printf 'local %s=%s\n' "$varname" "$escaped_val" + ;; + (modify) + printf 'local %s="$(%s %s)"\n' "$varname" "$func" "$escaped_val" + ;; + esac + fi + fi + done + # Print default values when no values were provided + local opt_base= + for opt_base in $opt_bases ; do + eval "local occurred=\"\${occurred_$opt_base:-}\"" + if test -n "$occurred" ; then + continue + fi + eval "local act_1=\"\$act_1_$opt_base\"" + eval "local varname=\"\$varname_$opt_base\"" + case "$act_1" in + (store) + eval "local varname=\"\${act_2_${opt_base}:-$varname}\"" + eval "local default=\"\${act_3_${opt_base}:-}\"" + printf 'local %s=%s\n' "$varname" "$default" + ;; + (store_const|run|modify) + eval "local varname=\"\${act_3_${opt_base}:-$varname}\"" + eval "local default=\"\${act_4_${opt_base}:-}\"" + printf 'local %s=%s\n' "$varname" "$default" + ;; + esac + done +} + get_pvs_comment() { cat > pvs-comment << EOF // This is an open source non-commercial project. Dear PVS-Studio, please check @@ -62,18 +237,16 @@ install_pvs() { cd .. } -create_compile_commands() { +create_compile_commands() {( + export CC=clang + export CFLAGS=' -O0 ' + mkdir build cd build - env \ - CC=clang \ - CFLAGS=' -O0 ' \ - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="$PWD/root" + cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="$PWD/root" make -j"$(get_jobs_num)" find src/nvim/auto -name '*.test-include.c' -delete - - cd .. -} +)} patch_sources() { get_pvs_comment @@ -87,7 +260,7 @@ patch_sources() { fi ' - if test "x$1" != "x--only-build" ; then + if test "${1:-}" != "--only-build" ; then find \ src/nvim test/functional/fixtures test/unit/fixtures \ -name '*.c' \ @@ -117,9 +290,9 @@ run_analysis() { } do_check() { - local tgt="$1" - local branch="$2" - local pvs_url="$3" + local tgt="$1" ; shift + local branch="$1" ; shift + local pvs_url="$1" ; shift git clone --branch="$branch" . "$tgt" @@ -133,7 +306,7 @@ do_check() { } do_recheck() { - local tgt="${1}" + local tgt="$1" cd "$tgt" @@ -143,49 +316,42 @@ do_recheck() { } detect_url() { - curl -L 'https://www.viva64.com/en/pvs-studio-download-linux/' \ - | grep -o 'https\{0,1\}://[^"<>]\{1,\}/pvs-studio[^/"<>]*\.tgz' + local url="${1:-detect}" + if test "$url" = detect ; then + curl -L 'https://www.viva64.com/en/pvs-studio-download-linux/' \ + | grep -o 'https\{0,1\}://[^"<>]\{1,\}/pvs-studio[^/"<>]*\.tgz' + else + printf '%s' "$url" + fi } main() { - local pvs_url="http://files.viva64.com/pvs-studio-6.15.21741.1-x86_64.tgz" - - if test "$1" = "--help" ; then + local def_pvs_url="http://files.viva64.com/pvs-studio-6.15.21741.1-x86_64.tgz" + eval "$( + getopts_long \ + help store_const \ + pvs 'modify detect_url pvs_url "${def_pvs_url}"' \ + patch store_const \ + only-build 'store_const --only-build' \ + recheck store_const \ + -- \ + 'store tgt "$PWD/../neovim-pvs"' \ + 'store branch master' \ + -- "$@" + )" + + if test -n "$help" ; then help - return + return 0 fi set -x - if test "$1" = "--pvs" ; then - shift - pvs_url="$1" ; shift - - if test "$pvs_url" = "detect" ; then - pvs_url="$(detect_url)" - fi - fi - - if test "$1" = "--patch" ; then - shift - if test "$1" = "--only-build" ; then - shift - patch_sources --only-build - else - patch_sources - fi - exit $? + if test -n "$patch" ; then + patch_sources "$only_build" + return $? fi - local recheck= - if test "$1" = "--recheck" ; then - recheck=1 - shift - fi - - local tgt="${1:-$PWD/../neovim-pvs}" - local branch="${2:-master}" - if test -z "$recheck" ; then do_check "$tgt" "$branch" "$pvs_url" else -- cgit From 68945ead6327aa7050fd3a82f5803e007ab5d979 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 2 May 2017 18:08:48 +0300 Subject: pvscheck: Refactor script so that it only `cd`s in a subshell [ci skip] --- scripts/pvscheck.sh | 66 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 23 deletions(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index 51ecaf0c46..7e965f5edf 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -212,15 +212,20 @@ getopts_long() { } get_pvs_comment() { - cat > pvs-comment << EOF + local tgt="$1" ; shift + + cat > "$tgt/pvs-comment" << EOF // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com EOF } -install_pvs() { - local pvs_url="$1" +install_pvs() {( + local tgt="$1" ; shift + local pvs_url="$1" ; shift + + cd "$tgt" mkdir pvs-studio cd pvs-studio @@ -231,25 +236,36 @@ install_pvs() { local pvsdir="$(find . -maxdepth 1 -mindepth 1)" find "$pvsdir" -maxdepth 1 -mindepth 1 -exec mv '{}' . \; rmdir "$pvsdir" +)} - export PATH="$PWD/bin${PATH+:}${PATH}" - - cd .. +adjust_path() { + if test -d "$tgt/pvs-studio" ; then + local saved_pwd="$PWD" + cd "$tgt/pvs-studio" + export PATH="$PWD/bin${PATH+:}${PATH}" + cd "$saved_pwd" + fi } create_compile_commands() {( + local tgt="$1" ; shift + export CC=clang export CFLAGS=' -O0 ' - mkdir build - cd build + mkdir "$tgt/build" + cd "$tgt/build" + cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="$PWD/root" make -j"$(get_jobs_num)" find src/nvim/auto -name '*.test-include.c' -delete )} -patch_sources() { - get_pvs_comment +patch_sources() {( + local tgt="$1" ; shift + local only_bulid="${1:-}" + + get_pvs_comment "$tgt" local sh_script=' pvs_comment="$(cat pvs-comment ; echo -n EOS)" @@ -260,7 +276,9 @@ patch_sources() { fi ' - if test "${1:-}" != "--only-build" ; then + cd "$tgt" + + if test "$only_build" != "--only-build" ; then find \ src/nvim test/functional/fixtures test/unit/fixtures \ -name '*.c' \ @@ -273,9 +291,13 @@ patch_sources() { -exec /bin/sh -c "$sh_script" - '{}' \; rm pvs-comment -} +)} + +run_analysis() {( + local tgt="$1" ; shift + + cd "$tgt" -run_analysis() { pvs-studio-analyzer \ analyze \ --threads "$(get_jobs_num)" \ @@ -287,7 +309,7 @@ run_analysis() { plog-converter -t xml -o PVS-studio.xml PVS-studio.log plog-converter -t errorfile -o PVS-studio.err PVS-studio.log plog-converter -t tasklist -o PVS-studio.tsk PVS-studio.log -} +)} do_check() { local tgt="$1" ; shift @@ -296,23 +318,21 @@ do_check() { git clone --branch="$branch" . "$tgt" - cd "$tgt" + install_pvs "$tgt" "$pvs_url" - install_pvs "$pvs_url" + adjust_path "$tgt" - create_compile_commands + create_compile_commands "$tgt" - run_analysis + run_analysis "$tgt" } do_recheck() { local tgt="$1" - cd "$tgt" - - export PATH="$PWD/pvs-studio/bin${PATH+:}${PATH}" + adjust_path "$tgt" - run_analysis + run_analysis "$tgt" } detect_url() { @@ -348,7 +368,7 @@ main() { set -x if test -n "$patch" ; then - patch_sources "$only_build" + patch_sources "$only_build" "$tgt" return $? fi -- cgit From 97806ee6d682ca8912f95825c485d96410802138 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 2 May 2017 18:17:12 +0300 Subject: pvscheck: Add --pvs-install mode [ci skip] --- scripts/pvscheck.sh | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index 7e965f5edf..39de763fe2 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -15,6 +15,7 @@ help() { echo 'Usage:' echo ' pvscheck.sh [--pvs URL] [target-directory [branch]]' echo ' pvscheck.sh [--pvs URL] [--recheck] [target-directory]' + echo ' pvscheck.sh [--pvs URL] --pvs-install {target-directory}' echo ' pvscheck.sh --patch [--only-build]' echo echo ' --pvs: Use the specified URL as a path to pvs-studio archive.' @@ -24,12 +25,14 @@ help() { echo ' That assumes certain viva64.com site properties and' echo ' may be broken by the site update.' echo + echo ' --only-build: (for --patch) Only patch files in ./build directory.' + echo + echo ' --pvs-install: Only install PVS-studio to the specified location.' + echo echo ' --patch: patch sources in the current directory.' echo ' Does not patch already patched files.' echo ' Does not run analysis.' echo - echo ' --only-build: Only patch files in ./build directory.' - echo echo ' --recheck: run analysis on a prepared target directory.' echo echo ' target-directory: Directory where build should occur.' @@ -354,6 +357,7 @@ main() { patch store_const \ only-build 'store_const --only-build' \ recheck store_const \ + pvs-install store_const \ -- \ 'store tgt "$PWD/../neovim-pvs"' \ 'store branch master' \ @@ -369,13 +373,12 @@ main() { if test -n "$patch" ; then patch_sources "$only_build" "$tgt" - return $? - fi - - if test -z "$recheck" ; then - do_check "$tgt" "$branch" "$pvs_url" - else + elif test -n "$pvs_install" ; then + install_pvs "$tgt" "$pvs_url" + elif test -n "$recheck" ; then do_recheck "$tgt" + else + do_check "$tgt" "$branch" "$pvs_url" fi } -- cgit From 3638d28f68969c81242b8d7345f1d0348fce497d Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 2 May 2017 18:24:29 +0300 Subject: pvscheck: Add --deps to build with all dependencies [ci skip] --- scripts/pvscheck.sh | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index 39de763fe2..da55965d36 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -13,7 +13,7 @@ get_jobs_num() { help() { echo 'Usage:' - echo ' pvscheck.sh [--pvs URL] [target-directory [branch]]' + echo ' pvscheck.sh [--pvs URL] [--deps] [target-directory [branch]]' echo ' pvscheck.sh [--pvs URL] [--recheck] [target-directory]' echo ' pvscheck.sh [--pvs URL] --pvs-install {target-directory}' echo ' pvscheck.sh --patch [--only-build]' @@ -25,6 +25,10 @@ help() { echo ' That assumes certain viva64.com site properties and' echo ' may be broken by the site update.' echo + echo ' --deps: (for regular run) Use top-level Makefile and build deps.' + echo ' Without this it assumes all dependencies are already' + echo ' installed.' + echo echo ' --only-build: (for --patch) Only patch files in ./build directory.' echo echo ' --pvs-install: Only install PVS-studio to the specified location.' @@ -252,15 +256,22 @@ adjust_path() { create_compile_commands() {( local tgt="$1" ; shift + local deps="$1" ; shift export CC=clang export CFLAGS=' -O0 ' - mkdir "$tgt/build" - cd "$tgt/build" + if test -z "$deps" ; then + mkdir "$tgt/build" + cd "$tgt/build" + + cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="$PWD/root" + make -j"$(get_jobs_num)" + else + cd "$tgt" - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="$PWD/root" - make -j"$(get_jobs_num)" + make -j"$(get_jobs_num)" CMAKE_EXTRA_FLAGS=" -DCMAKE_INSTALL_PREFIX=$PWD/root -DCMAKE_BUILD_TYPE=Debug " + fi find src/nvim/auto -name '*.test-include.c' -delete )} @@ -318,6 +329,7 @@ do_check() { local tgt="$1" ; shift local branch="$1" ; shift local pvs_url="$1" ; shift + local deps="$1" ; shift git clone --branch="$branch" . "$tgt" @@ -325,7 +337,7 @@ do_check() { adjust_path "$tgt" - create_compile_commands "$tgt" + create_compile_commands "$tgt" "$deps" run_analysis "$tgt" } @@ -358,6 +370,7 @@ main() { only-build 'store_const --only-build' \ recheck store_const \ pvs-install store_const \ + deps store_const \ -- \ 'store tgt "$PWD/../neovim-pvs"' \ 'store branch master' \ @@ -378,7 +391,7 @@ main() { elif test -n "$recheck" ; then do_recheck "$tgt" else - do_check "$tgt" "$branch" "$pvs_url" + do_check "$tgt" "$branch" "$pvs_url" "$deps" fi } -- cgit From 0c6e0460b6f15dce8dd5f517712093d843d76058 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 2 May 2017 18:33:41 +0300 Subject: pvscheck: When using --recheck rerun build [ci skip] --- scripts/pvscheck.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index da55965d36..67834cca8a 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -262,7 +262,7 @@ create_compile_commands() {( export CFLAGS=' -O0 ' if test -z "$deps" ; then - mkdir "$tgt/build" + mkdir -p "$tgt/build" cd "$tgt/build" cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="$PWD/root" @@ -347,6 +347,8 @@ do_recheck() { adjust_path "$tgt" + create_compile_commands "$tgt" "$deps" + run_analysis "$tgt" } -- cgit From 4f4d21693bb1665f1a398fb58dc2c554ba7b4eba Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 2 May 2017 21:53:16 +0300 Subject: pvscheck: Use absolute path for finding test-include.c It was currently unknown in which directory create_compile_commands will end up in. [ci skip] --- scripts/pvscheck.sh | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index 67834cca8a..c75dd2ab76 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -263,16 +263,29 @@ create_compile_commands() {( if test -z "$deps" ; then mkdir -p "$tgt/build" - cd "$tgt/build" + ( + cd "$tgt/build" - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="$PWD/root" - make -j"$(get_jobs_num)" + cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="$PWD/root" + make -j"$(get_jobs_num)" + ) else - cd "$tgt" + ( + cd "$tgt" - make -j"$(get_jobs_num)" CMAKE_EXTRA_FLAGS=" -DCMAKE_INSTALL_PREFIX=$PWD/root -DCMAKE_BUILD_TYPE=Debug " + make -j"$(get_jobs_num)" CMAKE_EXTRA_FLAGS=" -DCMAKE_INSTALL_PREFIX=$PWD/root -DCMAKE_BUILD_TYPE=Debug " + ) fi - find src/nvim/auto -name '*.test-include.c' -delete + find "$tgt/build/src/nvim/auto" -name '*.test-include.c' -delete +)} + +# Warning: realdir below only cares about directories unlike realpath. +# +# realpath is not available in Ubuntu trusty yet. +realdir() {( + local dir="$1" + cd "$dir" + printf '%s\n' "$PWD" )} patch_sources() {( @@ -374,7 +387,7 @@ main() { pvs-install store_const \ deps store_const \ -- \ - 'store tgt "$PWD/../neovim-pvs"' \ + 'modify realdir tgt "$PWD/../neovim-pvs"' \ 'store branch master' \ -- "$@" )" -- cgit From 3c0cc028b7e787e3e87f21976d8b6333bf488219 Mon Sep 17 00:00:00 2001 From: AdnoC Date: Mon, 1 May 2017 20:35:04 -0400 Subject: dist: AppImage #6638 scripts/genappimage.sh produces an executable: nvim-${NVIM_VERSION}-glibc${GLIBC_VERSION}-${ARCHITECTURE}.AppImage Closes #6083 --- scripts/genappimage.sh | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100755 scripts/genappimage.sh (limited to 'scripts') diff --git a/scripts/genappimage.sh b/scripts/genappimage.sh new file mode 100755 index 0000000000..fd7247b947 --- /dev/null +++ b/scripts/genappimage.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +######################################################################## +# Package the binaries built as an AppImage +# By Simon Peter 2016 +# For more information, see http://appimage.org/ +######################################################################## + +# App arch, used by generate_appimage. +if [ -z "$ARCH" ]; then + export ARCH="$(arch)" +fi + +# App name, used by generate_appimage. +APP=nvim + +ROOT_DIR="$(git rev-parse --show-toplevel)" +APP_BUILD_DIR="$ROOT_DIR/build" +APP_DIR="$APP.AppDir" + +# App version, used by generate_appimage. +VERSION=$("$ROOT_DIR"/build/bin/nvim --version | head -n 1 | grep -o 'v.*') + +######################################################################## +# Compile nvim and install it into AppDir +######################################################################## + +# Build and install nvim into the AppImage +make CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX=${APP_DIR}/usr" +make install + +######################################################################## +# Get helper functions and move to AppDir +######################################################################## + +cd "$APP_BUILD_DIR" +mkdir "$APP_DIR" + +curl -Lo "$APP_BUILD_DIR"/appimage_functions.sh https://github.com/probonopd/AppImages/raw/master/functions.sh +. ./appimage_functions.sh + +# Copy desktop and icon file to AppDir for AppRun to pick them up. +# get_apprun +# get_desktop +cp "$ROOT_DIR/runtime/nvim.desktop" "$APP_DIR/" +cp "$ROOT_DIR/runtime/nvim.png" "$APP_DIR/" + +cd "$APP_DIR" + +# copy dependencies +copy_deps +# Move the libraries to usr/bin +move_lib + +# Delete stuff that should not go into the AppImage. +# Delete dangerous libraries; see +# https://github.com/probonopd/AppImages/blob/master/excludelist +delete_blacklisted + +######################################################################## +# AppDir complete. Now package it as an AppImage. +######################################################################## + +# No need for a fancy script. AppRun can just be a symlink to nvim. +ln -s usr/bin/nvim AppRun + +cd "$APP_BUILD_DIR" # Get out of AppImage directory. + +# Generate AppImage. +# - Expects: $ARCH, $APP, $VERSION env vars +# - Expects: ./$APP.AppDir/ directory +# - Produces: ../out/$APP-$VERSION.glibc$GLIBC_NEEDED-$ARCH.AppImage +generate_appimage + +# NOTE: There is currently a bug in the `generate_appimage` function (see +# https://github.com/probonopd/AppImages/issues/228) that causes repeated builds +# that result in the same name to fail. +# Moving the final executable to a different folder gets around this issue. + +mv "$ROOT_DIR"/out/*.AppImage "$ROOT_DIR"/build/bin +# Remove the (now empty) folder the AppImage was built in +rmdir "$ROOT_DIR"/out -- cgit From 577befef9729ba711eece923a495fff51f73d324 Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 8 May 2017 20:54:09 +0300 Subject: generators: Do not leak error messages text --- scripts/genmsgpack.lua | 51 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) (limited to 'scripts') diff --git a/scripts/genmsgpack.lua b/scripts/genmsgpack.lua index fff5f9c7ed..86a051fb4c 100644 --- a/scripts/genmsgpack.lua +++ b/scripts/genmsgpack.lua @@ -401,7 +401,7 @@ local function process_function(fn) Error err = ERROR_INIT; if (lua_gettop(lstate) != %i) { api_set_error(&err, kErrorTypeValidation, "Expected %i argument%s"); - return luaL_error(lstate, "%%s", err.msg); + goto exit_0; } ]], lua_c_function_name, #fn.parameters, #fn.parameters, (#fn.parameters == 1) and '' or 's')) @@ -420,11 +420,11 @@ local function process_function(fn) const %s %s = nlua_pop_%s(lstate, &err); if (ERROR_SET(&err)) { - %s - return luaL_error(lstate, "%%s", err.msg); + goto exit_%u; } - ]], param[1], cparam, param_type, table.concat(free_code, '\n '))) - free_code[#free_code + 1] = ('api_free_%s(%s);'):format(lc_param_type, cparam) + ]], param[1], cparam, param_type, #fn.parameters - j)) + free_code[#free_code + 1] = ('api_free_%s(%s);'):format( + lc_param_type, cparam) cparams = cparam .. ', ' .. cparams end if fn.receives_channel_id then @@ -435,7 +435,28 @@ local function process_function(fn) else cparams = cparams:gsub(', $', '') end - free_at_exit_code = table.concat(free_code, '\n ') + local free_at_exit_code = '' + for i = 1, #free_code do + local rev_i = #free_code - i + 1 + local code = free_code[rev_i] + if i == 1 then + free_at_exit_code = free_at_exit_code .. ('\n %s'):format(code) + else + free_at_exit_code = free_at_exit_code .. ('\n exit_%u:\n %s'):format( + rev_i, code) + end + end + local err_throw_code = [[ + + exit_0: + if (ERROR_SET(&err)) { + luaL_where(lstate, 1); + lua_pushstring(lstate, err.msg); + api_clear_error(&err); + lua_concat(lstate, 2); + return lua_error(lstate); + } + ]] if fn.return_type ~= 'void' then if fn.return_type:match('^ArrayOf') then return_type = 'Array' @@ -444,24 +465,20 @@ local function process_function(fn) end write_shifted_output(output, string.format([[ const %s ret = %s(%s); - %s - if (ERROR_SET(&err)) { - return luaL_error(lstate, "%%s", err.msg); - } nlua_push_%s(lstate, ret); api_free_%s(ret); + %s + %s return 1; - ]], fn.return_type, fn.name, cparams, free_at_exit_code, return_type, - return_type:lower())) + ]], fn.return_type, fn.name, cparams, return_type, return_type:lower(), + free_at_exit_code, err_throw_code)) else write_shifted_output(output, string.format([[ %s(%s); - %s - if (ERROR_SET(&err)) { - return luaL_error(lstate, "%%s", err.msg); - } + %s + %s return 0; - ]], fn.name, cparams, free_at_exit_code)) + ]], fn.name, cparams, free_at_exit_code, err_throw_code)) end write_shifted_output(output, [[ } -- cgit From 489d10c57c68183c042fd582e6c8eadbb0efc5a7 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 29 Apr 2017 13:06:14 +0200 Subject: api: generate ui events --- scripts/gen_ui_events.lua | 183 ++++++++++++++++++++++++++++++++++++++++++++++ scripts/genmsgpack.lua | 1 + 2 files changed, 184 insertions(+) create mode 100644 scripts/gen_ui_events.lua (limited to 'scripts') diff --git a/scripts/gen_ui_events.lua b/scripts/gen_ui_events.lua new file mode 100644 index 0000000000..ab5a8655fe --- /dev/null +++ b/scripts/gen_ui_events.lua @@ -0,0 +1,183 @@ +lpeg = require('lpeg') +mpack = require('mpack') + +-- TODO: reduce copying +-- lpeg grammar for building api metadata from a set of header files. It +-- ignores comments and preprocessor commands and parses a very small subset +-- of C prototypes with a limited set of types +P, R, S = lpeg.P, lpeg.R, lpeg.S +C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg + +any = P(1) -- (consume one character) +letter = R('az', 'AZ') + S('_$') +num = R('09') +alpha = letter + num +nl = P('\r\n') + P('\n') +not_nl = any - nl +ws = S(' \t') + nl +fill = ws ^ 0 +c_comment = P('//') * (not_nl ^ 0) +c_preproc = P('#') * (not_nl ^ 0) +typed_container = + (P('ArrayOf(') + P('DictionaryOf(')) * ((any - P(')')) ^ 1) * P(')') +c_id = ( + typed_container + + (letter * (alpha ^ 0)) +) +c_void = P('void') +c_param_type = ( + ((P('Error') * fill * P('*') * fill) * Cc('error')) + + (C(c_id) * (ws ^ 1)) + ) +c_type = (C(c_void) * (ws ^ 1)) + c_param_type +c_param = Ct(c_param_type * C(c_id)) +c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0) +c_params = Ct(c_void + c_param_list) +c_proto = Ct( + Cg(c_type, 'return_type') * Cg(c_id, 'name') * + fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * + Cg(Cc(false), 'async') * + (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) * + (fill * Cg((P('REMOTE_ONLY') * Cc(true)), 'remote_only') ^ -1) * + (fill * Cg((P('REMOTE_IMPL') * Cc(true)), 'remote_impl') ^ -1) * + (fill * Cg((P('BRIDGE_IMPL') * Cc(true)), 'bridge_impl') ^ -1) * + fill * P(';') + ) +grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) + + +-- we need at least 4 arguments since the last two are output files +assert(#arg == 6) +input = io.open(arg[2], 'rb') +proto_output = io.open(arg[3], 'wb') +call_output = io.open(arg[4], 'wb') +remote_output = io.open(arg[5], 'wb') +bridge_output = io.open(arg[6], 'wb') + +functions = {} + +local events = grammar:match(input:read('*all')) + +function write_signature(output, ev, prefix, notype) + output:write('('..prefix) + if prefix == "" and #ev.parameters == 0 then + output:write('void') + end + for j = 1, #ev.parameters do + if j > 1 or prefix ~= '' then + output:write(', ') + end + local param = ev.parameters[j] + if not notype then + output:write(param[1]..' ') + end + output:write(param[2]) + end + output:write(')') +end + +function write_arglist(output, ev, need_copy) + output:write(' Array args = ARRAY_DICT_INIT;\n') + for j = 1, #ev.parameters do + local param = ev.parameters[j] + local kind = string.upper(param[1]) + local do_copy = need_copy and (kind == "ARRAY" or kind == "DICTIONARY" or kind == "STRING") + output:write(' ADD(args, ') + if do_copy then + output:write('copy_object(') + end + output:write(kind..'_OBJ('..param[2]..')') + if do_copy then + output:write(')') + end + output:write(');\n') + end +end + +for i = 1, #events do + ev = events[i] + assert(ev.return_type == 'void') + + if not ev.remote_only then + proto_output:write(' void (*'..ev.name..')') + write_signature(proto_output, ev, 'UI *ui') + proto_output:write(';\n') + + if not ev.remote_impl then + remote_output:write('static void remote_ui_'..ev.name) + write_signature(remote_output, ev, 'UI *ui') + remote_output:write('\n{\n') + write_arglist(remote_output, ev, true) + remote_output:write(' push_call(ui, "'..ev.name..'", args);\n') + remote_output:write('}\n\n') + end + + if not ev.bridge_impl then + + send, argv, recv, recv_argv, recv_cleanup = '', '', '', '', '' + argc = 1 + for j = 1, #ev.parameters do + local param = ev.parameters[j] + copy = 'copy_'..param[2] + if param[1] == 'String' then + send = send..' String copy_'..param[2]..' = copy_string('..param[2]..');\n' + argv = argv..', '..copy..'.data, INT2PTR('..copy..'.size)' + recv = (recv..' String '..param[2].. + ' = (String){.data = argv['..argc..'],'.. + '.size = (size_t)argv['..(argc+1)..']};\n') + recv_argv = recv_argv..', '..param[2] + recv_cleanup = recv_cleanup..' api_free_string('..param[2]..');\n' + argc = argc+2 + elseif param[1] == 'Array' then + send = send..' Array copy_'..param[2]..' = copy_array('..param[2]..');\n' + argv = argv..', '..copy..'.items, INT2PTR('..copy..'.size)' + recv = (recv..' Array '..param[2].. + ' = (Array){.items = argv['..argc..'],'.. + '.size = (size_t)argv['..(argc+1)..']};\n') + recv_argv = recv_argv..', '..param[2] + recv_cleanup = recv_cleanup..' api_free_array('..param[2]..');\n' + argc = argc+2 + elseif param[1] == 'Integer' or param[1] == 'Boolean' then + argv = argv..', INT2PTR('..param[2]..')' + recv_argv = recv_argv..', PTR2INT(argv['..argc..'])' + argc = argc+1 + else + assert(false) + end + end + bridge_output:write('static void ui_bridge_'..ev.name.. + '_event(void **argv)\n{\n') + bridge_output:write(' UI *ui = UI(argv[0]);\n') + bridge_output:write(recv) + bridge_output:write(' ui->'..ev.name..'(ui'..recv_argv..');\n') + bridge_output:write(recv_cleanup) + bridge_output:write('}\n\n') + + bridge_output:write('static void ui_bridge_'..ev.name) + write_signature(bridge_output, ev, 'UI *ui') + bridge_output:write('\n{\n') + bridge_output:write(send) + bridge_output:write(' UI_CALL(ui, '..ev.name..', '..argc..', ui'..argv..');\n}\n') + end + end + + call_output:write('void ui_call_'..ev.name) + write_signature(call_output, ev, '') + call_output:write('\n{\n') + if ev.remote_only then + write_arglist(call_output, ev, false) + call_output:write(' ui_event("'..ev.name..'", args);\n') + else + call_output:write(' UI_CALL') + write_signature(call_output, ev, ev.name, true) + call_output:write(";\n") + end + call_output:write("}\n\n") + +end + + + +proto_output:close() +call_output:close() +remote_output:close() diff --git a/scripts/genmsgpack.lua b/scripts/genmsgpack.lua index 86a051fb4c..c16a844586 100644 --- a/scripts/genmsgpack.lua +++ b/scripts/genmsgpack.lua @@ -87,6 +87,7 @@ for i = 6, #arg do headers[#headers + 1] = parts[#parts - 1]..'/'..parts[#parts] local input = io.open(full_path, 'rb') + local tmp = grammar:match(input:read('*all')) for i = 1, #tmp do local fn = tmp[i] -- cgit From c778311505fe89e3f32ff3027f0a41f0a2b2fd95 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 30 Apr 2017 13:08:39 +0200 Subject: generators: separate source generators from scripts --- scripts/gen_events.lua | 65 ------ scripts/gen_ui_events.lua | 183 --------------- scripts/gencharblob.lua | 48 ---- scripts/gendeclarations.lua | 287 ------------------------ scripts/geneval.lua | 67 ------ scripts/genex_cmds.lua | 88 -------- scripts/genmsgpack.lua | 513 ------------------------------------------- scripts/genoptions.lua | 190 ---------------- scripts/genunicodetables.lua | 327 --------------------------- 9 files changed, 1768 deletions(-) delete mode 100644 scripts/gen_events.lua delete mode 100644 scripts/gen_ui_events.lua delete mode 100644 scripts/gencharblob.lua delete mode 100755 scripts/gendeclarations.lua delete mode 100644 scripts/geneval.lua delete mode 100644 scripts/genex_cmds.lua delete mode 100644 scripts/genmsgpack.lua delete mode 100644 scripts/genoptions.lua delete mode 100644 scripts/genunicodetables.lua (limited to 'scripts') diff --git a/scripts/gen_events.lua b/scripts/gen_events.lua deleted file mode 100644 index 75e0b3da3a..0000000000 --- a/scripts/gen_events.lua +++ /dev/null @@ -1,65 +0,0 @@ -if arg[1] == '--help' then - print('Usage: gen_events.lua src/nvim enum_file event_names_file') - os.exit(0) -end - -local nvimsrcdir = arg[1] -local fileio_enum_file = arg[2] -local names_file = arg[3] - -package.path = nvimsrcdir .. '/?.lua;' .. package.path - -local auevents = require('auevents') -local events = auevents.events -local aliases = auevents.aliases - -enum_tgt = io.open(fileio_enum_file, 'w') -names_tgt = io.open(names_file, 'w') - -enum_tgt:write('typedef enum auto_event {') -names_tgt:write([[ -static const struct event_name { - size_t len; - char *name; - event_T event; -} event_names[] = {]]) - -for i, event in ipairs(events) do - if i > 1 then - comma = ',\n' - else - comma = '\n' - end - enum_tgt:write(('%s EVENT_%s = %u'):format(comma, event:upper(), i - 1)) - names_tgt:write(('%s {%u, "%s", EVENT_%s}'):format(comma, #event, event, event:upper())) -end - -for alias, event in pairs(aliases) do - names_tgt:write((',\n {%u, "%s", EVENT_%s}'):format(#alias, alias, event:upper())) -end - -names_tgt:write(',\n {0, NULL, (event_T)0}') - -enum_tgt:write('\n} event_T;\n') -names_tgt:write('\n};\n') - -enum_tgt:write(('\n#define NUM_EVENTS %u\n'):format(#events)) -names_tgt:write('\nstatic AutoPat *first_autopat[NUM_EVENTS] = {\n ') -line_len = 1 -for i = 1,((#events) - 1) do - line_len = line_len + #(' NULL,') - if line_len > 80 then - names_tgt:write('\n ') - line_len = 1 + #(' NULL,') - end - names_tgt:write(' NULL,') -end -if line_len + #(' NULL') > 80 then - names_tgt:write('\n NULL') -else - names_tgt:write(' NULL') -end -names_tgt:write('\n};\n') - -enum_tgt:close() -names_tgt:close() diff --git a/scripts/gen_ui_events.lua b/scripts/gen_ui_events.lua deleted file mode 100644 index ab5a8655fe..0000000000 --- a/scripts/gen_ui_events.lua +++ /dev/null @@ -1,183 +0,0 @@ -lpeg = require('lpeg') -mpack = require('mpack') - --- TODO: reduce copying --- lpeg grammar for building api metadata from a set of header files. It --- ignores comments and preprocessor commands and parses a very small subset --- of C prototypes with a limited set of types -P, R, S = lpeg.P, lpeg.R, lpeg.S -C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg - -any = P(1) -- (consume one character) -letter = R('az', 'AZ') + S('_$') -num = R('09') -alpha = letter + num -nl = P('\r\n') + P('\n') -not_nl = any - nl -ws = S(' \t') + nl -fill = ws ^ 0 -c_comment = P('//') * (not_nl ^ 0) -c_preproc = P('#') * (not_nl ^ 0) -typed_container = - (P('ArrayOf(') + P('DictionaryOf(')) * ((any - P(')')) ^ 1) * P(')') -c_id = ( - typed_container + - (letter * (alpha ^ 0)) -) -c_void = P('void') -c_param_type = ( - ((P('Error') * fill * P('*') * fill) * Cc('error')) + - (C(c_id) * (ws ^ 1)) - ) -c_type = (C(c_void) * (ws ^ 1)) + c_param_type -c_param = Ct(c_param_type * C(c_id)) -c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0) -c_params = Ct(c_void + c_param_list) -c_proto = Ct( - Cg(c_type, 'return_type') * Cg(c_id, 'name') * - fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * - Cg(Cc(false), 'async') * - (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) * - (fill * Cg((P('REMOTE_ONLY') * Cc(true)), 'remote_only') ^ -1) * - (fill * Cg((P('REMOTE_IMPL') * Cc(true)), 'remote_impl') ^ -1) * - (fill * Cg((P('BRIDGE_IMPL') * Cc(true)), 'bridge_impl') ^ -1) * - fill * P(';') - ) -grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) - - --- we need at least 4 arguments since the last two are output files -assert(#arg == 6) -input = io.open(arg[2], 'rb') -proto_output = io.open(arg[3], 'wb') -call_output = io.open(arg[4], 'wb') -remote_output = io.open(arg[5], 'wb') -bridge_output = io.open(arg[6], 'wb') - -functions = {} - -local events = grammar:match(input:read('*all')) - -function write_signature(output, ev, prefix, notype) - output:write('('..prefix) - if prefix == "" and #ev.parameters == 0 then - output:write('void') - end - for j = 1, #ev.parameters do - if j > 1 or prefix ~= '' then - output:write(', ') - end - local param = ev.parameters[j] - if not notype then - output:write(param[1]..' ') - end - output:write(param[2]) - end - output:write(')') -end - -function write_arglist(output, ev, need_copy) - output:write(' Array args = ARRAY_DICT_INIT;\n') - for j = 1, #ev.parameters do - local param = ev.parameters[j] - local kind = string.upper(param[1]) - local do_copy = need_copy and (kind == "ARRAY" or kind == "DICTIONARY" or kind == "STRING") - output:write(' ADD(args, ') - if do_copy then - output:write('copy_object(') - end - output:write(kind..'_OBJ('..param[2]..')') - if do_copy then - output:write(')') - end - output:write(');\n') - end -end - -for i = 1, #events do - ev = events[i] - assert(ev.return_type == 'void') - - if not ev.remote_only then - proto_output:write(' void (*'..ev.name..')') - write_signature(proto_output, ev, 'UI *ui') - proto_output:write(';\n') - - if not ev.remote_impl then - remote_output:write('static void remote_ui_'..ev.name) - write_signature(remote_output, ev, 'UI *ui') - remote_output:write('\n{\n') - write_arglist(remote_output, ev, true) - remote_output:write(' push_call(ui, "'..ev.name..'", args);\n') - remote_output:write('}\n\n') - end - - if not ev.bridge_impl then - - send, argv, recv, recv_argv, recv_cleanup = '', '', '', '', '' - argc = 1 - for j = 1, #ev.parameters do - local param = ev.parameters[j] - copy = 'copy_'..param[2] - if param[1] == 'String' then - send = send..' String copy_'..param[2]..' = copy_string('..param[2]..');\n' - argv = argv..', '..copy..'.data, INT2PTR('..copy..'.size)' - recv = (recv..' String '..param[2].. - ' = (String){.data = argv['..argc..'],'.. - '.size = (size_t)argv['..(argc+1)..']};\n') - recv_argv = recv_argv..', '..param[2] - recv_cleanup = recv_cleanup..' api_free_string('..param[2]..');\n' - argc = argc+2 - elseif param[1] == 'Array' then - send = send..' Array copy_'..param[2]..' = copy_array('..param[2]..');\n' - argv = argv..', '..copy..'.items, INT2PTR('..copy..'.size)' - recv = (recv..' Array '..param[2].. - ' = (Array){.items = argv['..argc..'],'.. - '.size = (size_t)argv['..(argc+1)..']};\n') - recv_argv = recv_argv..', '..param[2] - recv_cleanup = recv_cleanup..' api_free_array('..param[2]..');\n' - argc = argc+2 - elseif param[1] == 'Integer' or param[1] == 'Boolean' then - argv = argv..', INT2PTR('..param[2]..')' - recv_argv = recv_argv..', PTR2INT(argv['..argc..'])' - argc = argc+1 - else - assert(false) - end - end - bridge_output:write('static void ui_bridge_'..ev.name.. - '_event(void **argv)\n{\n') - bridge_output:write(' UI *ui = UI(argv[0]);\n') - bridge_output:write(recv) - bridge_output:write(' ui->'..ev.name..'(ui'..recv_argv..');\n') - bridge_output:write(recv_cleanup) - bridge_output:write('}\n\n') - - bridge_output:write('static void ui_bridge_'..ev.name) - write_signature(bridge_output, ev, 'UI *ui') - bridge_output:write('\n{\n') - bridge_output:write(send) - bridge_output:write(' UI_CALL(ui, '..ev.name..', '..argc..', ui'..argv..');\n}\n') - end - end - - call_output:write('void ui_call_'..ev.name) - write_signature(call_output, ev, '') - call_output:write('\n{\n') - if ev.remote_only then - write_arglist(call_output, ev, false) - call_output:write(' ui_event("'..ev.name..'", args);\n') - else - call_output:write(' UI_CALL') - write_signature(call_output, ev, ev.name, true) - call_output:write(";\n") - end - call_output:write("}\n\n") - -end - - - -proto_output:close() -call_output:close() -remote_output:close() diff --git a/scripts/gencharblob.lua b/scripts/gencharblob.lua deleted file mode 100644 index d860375e26..0000000000 --- a/scripts/gencharblob.lua +++ /dev/null @@ -1,48 +0,0 @@ -if arg[1] == '--help' then - print('Usage:') - print(' gencharblob.lua source target varname') - print('') - print('Generates C file with big uint8_t blob.') - print('Blob will be stored in a static const array named varname.') - os.exit() -end - -assert(#arg == 3) - -local source_file = arg[1] -local target_file = arg[2] -local varname = arg[3] - -source = io.open(source_file, 'r') -target = io.open(target_file, 'w') - -target:write('#include \n\n') -target:write(('static const uint8_t %s[] = {\n'):format(varname)) - -num_bytes = 0 -MAX_NUM_BYTES = 15 -- 78 / 5: maximum number of bytes on one line -target:write(' ') - -increase_num_bytes = function() - num_bytes = num_bytes + 1 - if num_bytes == MAX_NUM_BYTES then - num_bytes = 0 - target:write('\n ') - end -end - -for line in source:lines() do - for i = 1,string.len(line) do - byte = string.byte(line, i) - assert(byte ~= 0) - target:write(string.format(' %3u,', byte)) - increase_num_bytes() - end - target:write(string.format(' %3u,', string.byte('\n', 1))) - increase_num_bytes() -end - -target:write(' 0};\n') - -source:close() -target:close() diff --git a/scripts/gendeclarations.lua b/scripts/gendeclarations.lua deleted file mode 100755 index e999e53e4a..0000000000 --- a/scripts/gendeclarations.lua +++ /dev/null @@ -1,287 +0,0 @@ -#!/usr/bin/lua - -local fname = arg[1] -local static_fname = arg[2] -local non_static_fname = arg[3] -local preproc_fname = arg[4] - - -local lpeg = require('lpeg') - -local fold = function (func, ...) - local result = nil - for i, v in ipairs({...}) do - if result == nil then - result = v - else - result = func(result, v) - end - end - return result -end - -local folder = function (func) - return function (...) - return fold(func, ...) - end -end - -local lit = lpeg.P -local set = function(...) - return lpeg.S(fold(function (a, b) return a .. b end, ...)) -end -local any_character = lpeg.P(1) -local rng = function(s, e) return lpeg.R(s .. e) end -local concat = folder(function (a, b) return a * b end) -local branch = folder(function (a, b) return a + b end) -local one_or_more = function(v) return v ^ 1 end -local two_or_more = function(v) return v ^ 2 end -local any_amount = function(v) return v ^ 0 end -local one_or_no = function(v) return v ^ -1 end -local look_behind = lpeg.B -local look_ahead = function(v) return #v end -local neg_look_ahead = function(v) return -v end -local neg_look_behind = function(v) return -look_behind(v) end - -local w = branch( - rng('a', 'z'), - rng('A', 'Z'), - lit('_') -) -local aw = branch( - w, - rng('0', '9') -) -local s = set(' ', '\n', '\t') -local raw_word = concat(w, any_amount(aw)) -local right_word = concat( - raw_word, - neg_look_ahead(aw) -) -local word = branch( - concat( - branch(lit('ArrayOf('), lit('DictionaryOf(')), -- typed container macro - one_or_more(any_character - lit(')')), - lit(')') - ), - concat( - neg_look_behind(aw), - right_word - ) -) -local inline_comment = concat( - lit('/*'), - any_amount(concat( - neg_look_ahead(lit('*/')), - any_character - )), - lit('*/') -) -local spaces = any_amount(branch( - s, - -- Comments are really handled by preprocessor, so the following is not needed - inline_comment, - concat( - lit('//'), - any_amount(concat( - neg_look_ahead(lit('\n')), - any_character - )), - lit('\n') - ), - -- Linemarker inserted by preprocessor - concat( - lit('# '), - any_amount(concat( - neg_look_ahead(lit('\n')), - any_character - )), - lit('\n') - ) -)) -local typ_part = concat( - word, - any_amount(concat( - spaces, - lit('*') - )), - spaces -) -local typ = one_or_more(typ_part) -local typ_id = two_or_more(typ_part) -local arg = typ_id -- argument name is swallowed by typ -local pattern = concat( - any_amount(branch(set(' ', '\t'), inline_comment)), - typ_id, -- return type with function name - spaces, - lit('('), - spaces, - one_or_no(branch( -- function arguments - concat( - arg, -- first argument, does not require comma - any_amount(concat( -- following arguments, start with a comma - spaces, - lit(','), - spaces, - arg, - any_amount(concat( - lit('['), - spaces, - any_amount(aw), - spaces, - lit(']') - )) - )), - one_or_no(concat( - spaces, - lit(','), - spaces, - lit('...') - )) - ), - lit('void') -- also accepts just void - )), - spaces, - lit(')'), - any_amount(concat( -- optional attributes - spaces, - lit('FUNC_'), - any_amount(aw), - one_or_no(concat( -- attribute argument - spaces, - lit('('), - any_amount(concat( - neg_look_ahead(lit(')')), - any_character - )), - lit(')') - )) - )), - look_ahead(concat( -- definition must be followed by "{" - spaces, - lit('{') - )) -) - -if fname == '--help' then - print'Usage:' - print() - print' gendeclarations.lua definitions.c static.h non-static.h preprocessor.i' - os.exit() -end - -local preproc_f = io.open(preproc_fname) -local text = preproc_f:read("*all") -preproc_f:close() - - -local header = [[ -#ifndef DEFINE_FUNC_ATTRIBUTES -# define DEFINE_FUNC_ATTRIBUTES -#endif -#include "nvim/func_attr.h" -#undef DEFINE_FUNC_ATTRIBUTES -]] - -local footer = [[ -#include "nvim/func_attr.h" -]] - -local non_static = header -local static = header - -local filepattern = '^#%a* (%d+) "([^"]-)/?([^"/]+)"' -local curfile - -local init = 0 -local curfile = nil -local neededfile = fname:match('[^/]+$') -local declline = 0 -local declendpos = 0 -local curdir = nil -local is_needed_file = false -while init ~= nil do - init = text:find('[\n;}]', init) - if init == nil then - break - end - local init_is_nl = text:sub(init, init) == '\n' - init = init + 1 - if init_is_nl and is_needed_file then - declline = declline + 1 - end - if init_is_nl and text:sub(init, init) == '#' then - local line, dir, file = text:match(filepattern, init) - if file ~= nil then - curfile = file - is_needed_file = (curfile == neededfile) - declline = tonumber(line) - 1 - local curdir_start = dir:find('src/nvim/') - if curdir_start ~= nil then - curdir = dir:sub(curdir_start + #('src/nvim/')) - else - curdir = dir - end - else - declline = declline - 1 - end - elseif init < declendpos then - -- Skipping over declaration - elseif is_needed_file then - s = init - e = pattern:match(text, init) - if e ~= nil then - local declaration = text:sub(s, e - 1) - -- Comments are really handled by preprocessor, so the following is not - -- needed - declaration = declaration:gsub('/%*.-%*/', '') - declaration = declaration:gsub('//.-\n', '\n') - - declaration = declaration:gsub('# .-\n', '') - - declaration = declaration:gsub('\n', ' ') - declaration = declaration:gsub('%s+', ' ') - declaration = declaration:gsub(' ?%( ?', '(') - -- declaration = declaration:gsub(' ?%) ?', ')') - declaration = declaration:gsub(' ?, ?', ', ') - declaration = declaration:gsub(' ?(%*+) ?', ' %1') - declaration = declaration:gsub(' ?(FUNC_ATTR_)', ' %1') - declaration = declaration:gsub(' $', '') - declaration = declaration:gsub('^ ', '') - declaration = declaration .. ';' - declaration = declaration .. (' // %s/%s:%u'):format( - curdir, curfile, declline) - declaration = declaration .. '\n' - if declaration:sub(1, 6) == 'static' then - static = static .. declaration - else - non_static = non_static .. declaration - end - declendpos = e - end - end -end - -non_static = non_static .. footer -static = static .. footer - -local F -F = io.open(static_fname, 'w') -F:write(static) -F:close() - --- Before generating the non-static headers, check if the current file(if --- exists) is different from the new one. If they are the same, we won't touch --- the current version to avoid triggering an unnecessary rebuilds of modules --- that depend on this one -F = io.open(non_static_fname, 'r') -if F ~= nil then - if F:read('*a') == non_static then - os.exit(0) - end - io.close(F) -end - -F = io.open(non_static_fname, 'w') -F:write(non_static) -F:close() diff --git a/scripts/geneval.lua b/scripts/geneval.lua deleted file mode 100644 index b17ecb1a0c..0000000000 --- a/scripts/geneval.lua +++ /dev/null @@ -1,67 +0,0 @@ -mpack = require('mpack') - -local nvimsrcdir = arg[1] -local autodir = arg[2] -local metadata_file = arg[3] -local funcs_file = arg[4] - -if nvimsrcdir == '--help' then - print([[ -Usage: - lua geneval.lua src/nvim build/src/nvim/auto - -Will generate build/src/nvim/auto/funcs.generated.h with definition of functions -static const array. -]]) - os.exit(0) -end - -package.path = nvimsrcdir .. '/?.lua;' .. package.path - -local funcsfname = autodir .. '/funcs.generated.h' - -local gperfpipe = io.open(funcsfname .. '.gperf', 'wb') - -local funcs = require('eval').funcs -local metadata = mpack.unpack(io.open(arg[3], 'rb'):read("*all")) -for i,fun in ipairs(metadata) do - if not fun.noeval then - funcs[fun.name] = { - args=#fun.parameters, - func='api_wrapper', - data='&handle_'..fun.name, - } - end -end - -local funcsdata = io.open(funcs_file, 'w') -funcsdata:write(mpack.pack(funcs)) -funcsdata:close() - -gperfpipe:write([[ -%language=ANSI-C -%global-table -%readonly-tables -%define initializer-suffix ,0,0,NULL,NULL -%define word-array-name functions -%define hash-function-name hash_internal_func_gperf -%define lookup-function-name find_internal_func_gperf -%omit-struct-type -%struct-type -VimLFuncDef; -%% -]]) - -for name, def in pairs(funcs) do - args = def.args or 0 - if type(args) == 'number' then - args = {args, args} - elseif #args == 1 then - args[2] = 'MAX_FUNC_ARGS' - end - func = def.func or ('f_' .. name) - data = def.data or "NULL" - gperfpipe:write(('%s, %s, %s, &%s, (FunPtr)%s\n') - :format(name, args[1], args[2], func, data)) -end -gperfpipe:close() diff --git a/scripts/genex_cmds.lua b/scripts/genex_cmds.lua deleted file mode 100644 index cb566d46ca..0000000000 --- a/scripts/genex_cmds.lua +++ /dev/null @@ -1,88 +0,0 @@ -local nvimsrcdir = arg[1] -local includedir = arg[2] -local autodir = arg[3] - -if nvimsrcdir == '--help' then - print ([[ -Usage: - lua genex_cmds.lua src/nvim build/include build/src/nvim/auto - -Will generate files build/include/ex_cmds_enum.generated.h with cmdidx_T -enum and build/src/nvim/auto/ex_cmds_defs.generated.h with main Ex commands -definitions. -]]) - os.exit(0) -end - -package.path = nvimsrcdir .. '/?.lua;' .. package.path - -local enumfname = includedir .. '/ex_cmds_enum.generated.h' -local defsfname = autodir .. '/ex_cmds_defs.generated.h' - -local enumfile = io.open(enumfname, 'w') -local defsfile = io.open(defsfname, 'w') - -local defs = require('ex_cmds') -local lastchar = nil - -local i -local cmd -local first = true -local prevfirstchar = nil - -local byte_a = string.byte('a') -local byte_z = string.byte('z') - -local cmdidxs = string.format([[ -static const cmdidx_T cmdidxs[%u] = { -]], byte_z - byte_a + 2) - -enumfile:write([[ -typedef enum CMD_index { -]]) -defsfile:write(string.format([[ -static CommandDefinition cmdnames[%u] = { -]], #defs)) -for i, cmd in ipairs(defs) do - local enumname = cmd.enum or ('CMD_' .. cmd.command) - firstchar = string.byte(cmd.command) - if firstchar ~= prevfirstchar then - if (not prevfirstchar - or (byte_a <= firstchar and firstchar <= byte_z) - or (byte_a <= prevfirstchar and prevfirstchar <= byte_z)) then - if not first then - cmdidxs = cmdidxs .. ',\n' - end - cmdidxs = cmdidxs .. ' ' .. enumname - end - prevfirstchar = firstchar - end - if first then - first = false - else - defsfile:write(',\n') - end - enumfile:write(' ' .. enumname .. ',\n') - defsfile:write(string.format([[ - [%s] = { - .cmd_name = (char_u *) "%s", - .cmd_func = (ex_func_T)&%s, - .cmd_argt = %uL, - .cmd_addr_type = %i - }]], enumname, cmd.command, cmd.func, cmd.flags, cmd.addr_type)) -end -defsfile:write([[ - -}; -]]) -enumfile:write([[ - CMD_SIZE, - CMD_USER = -1, - CMD_USER_BUF = -2 -} cmdidx_T; -]]) -cmdidxs = cmdidxs .. [[ - -}; -]] -defsfile:write(cmdidxs) diff --git a/scripts/genmsgpack.lua b/scripts/genmsgpack.lua deleted file mode 100644 index c16a844586..0000000000 --- a/scripts/genmsgpack.lua +++ /dev/null @@ -1,513 +0,0 @@ -lpeg = require('lpeg') -mpack = require('mpack') - --- lpeg grammar for building api metadata from a set of header files. It --- ignores comments and preprocessor commands and parses a very small subset --- of C prototypes with a limited set of types -P, R, S = lpeg.P, lpeg.R, lpeg.S -C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg - -any = P(1) -- (consume one character) -letter = R('az', 'AZ') + S('_$') -num = R('09') -alpha = letter + num -nl = P('\r\n') + P('\n') -not_nl = any - nl -ws = S(' \t') + nl -fill = ws ^ 0 -c_comment = P('//') * (not_nl ^ 0) -c_preproc = P('#') * (not_nl ^ 0) -typed_container = - (P('ArrayOf(') + P('DictionaryOf(')) * ((any - P(')')) ^ 1) * P(')') -c_id = ( - typed_container + - (letter * (alpha ^ 0)) -) -c_void = P('void') -c_param_type = ( - ((P('Error') * fill * P('*') * fill) * Cc('error')) + - (C(c_id) * (ws ^ 1)) - ) -c_type = (C(c_void) * (ws ^ 1)) + c_param_type -c_param = Ct(c_param_type * C(c_id)) -c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0) -c_params = Ct(c_void + c_param_list) -c_proto = Ct( - Cg(c_type, 'return_type') * Cg(c_id, 'name') * - fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * - Cg(Cc(false), 'async') * - (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) * - (fill * Cg((P('FUNC_API_DEPRECATED_SINCE(') * C(num ^ 1)) * P(')'), - 'deprecated_since') ^ -1) * - (fill * Cg((P('FUNC_API_ASYNC') * Cc(true)), 'async') ^ -1) * - (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) * - (fill * Cg((P('FUNC_API_NOEVAL') * Cc(true)), 'noeval') ^ -1) * - fill * P(';') - ) -grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) - --- we need at least 4 arguments since the last two are output files -if arg[1] == '--help' then - print('Usage: genmsgpack.lua args') - print('Args: 1: source directory') - print(' 2: dispatch output file (dispatch_wrappers.generated.h)') - print(' 3: functions metadata output file (funcs_metadata.generated.h)') - print(' 4: API metadata output file (api_metadata.mpack)') - print(' 5: lua C bindings output file (msgpack_lua_c_bindings.generated.c)') - print(' rest: C files where API functions are defined') -end -assert(#arg >= 4) -functions = {} - -local nvimsrcdir = arg[1] -package.path = nvimsrcdir .. '/?.lua;' .. package.path - --- names of all headers relative to the source root (for inclusion in the --- generated file) -headers = {} - --- output h file with generated dispatch functions -dispatch_outputf = arg[2] --- output h file with packed metadata -funcs_metadata_outputf = arg[3] --- output metadata mpack file, for use by other build scripts -mpack_outputf = arg[4] -lua_c_bindings_outputf = arg[5] - --- set of function names, used to detect duplicates -function_names = {} - --- read each input file, parse and append to the api metadata -for i = 6, #arg do - local full_path = arg[i] - local parts = {} - for part in string.gmatch(full_path, '[^/]+') do - parts[#parts + 1] = part - end - headers[#headers + 1] = parts[#parts - 1]..'/'..parts[#parts] - - local input = io.open(full_path, 'rb') - - local tmp = grammar:match(input:read('*all')) - for i = 1, #tmp do - local fn = tmp[i] - if not fn.noexport then - functions[#functions + 1] = tmp[i] - function_names[fn.name] = true - if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then - -- this function should receive the channel id - fn.receives_channel_id = true - -- remove the parameter since it won't be passed by the api client - table.remove(fn.parameters, 1) - end - if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'error' then - -- function can fail if the last parameter type is 'Error' - fn.can_fail = true - -- remove the error parameter, msgpack has it's own special field - -- for specifying errors - fn.parameters[#fn.parameters] = nil - end - end - end - input:close() -end - -local function shallowcopy(orig) - local copy = {} - for orig_key, orig_value in pairs(orig) do - copy[orig_key] = orig_value - end - return copy -end - -local function startswith(String,Start) - return string.sub(String,1,string.len(Start))==Start -end - --- Export functions under older deprecated names. --- These will be removed eventually. -local deprecated_aliases = require("api.dispatch_deprecated") -for i,f in ipairs(shallowcopy(functions)) do - local ismethod = false - if startswith(f.name, "nvim_") then - if startswith(f.name, "nvim__") then - f.since = -1 - elseif f.since == nil then - print("Function "..f.name.." lacks since field.\n") - os.exit(1) - end - f.since = tonumber(f.since) - if f.deprecated_since ~= nil then - f.deprecated_since = tonumber(f.deprecated_since) - end - - if startswith(f.name, "nvim_buf_") then - ismethod = true - elseif startswith(f.name, "nvim_win_") then - ismethod = true - elseif startswith(f.name, "nvim_tabpage_") then - ismethod = true - end - else - f.noeval = true - f.since = 0 - f.deprecated_since = 1 - end - f.method = ismethod - local newname = deprecated_aliases[f.name] - if newname ~= nil then - if function_names[newname] then - -- duplicate - print("Function "..f.name.." has deprecated alias\n" - ..newname.." which has a separate implementation.\n".. - "Please remove it from src/nvim/api/dispatch_deprecated.lua") - os.exit(1) - end - local newf = shallowcopy(f) - newf.name = newname - if newname == "ui_try_resize" then - -- The return type was incorrectly set to Object in 0.1.5. - -- Keep it that way for clients that rely on this. - newf.return_type = "Object" - end - newf.impl_name = f.name - newf.noeval = true - newf.since = 0 - newf.deprecated_since = 1 - functions[#functions+1] = newf - end -end - --- don't expose internal attributes like "impl_name" in public metadata -exported_attributes = {'name', 'parameters', 'return_type', 'method', - 'since', 'deprecated_since'} -exported_functions = {} -for _,f in ipairs(functions) do - if not startswith(f.name, "nvim__") then - local f_exported = {} - for _,attr in ipairs(exported_attributes) do - f_exported[attr] = f[attr] - end - exported_functions[#exported_functions+1] = f_exported - end -end - - -funcs_metadata_output = io.open(funcs_metadata_outputf, 'wb') -funcs_metadata_output:write([[ -static const uint8_t funcs_metadata[] = { -]]) - --- serialize the API metadata using msgpack and embed into the resulting --- binary for easy querying by clients -packed_exported_functions = mpack.pack(exported_functions) -for i = 1, #packed_exported_functions do - funcs_metadata_output:write(string.byte(packed_exported_functions, i)..', ') - if i % 10 == 0 then - funcs_metadata_output:write('\n ') - end -end -funcs_metadata_output:write([[ -}; -]]) -funcs_metadata_output:close() - --- start building the dispatch wrapper output -output = io.open(dispatch_outputf, 'wb') - -local function real_type(type) - local rv = type - if typed_container:match(rv) then - if rv:match('Array') then - rv = 'Array' - else - rv = 'Dictionary' - end - end - return rv -end - -local function attr_name(rt) - if rt == 'Float' then - return 'floating' - else - return rt:lower() - end -end - --- start the handler functions. Visit each function metadata to build the --- handler function with code generated for validating arguments and calling to --- the real API. -for i = 1, #functions do - local fn = functions[i] - if fn.impl_name == nil then - local args = {} - - output:write('Object handle_'..fn.name..'(uint64_t channel_id, Array args, Error *error)') - output:write('\n{') - output:write('\n Object ret = NIL;') - -- Declare/initialize variables that will hold converted arguments - for j = 1, #fn.parameters do - local param = fn.parameters[j] - local converted = 'arg_'..j - output:write('\n '..param[1]..' '..converted..';') - end - output:write('\n') - output:write('\n if (args.size != '..#fn.parameters..') {') - output:write('\n api_set_error(error, kErrorTypeException, "Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);') - output:write('\n goto cleanup;') - output:write('\n }\n') - - -- Validation/conversion for each argument - for j = 1, #fn.parameters do - local converted, convert_arg, param, arg - param = fn.parameters[j] - converted = 'arg_'..j - local rt = real_type(param[1]) - if rt ~= 'Object' then - if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') then - -- Buffer, Window, and Tabpage have a specific type, but are stored in integer - output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..' && args.items['..(j - 1)..'].data.integer >= 0) {') - output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') - else - output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..') {') - output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..attr_name(rt)..';') - end - if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') or rt:match('^Boolean$') then - -- accept nonnegative integers for Booleans, Buffers, Windows and Tabpages - output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeInteger && args.items['..(j - 1)..'].data.integer >= 0) {') - output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') - end - output:write('\n } else {') - output:write('\n api_set_error(error, kErrorTypeException, "Wrong type for argument '..j..', expecting '..param[1]..'");') - output:write('\n goto cleanup;') - output:write('\n }\n') - else - output:write('\n '..converted..' = args.items['..(j - 1)..'];\n') - end - - args[#args + 1] = converted - end - - -- function call - local call_args = table.concat(args, ', ') - output:write('\n ') - if fn.return_type ~= 'void' then - -- has a return value, prefix the call with a declaration - output:write(fn.return_type..' rv = ') - end - - -- write the function name and the opening parenthesis - output:write(fn.name..'(') - - if fn.receives_channel_id then - -- if the function receives the channel id, pass it as first argument - if #args > 0 or fn.can_fail then - output:write('channel_id, '..call_args) - else - output:write('channel_id') - end - else - output:write(call_args) - end - - if fn.can_fail then - -- if the function can fail, also pass a pointer to the local error object - if #args > 0 then - output:write(', error);\n') - else - output:write('error);\n') - end - -- and check for the error - output:write('\n if (ERROR_SET(error)) {') - output:write('\n goto cleanup;') - output:write('\n }\n') - else - output:write(');\n') - end - - if fn.return_type ~= 'void' then - output:write('\n ret = '..string.upper(real_type(fn.return_type))..'_OBJ(rv);') - end - output:write('\n\ncleanup:'); - - output:write('\n return ret;\n}\n\n'); - end -end - --- Generate a function that initializes method names with handler functions -output:write([[ -void msgpack_rpc_init_method_table(void) -{ - methods = map_new(String, MsgpackRpcRequestHandler)(); - -]]) - -for i = 1, #functions do - local fn = functions[i] - output:write(' msgpack_rpc_add_method_handler('.. - '(String) {.data = "'..fn.name..'", '.. - '.size = sizeof("'..fn.name..'") - 1}, '.. - '(MsgpackRpcRequestHandler) {.fn = handle_'.. (fn.impl_name or fn.name).. - ', .async = '..tostring(fn.async)..'});\n') - -end - -output:write('\n}\n\n') -output:close() - -mpack_output = io.open(mpack_outputf, 'wb') -mpack_output:write(mpack.pack(functions)) -mpack_output:close() - -local function include_headers(output, headers) - for i = 1, #headers do - if headers[i]:sub(-12) ~= '.generated.h' then - output:write('\n#include "nvim/'..headers[i]..'"') - end - end -end - -local function write_shifted_output(output, str) - str = str:gsub('\n ', '\n') - str = str:gsub('^ ', '') - str = str:gsub(' +$', '') - output:write(str) -end - --- start building lua output -output = io.open(lua_c_bindings_outputf, 'wb') - -output:write([[ -#include -#include -#include - -#include "nvim/func_attr.h" -#include "nvim/api/private/defs.h" -#include "nvim/api/private/helpers.h" -#include "nvim/lua/converter.h" -]]) -include_headers(output, headers) -output:write('\n') - -lua_c_functions = {} - -local function process_function(fn) - lua_c_function_name = ('nlua_msgpack_%s'):format(fn.name) - write_shifted_output(output, string.format([[ - - static int %s(lua_State *lstate) - { - Error err = ERROR_INIT; - if (lua_gettop(lstate) != %i) { - api_set_error(&err, kErrorTypeValidation, "Expected %i argument%s"); - goto exit_0; - } - ]], lua_c_function_name, #fn.parameters, #fn.parameters, - (#fn.parameters == 1) and '' or 's')) - lua_c_functions[#lua_c_functions + 1] = { - binding=lua_c_function_name, - api=fn.name - } - local cparams = '' - local free_code = {} - for j = #fn.parameters,1,-1 do - param = fn.parameters[j] - cparam = string.format('arg%u', j) - param_type = real_type(param[1]) - lc_param_type = param_type:lower() - write_shifted_output(output, string.format([[ - const %s %s = nlua_pop_%s(lstate, &err); - - if (ERROR_SET(&err)) { - goto exit_%u; - } - ]], param[1], cparam, param_type, #fn.parameters - j)) - free_code[#free_code + 1] = ('api_free_%s(%s);'):format( - lc_param_type, cparam) - cparams = cparam .. ', ' .. cparams - end - if fn.receives_channel_id then - cparams = 'LUA_INTERNAL_CALL, ' .. cparams - end - if fn.can_fail then - cparams = cparams .. '&err' - else - cparams = cparams:gsub(', $', '') - end - local free_at_exit_code = '' - for i = 1, #free_code do - local rev_i = #free_code - i + 1 - local code = free_code[rev_i] - if i == 1 then - free_at_exit_code = free_at_exit_code .. ('\n %s'):format(code) - else - free_at_exit_code = free_at_exit_code .. ('\n exit_%u:\n %s'):format( - rev_i, code) - end - end - local err_throw_code = [[ - - exit_0: - if (ERROR_SET(&err)) { - luaL_where(lstate, 1); - lua_pushstring(lstate, err.msg); - api_clear_error(&err); - lua_concat(lstate, 2); - return lua_error(lstate); - } - ]] - if fn.return_type ~= 'void' then - if fn.return_type:match('^ArrayOf') then - return_type = 'Array' - else - return_type = fn.return_type - end - write_shifted_output(output, string.format([[ - const %s ret = %s(%s); - nlua_push_%s(lstate, ret); - api_free_%s(ret); - %s - %s - return 1; - ]], fn.return_type, fn.name, cparams, return_type, return_type:lower(), - free_at_exit_code, err_throw_code)) - else - write_shifted_output(output, string.format([[ - %s(%s); - %s - %s - return 0; - ]], fn.name, cparams, free_at_exit_code, err_throw_code)) - end - write_shifted_output(output, [[ - } - ]]) -end - -for _, fn in ipairs(functions) do - if not fn.noeval or fn.name:sub(1, 4) == '_vim' then - process_function(fn) - end -end - -output:write(string.format([[ -void nlua_add_api_functions(lua_State *lstate) - FUNC_ATTR_NONNULL_ALL -{ - lua_createtable(lstate, 0, %u); -]], #lua_c_functions)) -for _, func in ipairs(lua_c_functions) do - output:write(string.format([[ - - lua_pushcfunction(lstate, &%s); - lua_setfield(lstate, -2, "%s");]], func.binding, func.api)) -end -output:write([[ - - lua_setfield(lstate, -2, "api"); -} -]]) - -output:close() diff --git a/scripts/genoptions.lua b/scripts/genoptions.lua deleted file mode 100644 index 9d7f235a3b..0000000000 --- a/scripts/genoptions.lua +++ /dev/null @@ -1,190 +0,0 @@ -if arg[1] == '--help' then - print('Usage: genoptions.lua src/nvim options_file') - os.exit(0) -end - -local nvimsrcdir = arg[1] -local options_file = arg[2] - -package.path = nvimsrcdir .. '/?.lua;' .. package.path - -local opt_fd = io.open(options_file, 'w') - -local w = function(s) - if s:match('^ %.') then - opt_fd:write(s .. ',\n') - else - opt_fd:write(s .. '\n') - end -end - -local options = require('options') - -cstr = options.cstr - -local type_flags={ - bool='P_BOOL', - number='P_NUM', - string='P_STRING', -} - -local redraw_flags={ - statuslines='P_RSTAT', - current_window='P_RWIN', - current_window_only='P_RWINONLY', - current_buffer='P_RBUF', - all_windows='P_RALL', - everything='P_RCLR', - curswant='P_CURSWANT', -} - -local list_flags={ - comma='P_COMMA', - onecomma='P_ONECOMMA', - flags='P_FLAGLIST', - flagscomma='P_COMMA|P_FLAGLIST', -} - -local get_flags = function(o) - local ret = {type_flags[o.type]} - local add_flag = function(f) - ret[1] = ret[1] .. '|' .. f - end - if o.list then - add_flag(list_flags[o.list]) - end - if o.redraw then - for _, r_flag in ipairs(o.redraw) do - add_flag(redraw_flags[r_flag]) - end - end - if o.expand then - add_flag('P_EXPAND') - if o.expand == 'nodefault' then - add_flag('P_NO_DEF_EXP') - end - end - for _, flag_desc in ipairs({ - {'alloced'}, - {'nodefault'}, - {'no_mkrc'}, - {'vi_def'}, - {'vim'}, - {'secure'}, - {'gettext'}, - {'noglob'}, - {'normal_fname_chars', 'P_NFNAME'}, - {'pri_mkrc'}, - {'deny_in_modelines', 'P_NO_ML'}, - {'deny_duplicates', 'P_NODUP'}, - }) do - local key_name = flag_desc[1] - local def_name = flag_desc[2] or ('P_' .. key_name:upper()) - if o[key_name] then - add_flag(def_name) - end - end - return ret[1] -end - -local get_cond -get_cond = function(c, base_string) - local cond_string = base_string or '#if ' - if type(c) == 'table' then - cond_string = cond_string .. get_cond(c[1], '') - for i, subc in ipairs(c) do - if i > 1 then - cond_string = cond_string .. ' && ' .. get_cond(subc, '') - end - end - elseif c:sub(1, 1) == '!' then - cond_string = cond_string .. '!defined(' .. c:sub(2) .. ')' - else - cond_string = cond_string .. 'defined(' .. c .. ')' - end - return cond_string -end - -value_dumpers = { - ['function']=function(v) return v() end, - string=cstr, - boolean=function(v) return v and 'true' or 'false' end, - number=function(v) return ('%iL'):format(v) end, - ['nil']=function(v) return '0L' end, -} - -local get_value = function(v) - return '(char_u *) ' .. value_dumpers[type(v)](v) -end - -local get_defaults = function(d) - return '{' .. get_value(d.vi) .. ', ' .. get_value(d.vim) .. '}' -end - -local defines = {} - -local dump_option = function(i, o) - w(' [' .. ('%u'):format(i - 1) .. ']={') - w(' .fullname=' .. cstr(o.full_name)) - if o.abbreviation then - w(' .shortname=' .. cstr(o.abbreviation)) - end - w(' .flags=' .. get_flags(o)) - if o.enable_if then - w(get_cond(o.enable_if)) - end - if o.varname then - w(' .var=(char_u *)&' .. o.varname) - elseif #o.scope == 1 and o.scope[1] == 'window' then - w(' .var=VAR_WIN') - end - if o.enable_if then - w('#endif') - end - if #o.scope == 1 and o.scope[1] == 'global' then - w(' .indir=PV_NONE') - else - assert (#o.scope == 1 or #o.scope == 2) - assert (#o.scope == 1 or o.scope[1] == 'global') - local min_scope = o.scope[#o.scope] - local varname = o.pv_name or o.varname or ( - 'p_' .. (o.abbreviation or o.full_name)) - local pv_name = ( - 'OPT_' .. min_scope:sub(1, 3):upper() .. '(' .. ( - min_scope:sub(1, 1):upper() .. 'V_' .. varname:sub(3):upper() - ) .. ')' - ) - if #o.scope == 2 then - pv_name = 'OPT_BOTH(' .. pv_name .. ')' - end - defines['PV_' .. varname:sub(3):upper()] = pv_name - w(' .indir=' .. pv_name) - end - if o.defaults then - if o.defaults.condition then - w(get_cond(o.defaults.condition)) - end - w(' .def_val=' .. get_defaults(o.defaults.if_true)) - if o.defaults.condition then - if o.defaults.if_false then - w('#else') - w(' .def_val=' .. get_defaults(o.defaults.if_false)) - end - w('#endif') - end - end - w(' },') -end - -w('static vimoption_T options[] = {') -for i, o in ipairs(options.options) do - dump_option(i, o) -end -w(' [' .. ('%u'):format(#options.options) .. ']={.fullname=NULL}') -w('};') -w('') - -for k, v in pairs(defines) do - w('#define ' .. k .. ' ' .. v) -end -opt_fd:close() diff --git a/scripts/genunicodetables.lua b/scripts/genunicodetables.lua deleted file mode 100644 index 66430ba26e..0000000000 --- a/scripts/genunicodetables.lua +++ /dev/null @@ -1,327 +0,0 @@ --- Script creates the following tables in unicode_tables.generated.h: --- --- 1. doublewidth and ambiguous tables: sorted list of non-overlapping closed --- intervals. Codepoints in these intervals have double (W or F) or ambiguous --- (A) east asian width respectively. --- 2. combining table: same as the above, but characters inside are combining --- characters (i.e. have general categories equal to Mn, Mc or Me). --- 3. foldCase, toLower and toUpper tables used to convert characters to --- folded/lower/upper variants. In these tables first two values are --- character ranges: like in previous tables they are sorted and must be --- non-overlapping. Third value means step inside the range: e.g. if it is --- 2 then interval applies only to first, third, fifth, … character in range. --- Fourth value is number that should be added to the codepoint to yield --- folded/lower/upper codepoint. --- 4. emoji_width and emoji_all tables: sorted lists of non-overlapping closed --- intervals of Emoji characters. emoji_width contains all the characters --- which don't have ambiguous or double width, and emoji_all has all Emojis. -if arg[1] == '--help' then - print('Usage:') - print(' genunicodetables.lua unicode/ unicode_tables.generated.h') - os.exit(0) -end - -local basedir = arg[1] -local pathsep = package.config:sub(1, 1) -local get_path = function(fname) - return basedir .. pathsep .. fname -end - -local unicodedata_fname = get_path('UnicodeData.txt') -local casefolding_fname = get_path('CaseFolding.txt') -local eastasianwidth_fname = get_path('EastAsianWidth.txt') -local emoji_fname = get_path('emoji-data.txt') - -local utf_tables_fname = arg[2] - -local split_on_semicolons = function(s) - local ret = {} - local idx = 1 - while idx <= #s + 1 do - item = s:match('^[^;]*', idx) - idx = idx + #item + 1 - if idx <= #s + 1 then - assert(s:sub(idx - 1, idx - 1) == ';') - end - item = item:gsub('^%s*', '') - item = item:gsub('%s*$', '') - table.insert(ret, item) - end - return ret -end - -local fp_lines_to_lists = function(fp, n, has_comments) - local ret = {} - local line - local i = 0 - while true do - i = i + 1 - line = fp:read('*l') - if not line then - break - end - if (not has_comments - or (line:sub(1, 1) ~= '#' and not line:match('^%s*$'))) then - local l = split_on_semicolons(line) - if #l ~= n then - io.stderr:write(('Found %s items in line %u, expected %u\n'):format( - #l, i, n)) - io.stderr:write('Line: ' .. line .. '\n') - return nil - end - table.insert(ret, l) - end - end - return ret -end - -local parse_data_to_props = function(ud_fp) - return fp_lines_to_lists(ud_fp, 15, false) -end - -local parse_fold_props = function(cf_fp) - return fp_lines_to_lists(cf_fp, 4, true) -end - -local parse_width_props = function(eaw_fp) - return fp_lines_to_lists(eaw_fp, 2, true) -end - -local parse_emoji_props = function(emoji_fp) - return fp_lines_to_lists(emoji_fp, 2, true) -end - -local make_range = function(start, end_, step, add) - if step and add then - return (' {0x%x, 0x%x, %d, %d},\n'):format( - start, end_, step == 0 and -1 or step, add) - else - return (' {0x%04x, 0x%04x},\n'):format(start, end_) - end -end - -local build_convert_table = function(ut_fp, props, cond_func, nl_index, - table_name) - ut_fp:write('static const convertStruct ' .. table_name .. '[] = {\n') - local start = -1 - local end_ = -1 - local step = 0 - local add = -1 - for _, p in ipairs(props) do - if cond_func(p) then - local n = tonumber(p[1], 16) - local nl = tonumber(p[nl_index], 16) - if start >= 0 and add == (nl - n) and (step == 0 or n - end_ == step) then - -- Continue with the same range. - step = n - end_ - end_ = n - else - if start >= 0 then - -- Produce previous range. - ut_fp:write(make_range(start, end_, step, add)) - end - start = n - end_ = n - step = 0 - add = nl - n - end - end - end - if start >= 0 then - ut_fp:write(make_range(start, end_, step, add)) - end - ut_fp:write('};\n') -end - -local build_case_table = function(ut_fp, dataprops, table_name, index) - local cond_func = function(p) - return p[index] ~= '' - end - return build_convert_table(ut_fp, dataprops, cond_func, index, - 'to' .. table_name) -end - -local build_fold_table = function(ut_fp, foldprops) - local cond_func = function(p) - return (p[2] == 'C' or p[2] == 'S') - end - return build_convert_table(ut_fp, foldprops, cond_func, 3, 'foldCase') -end - -local build_combining_table = function(ut_fp, dataprops) - ut_fp:write('static const struct interval combining[] = {\n') - local start = -1 - local end_ = -1 - for _, p in ipairs(dataprops) do - if (({Mn=true, Mc=true, Me=true})[p[3]]) then - local n = tonumber(p[1], 16) - if start >= 0 and end_ + 1 == n then - -- Continue with the same range. - end_ = n - else - if start >= 0 then - -- Produce previous range. - ut_fp:write(make_range(start, end_)) - end - start = n - end_ = n - end - end - end - if start >= 0 then - ut_fp:write(make_range(start, end_)) - end - ut_fp:write('};\n') -end - -local build_width_table = function(ut_fp, dataprops, widthprops, widths, - table_name) - ut_fp:write('static const struct interval ' .. table_name .. '[] = {\n') - local start = -1 - local end_ = -1 - local dataidx = 1 - local ret = {} - for _, p in ipairs(widthprops) do - if widths[p[2]:sub(1, 1)] then - local rng_start, rng_end = p[1]:find('%.%.') - local n, n_last - if rng_start then - -- It is a range. We don’t check for composing char then. - n = tonumber(p[1]:sub(1, rng_start - 1), 16) - n_last = tonumber(p[1]:sub(rng_end + 1), 16) - else - n = tonumber(p[1], 16) - n_last = n - end - local dn - while true do - dn = tonumber(dataprops[dataidx][1], 16) - if dn >= n then - break - end - dataidx = dataidx + 1 - end - if dn ~= n and n_last == n then - io.stderr:write('Cannot find character ' .. n .. ' in data table.\n') - end - -- Only use the char when it’s not a composing char. - -- But use all chars from a range. - local dp = dataprops[dataidx] - if (n_last > n) or (not (({Mn=true, Mc=true, Me=true})[dp[3]])) then - if start >= 0 and end_ + 1 == n then - -- Continue with the same range. - else - if start >= 0 then - ut_fp:write(make_range(start, end_)) - table.insert(ret, {start, end_}) - end - start = n - end - end_ = n_last - end - end - end - if start >= 0 then - ut_fp:write(make_range(start, end_)) - table.insert(ret, {start, end_}) - end - ut_fp:write('};\n') - return ret -end - -local build_emoji_table = function(ut_fp, emojiprops, doublewidth, ambiwidth) - local emojiwidth = {} - local emoji = {} - for _, p in ipairs(emojiprops) do - if p[2]:match('Emoji%s+#') then - local rng_start, rng_end = p[1]:find('%.%.') - if rng_start then - n = tonumber(p[1]:sub(1, rng_start - 1), 16) - n_last = tonumber(p[1]:sub(rng_end + 1), 16) - else - n = tonumber(p[1], 16) - n_last = n - end - if #emoji > 0 and n - 1 == emoji[#emoji][2] then - emoji[#emoji][2] = n_last - else - table.insert(emoji, { n, n_last }) - end - - -- Characters below 1F000 may be considered single width traditionally, - -- making them double width causes problems. - if n >= 0x1f000 then - -- exclude characters that are in the ambiguous/doublewidth table - for _, ambi in ipairs(ambiwidth) do - if n >= ambi[1] and n <= ambi[2] then - n = ambi[2] + 1 - end - if n_last >= ambi[1] and n_last <= ambi[2] then - n_last = ambi[1] - 1 - end - end - for _, double in ipairs(doublewidth) do - if n >= double[1] and n <= double[2] then - n = double[2] + 1 - end - if n_last >= double[1] and n_last <= double[2] then - n_last = double[1] - 1 - end - end - - if n <= n_last then - if #emojiwidth > 0 and n - 1 == emojiwidth[#emojiwidth][2] then - emojiwidth[#emojiwidth][2] = n_last - else - table.insert(emojiwidth, { n, n_last }) - end - end - end - end - end - - ut_fp:write('static const struct interval emoji_all[] = {\n') - for _, p in ipairs(emoji) do - ut_fp:write(make_range(p[1], p[2])) - end - ut_fp:write('};\n') - - ut_fp:write('static const struct interval emoji_width[] = {\n') - for _, p in ipairs(emojiwidth) do - ut_fp:write(make_range(p[1], p[2])) - end - ut_fp:write('};\n') -end - -local ud_fp = io.open(unicodedata_fname, 'r') -local dataprops = parse_data_to_props(ud_fp) -ud_fp:close() - -local ut_fp = io.open(utf_tables_fname, 'w') - -build_case_table(ut_fp, dataprops, 'Lower', 14) -build_case_table(ut_fp, dataprops, 'Upper', 13) -build_combining_table(ut_fp, dataprops) - -local cf_fp = io.open(casefolding_fname, 'r') -local foldprops = parse_fold_props(cf_fp) -cf_fp:close() - -build_fold_table(ut_fp, foldprops) - -local eaw_fp = io.open(eastasianwidth_fname, 'r') -local widthprops = parse_width_props(eaw_fp) -eaw_fp:close() - -local doublewidth = build_width_table(ut_fp, dataprops, widthprops, - {W=true, F=true}, 'doublewidth') -local ambiwidth = build_width_table(ut_fp, dataprops, widthprops, - {A=true}, 'ambiguous') - -local emoji_fp = io.open(emoji_fname, 'r') -local emojiprops = parse_emoji_props(emoji_fp) -emoji_fp:close() - -build_emoji_table(ut_fp, emojiprops, doublewidth, ambiwidth) - -ut_fp:close() -- cgit From d72df05b930c7dd79f138ec371124329eb9c9259 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 20 May 2017 03:35:50 +0300 Subject: pvscheck: Add --only-analyse mode --- scripts/pvscheck.sh | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index c75dd2ab76..79ed08f458 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -14,7 +14,7 @@ get_jobs_num() { help() { echo 'Usage:' echo ' pvscheck.sh [--pvs URL] [--deps] [target-directory [branch]]' - echo ' pvscheck.sh [--pvs URL] [--recheck] [target-directory]' + echo ' pvscheck.sh [--pvs URL] [--recheck|--only-analyse] [target-directory]' echo ' pvscheck.sh [--pvs URL] --pvs-install {target-directory}' echo ' pvscheck.sh --patch [--only-build]' echo @@ -39,6 +39,9 @@ help() { echo echo ' --recheck: run analysis on a prepared target directory.' echo + echo ' --only-analyse: run analysis on a prepared target directory ' + echo ' without building Neovim.' + echo echo ' target-directory: Directory where build should occur.' echo ' Default: ../neovim-pvs' echo @@ -348,20 +351,23 @@ do_check() { install_pvs "$tgt" "$pvs_url" - adjust_path "$tgt" + do_recheck "$tgt" "$deps" +} + +do_recheck() { + local tgt="$1" ; shift + local deps="$2" ; shift create_compile_commands "$tgt" "$deps" - run_analysis "$tgt" + do_analysis "$tgt" } -do_recheck() { - local tgt="$1" +do_analysis() { + local tgt="$1" ; shift adjust_path "$tgt" - create_compile_commands "$tgt" "$deps" - run_analysis "$tgt" } @@ -384,6 +390,7 @@ main() { patch store_const \ only-build 'store_const --only-build' \ recheck store_const \ + only-analyse store_const \ pvs-install store_const \ deps store_const \ -- \ @@ -404,7 +411,9 @@ main() { elif test -n "$pvs_install" ; then install_pvs "$tgt" "$pvs_url" elif test -n "$recheck" ; then - do_recheck "$tgt" + do_recheck "$tgt" "$deps" + elif test -n "$only_analyse" ; then + do_analysis "$tgt" else do_check "$tgt" "$branch" "$pvs_url" "$deps" fi -- cgit From 7f24736ebc050a9b81d4d2db0158111486b1836b Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 20 May 2017 03:44:23 +0300 Subject: pvscheck: Handle invalid option error gracefully --- scripts/pvscheck.sh | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index 79ed08f458..949021a174 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -50,7 +50,17 @@ help() { } getopts_error() { - printf '%s\n' "$1" >&2 + local msg="$1" ; shift + local do_help= + if test "$msg" = "--help" ; then + msg="$1" ; shift + do_help=1 + fi + printf '%s\n' "$msg" >&2 + if test -n "$do_help" ; then + printf '\n' >&2 + help >&2 + fi echo 'return 1' return 1 } @@ -146,8 +156,8 @@ getopts_long() { if test -n "$opt_base" ; then eval "local occurred_$opt_base=1" - eval "local act_1=\"\$act_1_$opt_base\"" - eval "local varname=\"\$varname_$opt_base\"" + eval "local act_1=\"\${act_1_$opt_base:-}\"" + eval "local varname=\"\${varname_$opt_base:-}\"" local need_val= local func= case "$act_1" in @@ -170,6 +180,9 @@ getopts_long() { eval "varname=\"\${act_3_${opt_base}:-$varname}\"" need_val=1 ;; + ("") + getopts_error --help "Wrong argument: $argument" + ;; esac if test -n "$need_val" ; then local val= -- cgit From c585a72cdc6d2cb7f507c59eb4a6981e54c77ebc Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 20 May 2017 05:06:16 +0300 Subject: pvscheck: Provide arguments to `patch_sources` in correct order --- scripts/pvscheck.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index 949021a174..ca85b6be7f 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -306,7 +306,7 @@ realdir() {( patch_sources() {( local tgt="$1" ; shift - local only_bulid="${1:-}" + local only_bulid="${1}" ; shift get_pvs_comment "$tgt" @@ -420,7 +420,7 @@ main() { set -x if test -n "$patch" ; then - patch_sources "$only_build" "$tgt" + patch_sources "$tgt" "$only_build" elif test -n "$pvs_install" ; then install_pvs "$tgt" "$pvs_url" elif test -n "$recheck" ; then -- cgit From 90f20bd7b17a4c6889136008593312f8f8fe377b Mon Sep 17 00:00:00 2001 From: James McCoy Date: Fri, 9 Jun 2017 16:42:43 -0400 Subject: pvscheck: Fix argument handling in do_recheck [ci skip] --- scripts/pvscheck.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index ca85b6be7f..d6d28e3c6c 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -369,7 +369,7 @@ do_check() { do_recheck() { local tgt="$1" ; shift - local deps="$2" ; shift + local deps="$1" ; shift create_compile_commands "$tgt" "$deps" -- cgit From 6eb2bcd1a02872433871cc53f525e90dc03fe4dd Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sun, 11 Jun 2017 16:25:13 +0200 Subject: scripts/vim-patch.sh: do not git-reset on push failure (#6878) This was added from the beginning to submit_pr in 775a16b0b, but I cannot see why that is useful - in contrast, it will mess with the local branch in case "origin" cannot be pushed to (i.e. when it points to neovim/neovim itself). --- scripts/vim-patch.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index 3b083e7b83..63665b9253 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -280,7 +280,7 @@ submit_pr() { echo "Pushing to 'origin/${checked_out_branch}'." output="$(git push origin "${checked_out_branch}" 2>&1)" && echo "✔ ${output}" || - (echo "✘ ${output}"; git reset --soft HEAD^1; false) + (echo "✘ ${output}"; false) echo fi -- cgit From 45df8f77dff1083ec518427289533ec05f1ff0c3 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Thu, 15 Jun 2017 19:01:11 +0200 Subject: scripts/pvscheck.sh: fixes [ci skip] --- scripts/pvscheck.sh | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index d6d28e3c6c..535f14beb4 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -1,14 +1,15 @@ #!/bin/sh + +# Assume that "local" is available. +# shellcheck disable=SC2039 + set -e # Note: -u causes problems with posh, it barks at “undefined” $@ when no # arguments provided. test -z "$POSH_VERSION" && set -u -get_jobs_num() { - local num="$(cat /proc/cpuinfo | grep -c "^processor")" - num="$(echo $(( num + 1 )))" - num="${num:-1}" - echo $num +echo_jobs_num() { + echo $(( $(grep -c "^processor" /proc/cpuinfo) + 1 )) } help() { @@ -21,7 +22,7 @@ help() { echo ' --pvs: Use the specified URL as a path to pvs-studio archive.' echo ' By default latest tested version is used.' echo - echo ' May use `--pvs detect` to try detecting latest version.' + echo ' May use "--pvs detect" to try detecting latest version.' echo ' That assumes certain viva64.com site properties and' echo ' may be broken by the site update.' echo @@ -261,15 +262,6 @@ install_pvs() {( rmdir "$pvsdir" )} -adjust_path() { - if test -d "$tgt/pvs-studio" ; then - local saved_pwd="$PWD" - cd "$tgt/pvs-studio" - export PATH="$PWD/bin${PATH+:}${PATH}" - cd "$saved_pwd" - fi -} - create_compile_commands() {( local tgt="$1" ; shift local deps="$1" ; shift @@ -283,13 +275,13 @@ create_compile_commands() {( cd "$tgt/build" cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="$PWD/root" - make -j"$(get_jobs_num)" + make -j"$(echo_jobs_num)" ) else ( cd "$tgt" - make -j"$(get_jobs_num)" CMAKE_EXTRA_FLAGS=" -DCMAKE_INSTALL_PREFIX=$PWD/root -DCMAKE_BUILD_TYPE=Debug " + make -j"$(echo_jobs_num)" CMAKE_EXTRA_FLAGS=" -DCMAKE_INSTALL_PREFIX=$PWD/root -DCMAKE_BUILD_TYPE=Debug " ) fi find "$tgt/build/src/nvim/auto" -name '*.test-include.c' -delete @@ -379,7 +371,12 @@ do_recheck() { do_analysis() { local tgt="$1" ; shift - adjust_path "$tgt" + if test -d "$tgt/pvs-studio" ; then + local saved_pwd="$PWD" + cd "$tgt/pvs-studio" + export PATH="$PWD/bin${PATH+:}${PATH}" + cd "$saved_pwd" + fi run_analysis "$tgt" } -- cgit From 26235bc050abece269737fd2b77bbc392d45ffc1 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 19 Jun 2017 01:43:18 +0200 Subject: genappimage.sh: set CMAKE_INSTALL_MANDIR Avoids attempt to install manpage to system location. Also: - Don't attempt `nvim --version` until after it was built. - Remove unnecessary `mkdir`. --- scripts/genappimage.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/genappimage.sh b/scripts/genappimage.sh index fd7247b947..a73ccd86c7 100755 --- a/scripts/genappimage.sh +++ b/scripts/genappimage.sh @@ -18,23 +18,22 @@ ROOT_DIR="$(git rev-parse --show-toplevel)" APP_BUILD_DIR="$ROOT_DIR/build" APP_DIR="$APP.AppDir" -# App version, used by generate_appimage. -VERSION=$("$ROOT_DIR"/build/bin/nvim --version | head -n 1 | grep -o 'v.*') - ######################################################################## # Compile nvim and install it into AppDir ######################################################################## # Build and install nvim into the AppImage -make CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX=${APP_DIR}/usr" +make CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX=${APP_DIR}/usr -DCMAKE_INSTALL_MANDIR=man" make install ######################################################################## # Get helper functions and move to AppDir ######################################################################## +# App version, used by generate_appimage. +VERSION=$("$ROOT_DIR"/build/bin/nvim --version | head -n 1 | grep -o 'v.*') + cd "$APP_BUILD_DIR" -mkdir "$APP_DIR" curl -Lo "$APP_BUILD_DIR"/appimage_functions.sh https://github.com/probonopd/AppImages/raw/master/functions.sh . ./appimage_functions.sh @@ -80,3 +79,5 @@ generate_appimage mv "$ROOT_DIR"/out/*.AppImage "$ROOT_DIR"/build/bin # Remove the (now empty) folder the AppImage was built in rmdir "$ROOT_DIR"/out + +echo 'genappimage.sh: finished' -- cgit From a46970449540e327dd858b597dbfad0a2c1fb48a Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 25 Jun 2017 03:26:04 +0200 Subject: scripts/pvscheck.sh: HACK: de-parallelize on CI References https://github.com/neovim/bot-ci/pull/105 --- scripts/pvscheck.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index 535f14beb4..b3ca2c0fb8 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -9,7 +9,9 @@ set -e test -z "$POSH_VERSION" && set -u echo_jobs_num() { - echo $(( $(grep -c "^processor" /proc/cpuinfo) + 1 )) + [ -n "$TRAVIS_CI_BUILD" ] \ + && echo 1 \ + || echo $(( $(grep -c "^processor" /proc/cpuinfo) + 1 )) } help() { -- cgit From 4b08b5d1942ac12c54b959ec4bb2c5e13b2de587 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 25 Jun 2017 07:35:01 +0200 Subject: scripts/pvscheck.sh: HACK: de-parallelize on CI https://github.com/neovim/bot-ci/pull/105#issuecomment-309282132 --- scripts/pvscheck.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index b3ca2c0fb8..575648c688 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -9,9 +9,12 @@ set -e test -z "$POSH_VERSION" && set -u echo_jobs_num() { - [ -n "$TRAVIS_CI_BUILD" ] \ - && echo 1 \ - || echo $(( $(grep -c "^processor" /proc/cpuinfo) + 1 )) + if [ -n "${TRAVIS:-}" ] ; then + # HACK: /proc/cpuinfo on Travis CI is misleading, so hardcode 1. + echo 1 + else + echo $(( $(grep -c "^processor" /proc/cpuinfo) + 1 )) + fi } help() { -- cgit From 2b377d89dbe4174a74e021ffe4e8b86d0d729d0e Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 25 Jun 2017 07:52:21 +0200 Subject: scripts/pvscheck.sh: fix function rename --- scripts/pvscheck.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/pvscheck.sh b/scripts/pvscheck.sh index 575648c688..dfdc539bf9 100755 --- a/scripts/pvscheck.sh +++ b/scripts/pvscheck.sh @@ -8,7 +8,7 @@ set -e # arguments provided. test -z "$POSH_VERSION" && set -u -echo_jobs_num() { +get_jobs_num() { if [ -n "${TRAVIS:-}" ] ; then # HACK: /proc/cpuinfo on Travis CI is misleading, so hardcode 1. echo 1 @@ -280,13 +280,13 @@ create_compile_commands() {( cd "$tgt/build" cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="$PWD/root" - make -j"$(echo_jobs_num)" + make -j"$(get_jobs_num)" ) else ( cd "$tgt" - make -j"$(echo_jobs_num)" CMAKE_EXTRA_FLAGS=" -DCMAKE_INSTALL_PREFIX=$PWD/root -DCMAKE_BUILD_TYPE=Debug " + make -j"$(get_jobs_num)" CMAKE_EXTRA_FLAGS=" -DCMAKE_INSTALL_PREFIX=$PWD/root -DCMAKE_BUILD_TYPE=Debug " ) fi find "$tgt/build/src/nvim/auto" -name '*.test-include.c' -delete -- cgit