Warning: this is an htmlized version!
The original is across this link,
and the conversion rules are here.
-- ctypes2.lua: implement (middle-)C types on top of peek.c.
-- This file:
--   http://angg.twu.net/peek/ctypes2.lua.html
--   http://angg.twu.net/peek/ctypes2.lua
--           (find-angg "peek/ctypes2.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
-- Version: 2012feb01
-- License: GPL3
--
-- See: (find-TH "peek")
--    http://angg.twu.net/peek.html
-- file:///home/edrx/TH/L/peek.html
-- (find-dn5file "")
-- This is just a skeleton at the moment.

-- (find-angg "DAVINCI/peek.lua")
-- (find-angg "DAVINCI/peek-luadecls-1.txt")
-- (find-angg "DAVINCI/peek-luadecls-2.txt")
-- (find-angg "LUA/middle-c.lua")

-- To do: add pointers to several programs that understand C types...
--   cdecl
--   GDB (ptype)
--   the LuaJIT FFI
--   Fabrice Bellard's TCC
--   CLisp FFIs
-- All my doubts about types in C should be explained here:
--   http://c-faq.com/aryptr/index.html
--   http://c-faq.com/struct/index.html

-- package.path = ee_expand("~/dednat5/?.lua")..";"..package.path
-- require "eoo"         -- (find-dn5 "eoo.lua")

ee_dofile "~/dednat5/eoo.lua"

ctypes = {}

CType = Class {
  type    = "CType",
  __tostring = function (ct) return ct:tos() end,
  __index = {
    name        = function (ct) return ct.ctype end,
    size        = function (ct) return ct.nbytes end,
    size_error  = function (ct) error("Expected a size for: "..ct:tos()) end,
    size_assert = function (ct) return ct:size() or ct:size_error() end,
    --
    canon = function (ct)
        local ctname = ct.ctype
        if ctypes[ctname] == nil then ctypes[ctname]=ct; return ct end
        return ctypes[ctname]
      end,
    tos = function (ct) return ct.ctype end,
    --
    star = function (ct)
        local oldctname = ct.ctype
        local newctname = oldctname.."*"
        return CStarType {
            ctype=newctname, basetype=oldctname, what="*",
            nbytes=4, align=4
          }:canon()
      end,
    array_u = function (ct)
        local oldctname = ct.ctype
        local    ctname = oldctname.."[]"
        ct:size_assert()
        return CArrayType {
            ctype=ctname, basetype=oldctname, what="[]",
            nbytes=nil, align=ct.align
          }:canon()
      end,
    array_n = function (ct, n)
        local oldctname = ct.ctype
        local    ctname = oldctname.."["..n.."]"
        local oldsize   = ct:size_assert()
        return CArrayType {
            ctype=ctname, basetype=oldctname, what="[n]",
            nbytes=oldsize*n, align=ct.align
          }:canon()
      end,
    _ = function (ct, str)
        if str == "*" then return ct:star() end
        if str == "[]" then return ct:array_u() end
        local n = str:match("^%[([0-9]*)%]$")
        if n then return ct:array_n(tonumber(n)) end
        error("___?")
      end,
  }
}

CPrimType = ClassOver (CType) {
  type    = "CPrimType",
  __tostring = function (ct) return ct:tos() end,
  __index = {
  },
}
CStarType = ClassOver (CType) {
  type    = "CStarType",
  __tostring = function (ct) return ct:tos() end,
  __index = {
  },
}
CArrayType = ClassOver (CType) {
  type    = "CArrayType",
  __tostring = function (ct) return ct:tos() end,
  __index = {
  },
}

CPrimType {ctype="char",   nbytes=1,   align=1} :canon()
CPrimType {ctype="uchar",  nbytes=1,   align=1} :canon()
CPrimType {ctype="short",  nbytes=2,   align=2} :canon()
CPrimType {ctype="ushort", nbytes=2,   align=2} :canon()
CPrimType {ctype="int",    nbytes=4,   align=4} :canon()
CPrimType {ctype="uint",   nbytes=4,   align=4} :canon()
CPrimType {ctype="void", nbytes=nil, align=nil} :canon()

cty = function (str)
    local spl = split(str)
    local ct = ctypes[spl[1]]
    for i=2,#spl do ct = ct:_(spl[i]) end
    return ct
  end



-- dump-to: tests
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "ctypes2.lua"

PP(cty "char [1] [2] * * [10]")    -- build
PP(cty "char[1][2]**[10]")         -- reuse

CTypeDefType = Class {
  type    = "CTypeDefType",
  __init  = function (c, o) ctypes[o.ctype] = o end,
  __index = {
  },
}

-- More classes:
-- CObj, CField, CStructType, CUnionType, CFunctionType, CTypedefType
-- Methods:
-- star, plus, read, write


------------------------------------------------------------

CStructType  {ctype="struct{int a,char b}", nbytes=5, align=4,
              offsets={["a"]=CField {ctype="int",  offset=0},
                       ["b"]=CField {ctype="char", offset=4},
                      },
             }
CUnionType   {ctype="union{int a,char b}",  nbytes=4, align=4,
              offsets={["a"]=CField {ctype="int",  offset=0},
                       ["b"]=CField {ctype="char", offset=0},
                      },
             }

CTypedefType {ctype="sab", base="struct{int a,char b}", nbytes=5, align=4}
CTypedefType {ctype="uab", base="union{int a,char b}",  nbytes=4, align=4}

PP(ctypes)

-- (find-blogme4 "eval.lua" "parse_pattern")

CObj {ctype="char",  addr=1000, bytes="w"}
CObj {ctype="char*", addr=1000}
CObj {ctype="char*", addr=1000, bytes="!@#$"}

methods:
  plus
  peek
  poke
  star
  

--               
--  __int__ __int__ c______
-- |_:_:_:_|_:_:_:_|_|_:_:_|
-- \-----intintc-----/
-- 0 1 2 3 4 5 6 7 8 9 101112
-- Example: if "intintc" is a ctype with nbytes=9 and align=4,
-- then it has excess=1 and miss=3, and "intintc[100]" is a ctype
-- with nbytes = (9+3)*100-3 = 1200-3 = 1197.
-- 

excess = nbytes % align
miss   = (excess == 0) and 0 else (nbytes - excess)



fake("char*", 1000)


(char*)1000 + 1 = (char*)1004
sizeof((char*)1000) = sizeof((char*)) = 4
*(char*)1000 = peek(1000, 1) = "a"

(char)25
(int)1234




* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
require "ctypes"
string.tonumber = tonumber
printf_ = tostring(printf):match("0x([0-9a-f]+)"):tonumber(16)
= peek_(printf_, 10)

-- (find-es "lua5" "lua-datatypes-gdb")

-- require "peek"
-- (find-angg "peek/peek-0.0.1-0.rockspec" "test")
buf = malloc_(20)
poke_(buf, "abcd")
PP(peek_(buf+2, 2))   --> "cd"





= print


= tostring(print)
= tostring(print):match("0x([0-9A-Fa-f]+)")
= tostring(print):match("0x([0-9A-Fa-f]+)")

hexton = function (hexstr)
    return tonumber(hexstr:match("0x([0-9A-Fa-f]+)"), 16)
  end
ntohex = function (n) return string.format("0x%x", n) end
= hexton "0x2F"
= ntohex(47)

 * (find-angg "peek/peek-0.0.1-0.rockspec" "test")

--]==]

-- (find-angg "peek/ctypes.lua")
-- (find-angg "DAVINCI/peek.lua")
-- (find-angg "DAVINCI/peek-luadecls-1.txt")
-- (find-angg "DAVINCI/peek-luadecls-2.txt")

-- Local Variables:
-- coding:             raw-text-unix
-- ee-anchor-format:   "«%s»"
-- End: