neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

gen_char_blob.lua (2449B)


      1 if arg[1] == '--help' then
      2  print('Usage:')
      3  print('  ' .. arg[0] .. ' [-c] target source varname [source varname]...')
      4  print('')
      5  print('Generates C file with big uint8_t blob.')
      6  print('Blob will be stored in a static const array named varname.')
      7  os.exit()
      8 end
      9 
     10 -- Recognized options:
     11 --   -c   compile Lua bytecode
     12 local options = {}
     13 
     14 while true do
     15  local opt = string.match(arg[1], '^-(%w)')
     16  if not opt then
     17    break
     18  end
     19 
     20  options[opt] = true
     21  table.remove(arg, 1)
     22 end
     23 
     24 assert(#arg >= 3 and (#arg - 1) % 2 == 0)
     25 
     26 local target_file = arg[1] or error('Need a target file')
     27 local target = io.open(target_file, 'w')
     28 
     29 target:write('#include <stdint.h>\n\n')
     30 
     31 local index_items = {}
     32 
     33 local warn_on_missing_compiler = true
     34 local modnames = {}
     35 for argi = 2, #arg, 2 do
     36  local source_file = arg[argi]
     37  local modname = arg[argi + 1]
     38  if modnames[modname] then
     39    error(string.format('modname %q is already specified for file %q', modname, modnames[modname]))
     40  end
     41  modnames[modname] = source_file
     42 
     43  local varname = string.gsub(modname, '%.', '_dot_') .. '_module'
     44  target:write(('static const uint8_t %s[] = {\n'):format(varname))
     45 
     46  local output
     47  if options.c then
     48    local luac = os.getenv('LUAC_PRG')
     49    if luac and luac ~= '' then
     50      output = io.popen(luac:format(source_file), 'r'):read('*a')
     51    elseif warn_on_missing_compiler then
     52      print('LUAC_PRG is missing, embedding raw source')
     53      warn_on_missing_compiler = false
     54    end
     55  end
     56 
     57  if not output then
     58    local source = io.open(source_file, 'r')
     59      or error(string.format("source_file %q doesn't exist", source_file))
     60    output = source:read('*a')
     61    source:close()
     62  end
     63 
     64  local num_bytes = 0
     65  local MAX_NUM_BYTES = 15 -- 78 / 5: maximum number of bytes on one line
     66  target:write(' ')
     67 
     68  local increase_num_bytes
     69  increase_num_bytes = function()
     70    num_bytes = num_bytes + 1
     71    if num_bytes == MAX_NUM_BYTES then
     72      num_bytes = 0
     73      target:write('\n ')
     74    end
     75  end
     76 
     77  for i = 1, string.len(output) do
     78    local byte = output:byte(i)
     79    target:write(string.format(' %3u,', byte))
     80    increase_num_bytes()
     81  end
     82 
     83  target:write('  0};\n')
     84  if modname ~= '_' then
     85    table.insert(
     86      index_items,
     87      '  { "' .. modname .. '", ' .. varname .. ', sizeof ' .. varname .. ' },\n\n'
     88    )
     89  end
     90 end
     91 
     92 target:write('static ModuleDef builtin_modules[] = {\n')
     93 target:write(table.concat(index_items))
     94 target:write('};\n')
     95 
     96 target:close()