lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Wed, 19 Jan 2005 11:55:04 +0000, duck <duck@extremis.net> wrote:

>bin2c is great because it lets you build Lua code right into your
>binary, though it means the code is in memory twice (once as a
>data string in the interpreter and once as a bytecode string inside the
>Lua machine).

What helps this is to use Windows resources. The following builds
the resource which can be #included in your resource file. Then just
use LoadResource() to load the script transiently into memory.
Then the code does not take up C string space.

I use something like

	luac -s -o $*.lc $*.lua
	lua bin2res.lua $*.lc > $@


bin2res.lua

--
-- modified load_buffer
--
-- BIN2RES.LUA
--
-- Convert files to byte arrays for automatic loading with lua_loadbuffer
--
-- Based on 'etc/bin2c.c' of Lua 5.0.1 sources by:
--      Luiz Henrique de Figueiredo (lhf@tecgraf.puc-rio.br)
--
-- Fixed so that subdirectory names are not included in debug info:
--      Asko Kauppi (asko.kauppi@sci.fi)
--
-- some changes and fixes by D. Burgess
--
local strlen,format,byte = string.len,string.format,string.byte
local oh
local function put2(s)
--  oh:write(format("0x%04x",(byte(s,1)*256) + byte(s,2)))
  oh:write(format("0x%02x",byte(s,2)))
  oh:write(format("%02x",byte(s,1)))
end
local function put1(s)
  oh:write(format('"\\%03o"',byte(s)))
end


local function dump(base, f, id)
  local str = ""
  local comma =","
  local s
  oh:write("bin2res_"..base, " RCDATA \n{\n")
  j = 0
  while not eof do
    s = f:read(2)
    if not s then
      eof=true
    end
    if not eof then
      local l = strlen(s)
      if j ~= 0 then oh:write(",") end
      if j>10 then
        oh:write("\n")
        j=0
      end
      if l == 2 then
        put2(s)
      elseif l == 1 then
        put1(s)
      end
    end
    if eof then
      oh:write("\n}\n")
      return
    end
    j = j + 1
  end
end

--
local function fdump( fn, id )
     --
     local f= io.open( fn, "rb" )    -- must open as binary

     if not f then
         error( "cannot open "..fn )
     else
         local _,_, base=string.find( fn, ".+[/\\](.-)$" )    -- remove path
         _,_, base= string.find( base or fn, "([^.]*)" )      -- remove suffix
         base = string.lower(base)
         local sz = f:seek('end',0)
         f:seek('set',0)

         oh:write("// data is bytes no alignment or byte reversal\n")
         oh:write("// size of data is " .. sz .."\n")
         dump(base, f, id, sz )
         f:close()
     end
end

local function main(argv)
  return function()
     if not argv or not argv[1] then
        error( 'file name required',0)    -- an error we need the size
so no stdin (no params)
        return
     end
     local outfil = nil
     local b=1
     if argv[1] == '-o' then
        b=3
        outfil = argv[2]
        if b > argv.n or not outfil then
          error'invalid arguments'
        end
     end
     if outfil then
       local e
       oh,e=io.open(outfil,"wb")
       if not oh then error ('cannot open ' .. outfil) end
     else
       oh=io.stdout
     end

     oh:write("// resource code automatically generated by bin2res --
DO NOT EDIT\n")
     oh:write "// #include in an RC file for "
     for i = b, argv.n, 1 do
         v=argv[i]
         oh:write (string.gsub(v,'\\','\\\\'),'\n')
     end
     for i = b, argv.n, 1 do fdump(argv[i],i) end
     return 0
  end
end

--main(arg)()
r,e = xpcall(main(arg), function(s) return s end)
if not r then io.stderr:write(e,'\n') end
return r