clua (empty) → 0.1
raw patch · 6 files changed
+264/−0 lines, 6 filesdep +basedep +bytestringdep +containerssetup-changed
Dependencies added: base, bytestring, containers, haskell98, language-c, pretty, pretty-show
Files
- LICENSE +30/−0
- README +47/−0
- Setup.hs +2/−0
- clua.cabal +22/−0
- clua.hs +16/−0
- parse-bin.lua +147/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2012, Tom Schouten++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Tom Schouten nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README view
@@ -0,0 +1,47 @@+Gather C structs tagged with __attribute__((__packed__)) and enum+definitions into a Lua data structure. This allows conversion between+binary blobs and Lua tables using functions parse-bin.lua provides,+useful for C applications with an embedded Lua interpreter.++This tool is a thin wrapper around the awesome Language.C library:+http://hackage.haskell.org/package/language-c+++BUILD++( Instructions for Debian ) ++# Optionally add ~/.cabal/bin to your search path. This is where+# cabal will install Haskell binaries, including the updated version+# of cabal itself.++apt-get install cabal-install haskell-platform+cabal update+cabal install cabal-install+cabal install pretty-show+cabal install happy+cabal install language-c++tar xf packed_lua.tar.gz+cd packed_lua++# The 2 commands below also appear in the Makefile.++cabal configure+cabal build++# At this point the binary will be in the local directory:+# dist/build/packed-lua/packed-lua+# Optionally install it to ~/.cabal/bin using:++cabal install++++USAGE++Provide the (possibly prepocessed) C file as a first argument and+gather the Lua output on stdout, i.e:++ packed_lua structs.c >sym.lua+
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ clua.cabal view
@@ -0,0 +1,22 @@+Name: clua+Version: 0.1+Synopsis: C to Lua data wrapper generator+Homepage: http://zwizwa.be/-/meta+License: BSD3+License-file: LICENSE+Author: Tom Schouten+Maintainer: tom@zwizwa.be+Category: Language+Build-type: Simple+Extra-source-files: README, parse-bin.lua+Cabal-version: >=1.2++Description: Gather enums and packed struct definitions from a C file+ and generate a Lua table that can be used in conjunction+ with parse-bin.lua to convert between Lua tables and+ binary data.++Executable clua+ Main-is: clua.hs+ Build-depends: base < 5, haskell98, pretty, containers,+ language-c, pretty-show, bytestring
+ clua.hs view
@@ -0,0 +1,16 @@+import CAnalyze -- wrappers around Language.C analysis+import PrintLua+import System++usage me =+ putStrLn $ "usage: " ++ me ++ " <c-file>"+++main = do+ args <- getArgs+ me <- getProgName+ case args of+ -- [file] -> report (aKeys packedStructs) file+ [file] -> packedLua file+ _ -> usage me+
+ parse-bin.lua view
@@ -0,0 +1,147 @@+-- Goes together with the struct wrapper generator.++-- Tools+local function table_copy(t)+ local u = { }+ for k, v in pairs(t) do u[k] = v end+ return setmetatable(u, getmetatable(t))+end+++parse = {}++-- Wrap table as abstract stream.+function parse.array2stream(arr)+ if (arr) then+ local i = 0+ return+ function()+ i = i + 1+ return arr[i]+ end+ else+ -- Allow arr to be nil in case we assume it's a stream of zeros.+ return+ function() + return 0+ end+ end+end++-- Parsers for "int", "float", "struct", "array"+function parse.int(stream, structs, signed, bits)+ local bytes = bits/8+ local accu = 0+ local shift = 1+ local byte = 0+ while (bytes > 0) do+ byte = assert(stream())+ accu = accu + shift * byte;+ shift = shift * 0x100+ bytes = bytes - 1+ end+ if ((signed == 'S') and (byte > 0x7F)) then+ accu = accu - shift+ end+ return accu+end++function parse.float()+ assert(nil) -- FIXME+end++function parse.struct(stream, structs, struct_name)+ return parse.table(stream, structs, structs[struct_name])+end++function parse.array(stream, structs, size, type_spec)+ if (size == 0) then+ return {}+ else+ local arr = {}+ for i=1, size do+ arr[i] = parse.type(stream, structs, type_spec)+ end+ return arr+ end+end++++-- Element dispatcher.+function parse.type(stream, structs, type_spec)+ local spec = table_copy(type_spec)+ local type = assert(table.remove(spec,1))+ -- print (type)+ local fun = assert(parse[type])+ return fun(stream, structs, table.unpack(spec))+end++-- Table dispatcher+function parse.table(stream, structs, tab_spec) + local tab = {}+ for i,rec_spec in pairs(tab_spec) do+ local type_spec, name = table.unpack(rec_spec)+ tab[name] = parse.type(stream, structs, type_spec)+ end+ return tab+end++-- Functional interface+function parse.array2table (array, structs, tab_spec)+ return parse.table (parse.array2stream(array), structs, tab_spec)+end+++-- Wrap table as abstract stream.+unparse = {}+function unparse.array2stream(t)+ return+ function(byte)+ table.insert(t, byte)+ end+end++function unparse.int(stream, val, structs, signed, bits)+ local bytes = bits/8+ local accu = val+ while (bytes > 0) do+ local byte = accu % 0x100+ stream(byte)+ accu = math.floor(accu / 0x100)+ bytes = bytes - 1+ end+end++function unparse.struct(stream, val, structs, struct_name)+ unparse.table(stream, val, structs, structs[struct_name])+end++function unparse.array(stream, arr, structs, size, type_spec)+ if (size > 0) then+ for i=1,size do+ unparse.type(stream, arr[i], structs, type_spec)+ end+ end+end++function unparse.type(stream, val, structs, type_spec)+ local spec = table_copy(type_spec)+ local type = assert(table.remove(spec,1))+ -- print (type)+ unparse[type](stream, val, structs, table.unpack(spec))+end++function unparse.table(stream, tab, structs, tab_spec) + for i,rec_spec in pairs(tab_spec) do+ local type_spec, name = table.unpack(rec_spec)+ unparse.type(stream, tab[name], structs, type_spec)+ end+end++-- Functional interface+function unparse.table2array(tab, structs, tab_spec)+ local arr = {}+ unparse.table(unparse.array2stream(arr), tab, structs, tab_spec)+ return arr+end