Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
#######
#
# E-scripts on DaVinci (only things not in scintilla.e or iup.e)
#
# Note 1: use the eev command (defined in eev.el) and the
# ee alias (in my .zshrc) to execute parts of this file.
# Executing this file as a whole makes no sense.
# An introduction to eev can be found here:
#
#   (find-eev-quick-intro)
#   http://angg.twu.net/eev-intros/find-eev-quick-intro.html
#
# Note 2: be VERY careful and make sure you understand what
# you're doing.
#
# Note 3: If you use a shell other than zsh things like |&
# and the for loops may not work.
#
# Note 4: I always run as root.
#
# Note 5: some parts are too old and don't work anymore. Some
# never worked.
#
# Note 6: the definitions for the find-xxxfile commands are on my
# .emacs.
#
# Note 7: if you see a strange command check my .zshrc -- it may
# be defined there as a function or an alias.
#
# Note 8: the sections without dates are always older than the
# sections with dates.
#
# This file is at <http://angg.twu.net/e/davinci.e>
#           or at <http://angg.twu.net/e/davinci.e.html>.
#        See also <http://angg.twu.net/emacs.html>,
#                 <http://angg.twu.net/.zshrc[.html]>,
#                 <http://angg.twu.net/escripts.html>,
#             and <http://angg.twu.net/>.
#
#######




    (find-es "davinci")
    (find-es "iup")
    (find-es "scintilla")
    Note: I'm trying to split my notes about the DaVinci project into
    several e-script files (iup.e, davinci.e, peek.e, ...) - but at the
    moment there are lots of duplications and lots of garbage...





# «.correspondencia»		(to "correspondencia")
# «.cronograma-inicial»		(to "cronograma-inicial")
# «.tcmd.tcl»			(to "tcmd.tcl")
# «.tcmd-screenshot»		(to "tcmd-screenshot")
# «.ldb-rewriting-functions»	(to "ldb-rewriting-functions")
# «.ldbenv»			(to "ldbenv")
# «.eepitch-gdb»		(to "eepitch-gdb")
# «.testing-intro.lua»		(to "testing-intro.lua")
# «.wish-event-loop»		(to "wish-event-loop")
# «.iup-event-loop»		(to "iup-event-loop")
# «.peek.lua»			(to "peek.lua")
# «.peek.lua:diagrams»		(to "peek.lua:diagrams")
# «.peek.lua:doc»		(to "peek.lua:doc")
# «.debugging-wish»		(to "debugging-wish")




#####
#
# Links para partes da correspondência com o Scuri
# 2007jul03
#
#####

# «correspondencia»  (to ".correspondencia")
# (code-c-d "davinciprivate"      "~/DAVINCI/")
# (code-c-d "davincimails200706"  "~/DAVINCI/mails-2007jun.html")
# (code-ps        "davinciedital" "~/DAVINCI/EditalUniversal_daVinci.pdf")
# (code-pdftotext "davinciedital" "~/DAVINCI/EditalUniversal_daVinci.pdf")
# (find-davinciprivatefile "")
# (find-davincieditalpage 1)
# (find-davincieditaltext)
# (find-davincimails200706w3m "" "tarefa" "console")
# (find-davincimails200706w3m "" "tarefa" "editor")
# (find-davincimails200706w3m "" "tarefa" "debug")
# (find-davincimails200706w3m "" "tarefa" "gerenciador de projetos")




#####
#
# Cronograma inicial
# 2007jul03
#
#####

# «cronograma-inicial»  (to ".cronograma-inicial")

Horas
    Descrição

( ) Ldb
(1)   Baixar versão atual
( )   Preparar exemplos de uso (pra usar com eepitch), incluindo:
(2)     Um que liste os nomes das funções no call stack
(2)     Um que liste variáveis locais numa dessas funções
(1)     Um que liste upvalues de uma dessas funções
( )     Um que sete breakpoints
( )     Um com single-stepping (dois modos: em terminologia do GDB, step/next) 
(4)   Ver como o Rici está transformando closures em nomes de funções
(2)   Limpar e documentar isso: (find-angg "LUA/lua50init.lua" "preparef2n")
(1)   Localizar o código do Ldb que converte frame height <-> marker + offset

( ) Lua: aprender o que falta da parte em C
(2)   Que estruturas representam (open/closed) upvalues?
(4)   Completar o diagrama em (find-es "lua-intro" "bytecode:captures")
( )   Fazer uma versão gráfica desse diagrama (com inkscape ou xfig)
(4)   Entender as funções que acessam o stack com índices positivos e negativos
(4)   Descobrir quais são as estruturas do pool de strings
(4)   Ressucitar o (find-angg "LUA/lua50init.lua" "load_PP")
(4)   Comparar com (find-pilw3m "24.2.3.html" "stackDump")
(4)   Ver o que o Rici fez de correspondente no ldb
(2)   Encontrar o código de GC que varre as posições válidas do stack
(4)   Descobrir como o código do traceback dá nomes para closures/funções

( ) Lua: aprender o que falta da debug lib
(4)   Rodar os exemplos do PiL

(4) Ler a documentação do TecMake
(1)   Descobrir que valores dar pras environment vars que ele usa
(3)   Testar esses valores e encontrar um subset mínimo
(2)   Descobrir como rodá-lo em modo verboso
(4)   Tentar compilar o IUP com ele (dessa vez a sério)
( )   Tentar compilar o LuaCmd com ele (não, isso ainda não)

( ) Binários do IUP e do LuaCmd
(1)   Baixar
(4)   Tentar rodar o IUP    a partir dos binários
(4)   Tentar rodar o LuaCmd a partir dos binários
(2)   IUP:    procurar (e rodar) exemplos de uso na documentação
(2)   LuaCmd: procurar (e rodar) exemplos de uso na documentação

(0) Conseguir o endereço de MSN do Scuri

(1) Descobrir quem são as pessoas com quem eu devo falar na PUC
(1)   Mandar e-mail pra elas sobre compilar o IUP com o TecMake -
(0)   Tentar marcar um horário
( )   Descobrir o e-mail do Alexandre que ficou interessado no dednat4

( ) Passar na PUC
( )   Conhecer as pessoas do TecGraf e do IUP
( )   Imprimir o artigo sobre a VM e encaderná-lo (espiral)
( )   Pedir ajuda com o TecMake
( )   Perguntar pro Sérgio (?) mais sobre o compilador de Lua em Lua

(0) Aprender SciTe (parte em Lua - a partir do SciTe)
(6)   Ler os docs no luawiki
(8)   Testar os exemplos
(0)   Descobrir como chamar named commands pelo nome (como M-x no emacs)
(0)   Descobrir como criar named commands novos

( ) Aprender SciTe e Scintilla (parte social)
(2)   Descobrir onde estão as mailing lists
(1)   Me inscrever nelas
(2)   Baixar arquivos das mailing lists
(2)   Pôr um link pra minha página sobre o davinci no luawiki

( ) Bindings de Lua pro Scintilla
( )   Descobrir como o Kein-Hong Man fez os bindings para SciTe
( )   Descobrir se ele fez algo pro Scintilla também

(4) Criar uma página sobre o DaVinci
(0)   Ligá-la com a minha página de Lua (luaforth.html)
(0)   Ligá-la com os e-scripts (davinci.e, lua5.e, lua-intro.e)
(0)   Ligá-la com as páginas do luawiki
  
( ) Aprender SciTe (parte em C)
(0)   Compilar a partir das fontes Debian (ok)
(3)   Compilar o Scintilla e o Scite a partir das fontes upstream
(0)   Verificar se o módulo Lua está habilitado por default no Debian
(0)   Verificar se o módulo Lua está habilitado por default no upstream
(1)   Localizar os bindings
(1)   Escolher um binding pouco usado
(1)   Mudar o código dele - incluir um printf("Hello\n")
(1)   Confirmar que isso funciona (e que o stdout funciona)
( )   Descobrir como criar um named command novo (em C)
( )   Descobrir como chamar named commands pelo nome (como M-x no emacs)
( )   Fazer um named command que imprima "Hello"
( )   Descobrir como usar a região
( )   Fazer um named command que imprima a região no stdout

( ) Documentação do eev
(1)   Implementar um truque novo no blogme: [_ texto]
(2)   Htmlizar o roadmap (que está em papel).
( )   Ver se com o roadmap já dá pras pessoas (algumas) decifrarem os e-scripts
( )   Fazer uma documentação (mínima) para o eepitch:
(1)     screenshot de verdade
(1)     ascii screenshot
(2)     incluir no eev-article.html
(1)   Consertar os docs sobre M-k e M-K
(1)   Consertar os links sobre M-k e M-K aqui: (find-efunctiondescr 'eev-mode)
(2)   Htmlizar o (find-efunctiondescr 'eev-mode)

( ) GDB (no Emacs)
(2)   Fazer um eepitch-gdb, para mandar comandos para o gdb
(2)   Encontrar um setting de 3 janelas que funcione com o eepitch
(2)   Adaptar os exemplos envolvendo GDB e Lua para o eepitch
(1)   Fazer screenshots e ascii screenshots

( ) TCmd
(1)   Terminar o código: (find-es "tcl" "text-widget")
(0)   Exportar o arquivo para a angg (como ~/TCL/tcmd.tcl)
( )   Localizar o screenshot do SciTe rodando algo como um TCmd em Python
(1)   Implementar a divisão em janelas (file e vars)
(1)   Descobrir como marcar uma linha em vermelho (com o tag currentline)
(0)   Descobrir como remover todos os overlays com o tag currentline
(1)   Implementar comando: setfile
(0)   Implementar comando: setvars
(1)   Implementar comando: setline
(1)   Implementar uma função "tcmd" em Lua (writefile + system/getoutput)


(setq last-kbd-macro (kbd "<delete> <right> C-k <delete> SPC"))
(+
  1   2 2 1     4 2 1 
  2 4   4 4 4 4 4 2 4 
  4 
4 1 3 2 4   
  1 4 4 2 2 
0 
1 1 0   
0 6 8 0 0 
  2 1 2 2 
4 0 0 0   
  0 3 0 0 1 1 1 1           
  1 2     1 1 2 1 1 2 
  2 2 2 1 
  1 0   1 1 0 1 0 1 1 
)
;; -> 134





http://www.tecgraf.puc-rio.br/iup/en/guide.html#buildlib




#####
#
# tcmd.tcl
# 2007jul04
#
#####

# «tcmd.tcl»  (to ".tcmd.tcl")
# (find-angg "DAVINCI/tcmd.tcl")
# (find-angg "TH/davinci.blogme")

# http://angg.twu.net/DAVINCI/tcmd.tcl
# http://angg.twu.net/DAVINCI/tcmd.tcl.html
# http://angg.twu.net/DAVINCI/tcmd-1.png
# http://www.tecgraf.puc-rio.br/luacmd/debug.gif
# http://www.tecgraf.puc-rio.br/luacmd/





#####
#
# TCmd: code to take a screenshot
# 2007jul04
#
#####

# «tcmd-screenshot»  (to ".tcmd-screenshot")
# (set-face-bold-p 'comint-highlight-input nil)
# (set-face-bold-p 'comint-highlight-input t)

* (eepitch-shell)
* (eepitch-kill)
* (eepitch-shell)
cd

~/DAVINCI/tcmd.tcl &

echo setfile ~/usrc/lua-5.1.2/test/fib.lua > /tmp/ee.tcmd.tcl
kill -USR2 $(cat /tmp/ee.tcmd.pid)
echo -e 'setvars "n = 4\nN = 1"' > /tmp/ee.tcmd.tcl
kill -USR2 $(cat /tmp/ee.tcmd.pid)
echo setline 5 > /tmp/ee.tcmd.tcl
kill -USR2 $(cat /tmp/ee.tcmd.pid)
echo setline 6 > /tmp/ee.tcmd.tcl
kill -USR2 $(cat /tmp/ee.tcmd.pid)

kill $(cat /tmp/ee.tcmd.pid)



# Upload:
Scp ~/DAVINCI/tcmd-1.png [email protected]:slow_html/DAVINCI/





#####
#
# ldb - rewriting some functions
# 2007jul10
#
#####

# «ldb-rewriting-functions»  (to ".ldb-rewriting-functions")
-- (find-ldbfile "ldb.lua" "function statemeta.proxystack(state)")
-- (find-ldbfile "ldb.lua" "function statemeta:makecontext(env)")
-- (find-ldbfile "ldb.lua" "function makeinfovar(info, sentinel, erroffset)")
-- (find-ldbfile "ldb.lua" "function State(sentinel, env)")


-- (find-ldbfile "ldb.lua" "function statemeta.proxystack(state)")
-- (find-ldbfile "ldb.lua" "function Memoize(func)")

-- a part of rici's "Memoize", rewritten
memoize_meta = function (func)
    return { __index = function(tbl, key)
          local value = func(key); tbl[key] = value; return value
        end
    }
  end

-- a part of rici's "statemeta.proxystack", rewritten
stackframe_meta = function (state, stack)
    return {
      __add = function (self, offset)
          if type(offset) == "number" then
            return stack[stack[self] + offset]
          end
        end,
      __sub = function (self, offset)
          if type(offset) == "number" then
            return stack[stack[self] - offset]
          end
        end,
      __index = function (self, key)
          local info = state[stack[self]]
          if infokeys[key] then return info[key]
          elseif infofuncs[key] then return infofuncs[key](info)
          else return info.var[key]
          end
        end,
      __newindex = function (self, key, val)
          local info = state[stack[self]]
          if infokeys[key] or infofuncs[key] then
            error(key.." cannot be modified")
          else info.var[key] = val
          end
        end
    }
  end

-- the main part of rici's "statemeta.proxystack", rewritten
statemeta.proxystack = function (state)
    local stack = {}
    setmetatable(stack, memoize_meta(function (level)
        if type(level) == "number" and state[level] then
          local rv = setmetatable({}, stackframe_meta(state, stack))
          stack[rv] = level
          return rv
        end
      end)
    return stack
  end


-- My first attempt to rewrite rici's "statemeta.proxystack". Delete this.
statemeta.proxystack = function (state)
    local stack -- defined below
    local function StackFrame()
      return setmetatable({}, {
        __add = function (self, offset)
            if type(offset) == "number" then
              return stack[stack[self] + offset]
            end
          end,
        __sub = function (self, offset)
            if type(offset) == "number" then
              return stack[stack[self] - offset]
            end
          end,
        __index = function (self, key)
            local info = state[stack[self]]
            if infokeys[key] then return info[key]
            elseif infofuncs[key] then return infofuncs[key](info)
            else return info.var[key]
            end
          end,
        __newindex = function (self, key, val)
            local info = state[stack[self]]
            if infokeys[key] or infofuncs[key] then
              error(key.." cannot be modified")
            else info.var[key] = val
            end
          end
        })
    stack = Memoize(function (level)
      if type(level) == "number" and state[level] then
        local rv = setmetatable({}, stackframe_meta(state, stack))
        stack[rv] = level
        return rv
      end
    end)
    return stack
  end


-- (find-pilfile "")
-- (find-pilgrep "grep -nH -e emoize *")
-- (find-pilw3m "17.1.html")
-- (find-lua51file "")




#####
#
# ldb - making it use an environment (ldbenv) and no locals
# 2007jul16
#
#####

# «ldbenv»  (to ".ldbenv")
# (find-ldbfile "")
# (find-ldbfile "ldb.lua")
# (find-ldbfile "ldb.lua" "return env.ldb")

We should do "return env.ldb, env" - or something like that.
Test this:

  ldbenv = setmetatable({ }, { __index = _G })
  setfenv(ldbenv)

Then define some "global" functions that call one another and some
"real" globals, like "print", that are inherited through __index.








#####
#
# Sections about eepitch and GUD for the eev-article
# 2007jul12
#
#####

# «eepitch-gdb»  (to ".eepitch-gdb")
# http://angg.twu.net/eev-article.html
# (find-eevarticlesection "channels")
# (find-eevarticlesection "eepitch")
# (find-angg ".emacs" "eepitch-gdb")

(This is a draft, full of errors, describing some code that does not
yet exist (ee-tbr), etc. Also, I don't know Rubikitch's real name, so
I used a random Japanese name...)



Sending lines to processes running in Emacs buffers: eepitch
============================================================

Emacs can run external programs interactively inside buffers; in the
screenshot in Figure 5 there's a shell running in the buffer "*shell*"
in the lower window. Technically, what is going on is much more
complex than what we described in the previous section. The shell runs
in a pseudo-terminal (pty), but ptys are usually associated to
rectangular grids of characters with a definite width and height,
while in an Emacs buffer the width of each line, and the total number
of lines,are only limited by memory constraints. Many interactive
programs expect their input to come through their more-or-less
minimalistic line editors, that may try to send to the terminal
commands like "clear the screen" or "go to column x at line y"; how
should these things be handled in a shell buffer? Also, the user can
move freely in a shell buffer, and edit its contents as text, but in
some situations the user will hit the "Return" key, Emacs should
select a part of the current line - except maybe some initial
characters that are seen as a prompt - and send that to the shell
process, as if the user had typed exactly that; so, Emacs takes over
the line editor of the shell process completely. The translation
between character sequences going through the pty and buffer-editing
functions is very tricky, full of non-obvious design choices, and even
though it has been around for more than  20 years it still has some
(inevitable) quirks.

I almost never used shell buffers, so I found the following idea, by
OGAMI Itto, very surprising when he sent it to the eev mailing list in
2005.

    (Figure 5 will be a screenshot that I haven't taken yet.)
    (It will be simpler than the scvreenshot from Fig. 6,
     that is this: http://angg.twu.net/IMAGES/eepitch-gdb.png )

The current window, above in Figure 5, is editing an e-script, and the
other window shows a shell buffer - that we will refer to as the
"target buffer". When the user types a certain key - by default F8 -
the current line is sent to the target buffer, and the point is moved
down to the next line; pressing F8 n times in sequence sendsn lines,
one by one.

One detail: "sending a line" means inserting its contents - except the
newline - at the current position in the target buffer, and then
running there the action associated to the "Return" key. "Return" is
almost always a special key, bound to different actions in different
major modes, so just inserting a newline would not work. [wouldn't
simulate what happens when a user types "Return"].

(anchor here)

Note that, in a sense, the action of F8 is much more complex than that
of F9, described in the last section; but user might perceive F8 as
being much simpler, as there are no external programs involved
(Expect, eegchannel, xterm), and no setup hassles - all the machinery
to make Emacs buffers invoke external processes in buffers pretending
to be terminals ("comint mode") comes built-in with Emacs since the
early 1980s.

Ogami's idea also included three "bonus features": window setup,
reconstruction of the target buffer, and star-escapes. In the default
Emacs setting some commands - M-x shell between them - might split the
current Emacs frame in two windows; none of eev's hyperlink functions
do that, and I have always felt that it is more naturalto use eev with
a setting (pop-up-windows set to nil) that disables window splittings
except when explicitly requested by the user. Anyway: M-x shell
ensures that a "*shell*" buffer is visible in a window, and that a
shell process is running in it; this setup code for F8,

  (eepitch '(shell))

splits the window (if the frame has just one window), and runs
`(shell)' in the other window - with the right defaults - to force
that window to display a shell buffer with a live shell process
running in it; it also sets a variable, eepitch-target-buffer, to that
buffer, so that the next `F8's will have a definite buffer to send
lines too - as target buffers need not necessarily be shell buffers.

As for the star-escapes, it's the same idea as with F9: when a line
starts with a red star glyph, running F8 on it executes everything on
it - after the red star - as Lisp, and if there are no errors the
point is moved down. So lines starting with a red star can be used to
set up an eepitch target, to switch to another target, or to do
special actions - like killing a certain target so that it will be
reconstructed anew by the next F8. Note that once that we recognize
that a region of an e-script is to be used by eepitch there is only
one key to be used to "run" each of its lines, both the ones with red
stars and the ones without: F8. However, as with F9, the user must
know what to expect after each step. A badly-written e-script for
eepitch may try, for example, to "cd" into a directory that doesn not
exist, and if the next line is, say, "tar -xvzf $S/http/foo/bar.tgz"
then it will try to unpack a tarball into the wrong place, creating a
big mess.


Using eepitch to control unprepared shells
------------------------------------------

  # (find-eevfile "eev.el" "EEVDIR")
  # (find-eevfile "eev.el")

As we have seen in section 4, M-x eev sends the region to a "prepared
shell"; if the shell has the right settings for the environment
variables $EEVTMPDIR and $EE, and if it has the shell function `ee',
then running `ee' in the shell "sources" the temporary script -
corresponding to the regin - in verbose mode. Well, if Emacs loads
eev.el and the environment variables $EEVDIR, $EEVTMPDIR and $EE are
not set, then they are set, respectively, to the directory where
eev.el was read from, to the subdirectory of it given by $EEVDIR/tmp,
and to the file $EEVTMPDIR/ee.sh. Processes started from Emacs inherit
these environment variables, so a shell buffer created by running F8
on these two lines,

  * (eepitch-shell)
  function ee () { set -v; . $EE; set +v; }

will be running a prepared shell. Such buffers can be used to let
users understand better how prepared shells work, and decide if they
want to patch their initialization files for the shell (see
eev-rctool) so that their shells will be "prepared" by default.

[IT (Note: I haven't yet played much with this idea - discuss running
eev-rctool on such shells (and a function that creates a buffer with
an e-script for that), and loading psne.sh from an unprepared shell).]


Controlling debuggers with eepitch
----------------------------------

# (find-node "(emacs)Debuggers")
# (find-node "(gdb)Top")

On *NIX it is common to keep debuggers separated into two parts: a
back-end, with a simple textual interface, and a front-end, that
controls the back-end via its textual interface but presents a better
interface, showing source files and breakpoints in a nice way, etc.
The GNU Debugger, GDB, is a back-end, and it can be used to debug and
single-step several compiled languages; the "Grand Unified Debugger"
mode of Emacs, a.k.a. GUD, is a front-end for GDB and other back-ends.

Usually, GUD splits an Emacs frame into two windows, one for
interaction with GDB (or other back-end, but let's say just "GDB" for
simplicity), and another one for displaying the source file where the
execution is. Some of the output of GDB - lines meaning, e.g., "we're
at the source file foo.c, at line 25" - are filtered by GUD and are
not shown in the GUD buffer; and the user can press special key
sequences on source files that generate commands to GDB - like, "set a
breakpoint on this line".

In order to control GDB with eepitch we need a window setting with
three windows, like in the screenshot in Figure 6.

     http://angg.twu.net/IMAGES/eepitch-gdb.png
     ^ Figure 6 will be this

The way to set up that does not integrate very well with the
"standard" eepitch at this moment, but that should come with time.



E-scripting GDB with eepitch
----------------------------

  # (find-node "(gdb)Set Breaks" "`tbreak ARGS'")
  # (find-node "(elisp)The Buffer List")

We can use elisp hyperlinks to point to specific lines in source files
- and we can combine these hyperlinks with the code to set up
breakpoints, in two ways.

  *;(find-lua51file "src/lvm.c" "case OP_CLOSE:" 1)
  * (find-lua51file "src/lvm.c" "case OP_CLOSE:" 1 '(ee-tbr))

The first line above contains an elisp hyperlink to a line in the
source of Lua. Actually, it points to the code for an opcode in Lua's
virtual machine that most people find rather mysterious. As the line
starts with `*;', an F8 on it executes a Lisp comment - i.e., does
nothing - and moves down; only a `M-e' (or a `C-e C-x C-e') on that
line would follow the hyperlink.

The second line, when executed with F8, would go to that line in the
source, then run `(ee-tbr)' there; ee-tbr invokes gud-tbr to set a
temporary breakpoint on that source line (i.e., one that is disabled
when the execution stops there for the first time), and then buries
the buffer - the one with "lmv.c" - like a `M-K' would do; the effect
is that the buffer in that window - the top-left window in a situation
like in Figure 6 - does not change, it will still show the e-script.

A variation on this is to wrap the hyperlink in an ee-tbr:

  * ;        (find-lua51file "src/lvm.c" "case OP_CLOSE:" 1)
  * (ee-tbr '(find-lua51file "src/lvm.c" "case OP_CLOSE:" 1))

When ee-tbr is called with an argument it evaluated the argument
inside a save-excursion, and sets a breakpoint there; the effect is
almost the same as the previous case, but this does not change the
order of the buffers in the buffer list.


Two little languages for debugging
----------------------------------

E-scripts for eepitch and GDB can be used to bring programs to a
certain point (and to inspect their data structures there; we will
have more to say about this in the next section). In a sense, as in
[Bentley], these e-scripts are written in a language that describes
states of running programs - and they can be executed step by step.

These e-scripts, being executable, can be used in e-mails to
communicate particular states of programs - say, where a certain bug
occurs. Unfortunately, they are too fragile and may cease working
after minimal changes in the program, and they are almost impossible
to read...

However, the screenshot in Figure 5 suggests another language for
communicating controlling programs with GDB: the contents of the
"*gud*" buffer. After removing some excess verbosity by hand we get
something that is readable enough if included in e-mails - and to
extract the original commands from that we just have to discard the
lines that don't start with "(gdb)", then remove the "(gdb)" prompts.
As for the hyperlinks with `(ee-tbr)', they may need to be copied to
the GUD buffer, and not filtered out; we still need to experiment with
different ways to do that to be able to choose one.


Inspecting data in running programs
-----------------------------------

Almost anyone who has learned a bit of Lisp should be familiar with
this kind of box diagrams. After running

  (setq x '(5 "ab"))
  (setq y (list x x '(5 "ab")))

the value of y can be represented by:

   ___ ___	 ___ ___             ___ ___	
  |___|___| --> |___|___| --------> |___|___| --> nil
    | ___________/                    |
    |/                                |
   _v_ ___	 ___ ___             _v_ ___	   ___ ___	 
  |___|___| --> |___|___| --> nil   |___|___| --> |___|___| --> nil
    |             |                   |             |
    v             v                   v             v
    5            "ab"                 5            "ab"               

This representation is verynice - it omits lots of details that are
usually irrelevant, like the address in the memory of each cons, and
the exact names of each struct in C and their fields. But sometimes we
need to understand the implementation in C, and a more complete
diagram would be convenient. At least, we would like to know how to
get, in the C source of Emacs, from the address of the leftmost cons
in the top line to the rightmost "ab" in the bottom line - but how do
we express following the "cdr" arrows, the "car" arrows, and
extracting the contents of a string object in elisp, One solution is
to use GDB, and e-scripts for it:

    ...

A "complete diagram" corresponding to the one above, whatever the
format that we choose to draw it, should include some information
explaining that "cdr" arrows correspond to "->cdr", "car" arrows
correspond to ..., and each string object corresponds to another kind
of box different from the cons boxes; to get to the C string stored in
an elisp string object we should examine its "foo" field, i.e., do a
"->foo".

Obviously, this same idea applies also to other programs with complex
data structures - and for some programs we may even have fancier ways
to explore their data structures; for example, in a graphic toolkit it
might be possible to change the background of a button to orange from
GDB.





#####
#
# Testing intro.lua
# 2007jul19
#
#####

# «testing-intro.lua»  (to ".testing-intro.lua")
# (find-angg "DAVINCI/intro.lua")
# (find-angg "DAVINCI/tcmd.tcl")

# Install Tcl/Tk and Expect.
# (Packages are available for most distributions).

# Download and compile SciTe 1.74 (upstream).
# Install the dependencies; get the list from:
#   http://ftp.debian.org/debian/pool/main/s/scite/scite_1.71-1.dsc
# (find-es "davinci" "scite-upstream")

mkdir ~/DAVINCI/
cd    ~/DAVINCI/
wget http://angg.twu.net/DAVINCI/intro.lua
wget http://angg.twu.net/DAVINCI/tcmd.tcl
wget http://angg.twu.net/LUA/lua50init.lua


* (eepitch-shell)
# (find-angg "DAVINCI/intro.lua")
cd ~/DAVINCI/
~/usrc/scite174/scite/bin/SciTE intro.lua &


* (eepitch-shell)
kill $(cat /tmp/ee.tcmd.pid)
* (eepitch-kill)


* (eepitch-shell)
cd ~/DAVINCI/
./tcmd.tcl &
~/usrc/scite174/scite/bin/SciTE intro.lua &









# (find-angg "DAVINCI/tcmd.tcl")
kill $(cat /tmp/ee.tcmd.pid)
cd ~/DAVINCI/
./tcmd.tcl &




* (eepitch-shell)
cd ~/DAVINCI/
cp -v ~/usrc/lua-5.1.2/test/fib.lua .
kill $(cat /tmp/ee.tcmd.pid)
~/DAVINCI/tcmd.tcl &

* (eepitch-lua51)
tcmd = function (tclcode)
    writefile("/tmp/ee.tcmd.tcl", tclcode)
    local output = getoutput("kill -USR2 $(cat /tmp/ee.tcmd.pid)")
    if output ~= "" then error(output) end
  end

tcmd("setfile fib.lua")
tcmd('setvars "n = 4\nN = 1"')
tcmd("setline 5")
tcmd("setline 6")


# (find-scitegrep "grep -niH -e '\"editor\"' $(find *)")
# (find-scitefile "scite/src/LuaExtension.cxx" "\"editor\"")






#####
#
# Scite ST and friends
# 2007jul24
#
#####

http://caladbolg.net/scite.php
http://caladbolg.net/scite/images/pm.png
http://caladbolg.net/scite_snippets.php
http://caladbolg.net/scite_st.php
http://scite-tools.googlecode.com/svn/trunk/scripts/doc/snippets_doc.txt
http://scitetools.wordpress.com/




#####
#
# LuaEclipse and RemDebug
# 2007jul24
#
#####

http://lists.luaforge.net/pipermail/luaeclipse-developers/
http://www.keplerproject.org/remdebug/
http://lua-users.org/lists/lua-l/2005-09/msg00602.html
http://lua-users.org/lists/lua-l/2006-06/msg00426.html
http://lists.luaforge.net/pipermail/kepler-project/2007-July/000997.html




#####
#
# Wish's event loop
# 2007jul26
#
#####

# «wish-event-loop»  (to ".wish-event-loop")
# (find-es "tcl" "wish-event-loop")
# (find-es "iup" "iup-event-loop")




#####
#
# IUP's event loop
# 2007jul30
#
#####

# «iup-event-loop»  (to ".iup-event-loop")
# (find-fline "~/LOGS/2007jul30.scuri")
# (find-iupgrep "grep -nH -e MainLoop $(find *)")
# (find-iupfile "srclua5/iuplua_api.c" "static int MainLoop(lua_State *L)")
# (find-iupfile "src/mot/motif.c" "int IupMainLoop (void)")




#####
#
# Scite/Scintilla's event loop
# 2007aug08
#
#####

# (find-scites "")




#####
#
# peek.lua: notes
# 2007jul30
#
#####

# «peek.lua»  (to ".peek.lua")

PrimitiveType("int",          4)
PrimitiveType("unsignedint",  4)
PrimitiveType("char",         1)
PrimitiveType("unsignedchar", 1)

PointerTo (nil,           "void*")
PointerTo ("char",        "char*")
PointerTo ("char*",       "char**")
ArrayOf   ("char*",       "char*[7]",    7)
ArrayOf   ("char*[7]",    "char*[7][4]", 4)
PointerTo ("char*[7][4]", "char*[7][4]*")
StructOf  ("int i   char c", "struct:ic")
TypedefTo ("struct:ic", "ic")

ArrayOf("char", "char[12]", 12)

-- (gdb) ptype month
-- type = char *[4][7]
-- (gdb) ptype &month
-- type = char *(*)[4][7]
-- (gdb) p     month
-- $1 = {{0x8048468 "Aa", 0x804846b "Bb", 0x804846e "Cc", 0x8048471 "Dd",
--        0x8048474 "Ee", 0x8048477 "Ff", 0x804847a "Gg"},
--       {0x804847d "Hh", 0x8048480 "Ii", 0x8048483 "Jj", 0x8048486 "Kk",
--        0x8048489 "Ll", 0x804848c "Mm", 0x804848f "Nn"},
--       {0x8048492 "Oo", 0x8048495 "Pp", 0x8048498 "Qq", 0x804849b "Rr",
--        0x804849e "Ss", 0x80484a1 "Tt", 0x80484a4 "Uu"},
--       {0x80484a7 "Vv", 0x80484aa "Ww", 0x80484ad "Xx", 0x80484b0 "Yy",
--        0x80484b3 "Zz", 0x80484b6 ";:", 0x80484b9 ",."}}
-- (gdb) p     &month
-- $2 = (char *(*)[4][7]) 0x8049600

-- Methods:
--   :star()
--   :plus(k)
--   :box(k)
--   :amp()
--   :field(fieldname)
--   :arrow(fieldname)
--   :value()
--   :sizeof()

-- int i;
-- i === {addr=1000000, type="int", value="\00\00\00\42"}

ctype_meta = { }
CType = function (type, tbl)
    tbl[type] = type
    ctypes[type] = setmetatable(tbl, ctype_meta)
  end

PrimitiveType = function (type, sizeof)
    CType(type, { kind = "prim", sizeof = sizeof })
  end
PointerTo = function (base, type)
    CType(type, { kind = "*", sizeof = 4, star = base })
  end
ArrayOf = function (base, type, n)
    local basesizeof = ctypes[base].sizeof
    CType(type, { kind = "[]", sizeof = n and n * basesizeof, star = base })
  end

PrimitiveType("unsignedint",  4)
PrimitiveType("char",         1)
PrimitiveType("unsignedchar", 1)
PointerTo (nil,           "void*")
PointerTo ("char",        "char*")
PointerTo ("char*",       "char**")
ArrayOf   ("char*",       "char*[7]",    7)
ArrayOf   ("char*[7]",    "char*[7][4]", 4)
PointerTo ("char*[7][4]", "char*[7][4]*")
-- StructOf  ("int i   char c", "struct:ic")
-- TypedefTo ("struct:ic", "ic")

ctype_meta.star = function(

pointer_star = function (cobj)


-- {addr=2000, type="int*"}:star()   = {addr=peekptr(2000), type="int"}
-- {addr=2000, type="int[5]"}:star() = {addr=2000, type="int"}
-- {addr=2000, type="int[]"}:star()  = {addr=2000, type="int"}

pointer_meta = {
  sizeof = function (cobj) return 4 end
  star   = function (cobj)
      return Cobj {addr = peekptr(cobj.addr), type = cobj:type().star}
}

    


c4tonumber = function (c4)
    local bt = string.byte
    local a, b, c, d = bt(c4, 1), bt(c4, 2), bt(c4, 3), bt(c4, 4)
    return a + 256 * (b + 256 * (c + 256 * (d)))
  end
peekptr = function (addr) return c4tonumber(peek(addr, 4)) end


* (eepitch-lua51)
= string.byte(string.char(200, 233), 2)





#####
#
# peek.lua: diagrams (the oldest ones)
# 2007aug01
#
#####

# «peek.lua:diagrams»  (to ".peek.lua:diagrams")
#*
cd /tmp/
cat > charptr.c <<'%%%'
char c='@';
char *cp;
char ca[]="@ABCD";
char ca5[5];
int main () {
  return 0;
}
%%%
gcc -g -Wall -o charptr charptr.c

#*
;; (find-efunction 'eepitch-gdb-lua-kill)
(defun eepitch-gdb-charptr ()
  (eepitch-gdb "*gud-charptr*" "gdb --annotate=3 /tmp/charptr"))
(defun eepitch-gdb-charptr-kill ()
  (eepitch-gdb-kill "*gud-charptr*"))

* (eepitch-gdb-charptr-kill)
* (eepitch-gdb-charptr)
ptype ca5
ptype   *ca5
ptype   ca5+0
ptype c
ptype   &c
ptype cp
ptype   *cp
ptype ca
ptype   ca+0
                             +------------------+
			     |   addr=1000      |
			     |   type="char[5]" |
			     |  value="@ABCD"   |
		       	 +-| | sizeof=5         |
		        /    |   star="char"    |
		       /     |    amp=          | |---+
		    * /	     +------------------+      \ weaken
		     / 	       	      |	  	      	\
		    /  	       	      |	+0	      	 \
		   v   	     	      v	  	       	  v
+----------------+	     +-------------------+          +------------------+
|   addr=1000    |	     |   addr=nil        |          |   addr=1000      |
|   type="char"  |     &     |   type="char*"    |   +0     |   type="char[]"  |
|  value="@"     | |-------> |  value=toc4(1000) |  deref   |  value=nil       |
| sizeof=1       | <-------| | sizeof=4          | <------| | sizeof=nil       |
|   star=nil     |     *     |   star="char"     |          |   star="char"    |
|    amp="char*" |           |    amp="char**"   |          |    amp="char[]*"?|
+----------------+           +-------------------+          +------------------+
		   ^   	       	      ^
		    \  	     	      |	+0
		     \	     	      -
		    * \	     +-------------------+
		       \     |   addr=2000       |
			\    |   type="char*"    |
			 +-| |  value=toc4(1000) |
			     | sizeof=4          |
			     |   star="char"     |
			     |    amp="char**"   |
			     +-------------------+





#####
#
# peek.lua - documentation
# 2007aug02
#
#####

# «peek.lua:doc»  (to ".peek.lua:doc")

Inspirations:
  PiL:     (find-pilw3m "25.3.html" "A Generic Call Function")
  cdecl:   (find-es "anatocc" "cdecl")
  cinvoke: (find-es "lua5" "cinvoke")
  evil.rb: (find-es "ruby" "evil.rb")
  gdb:     (find-es "gdb" "C-types")
  swig:    (find-es "swig" "C-types-as-strings")



Primitive types
===============
"char", "int", etc are primitive types, with sizeofs 1, 4, etc.

Names of types and "TD" ("type data")
=====================================
For each type name "t" the table TD has an entry describing its "type
data" - its sizeof, its name, how it reacts to the ampersand and star
operators, etc.

The table TD lets us refer to types by their names.

Array types
===========
If "t" is a type and "n" is a non-negative integer, then "t[n]" is a
type with sizeof = n * TD["t"].sizeof.

When "t" doesn't have a sizeof we can't create a type "t[n]".

If "t" is a type with a sizeof then "t[]" is a type without a sizeof.

When "t" doesn't have a sizeof then we can't create a type "t[]". We
can't create types like "char[5][][2]" or "char[5][][]".

Pointer types
=============
If "t" is a type then "t*" is a type with sizeof 4.

A type like "char[5][]**[2]" is valid.

"void" is a special primitive type with no sizeof.

"void*" is a type with sizeof 4.

Arrays and pointers in C and in peek.lua
========================================
A declaration in C like

  char *(*mptr)[4][7];

corresponds to:

  char *(((*mptr)[4])[7]);

If we write the "[...]"s at the left this becomes:

  char *([7]([4](*mptr)));

This is the order that we will use for type names in peek.lua; it lets
us get rid of the parentheses.

In peek.lua, after a declaration corresponding to the one above, the
variable

  "mptr" would have type "char*[7][4]*";
  "*mptr" would have type "char*[7][4]",
  "[3]*mptr" would have type "char*[7]",
  "[6][3]*mptr" would have type "char*", and
  "*[6][3]*mptr" would have type "char".

Struct types
============

If "t", "u" and "v" are types with sizeofs, then a declaration like
this in C,

  struct s {
    t a;
    u b;
    v c;
  };

corresponds to defining these types in TD:

  "struct:s"
  "struct{t:a;u:b;v:c;}"

The TD entry for "struct:s" points to the entry for
"struct{t:a;u:b;v:c;}".

When we omit the name of the struct in C, as in

  struct {
    t a;
    u b;
    v c;
  };

then this corresponds to having just the entry 

  "struct{t:a;u:b;v:c;}"

in TD; the entry "struct:s" is not created.

The sizeof of the resulting "struct" types is the sum of the sizeofs
of the fields of the struct.

We can only create a struct type when all the fields have sizeofs.

We can create a struct with field of type "t*" (that has sizeof = 4)
even if the type "t" has no sizeof, or if its sizeof is unknown at the
moment of the creation of the struct type.

Union types
===========
"union" types are like "struct" types, with "union" replacing "struct"
everywhere.

The sizeof of a "union" type is the maximum of the sizeofs of its
fields.

peek
====
We will only need to define one Lua function in C: peek. "peek(addr,
len)" returns the result of reading len bytes from the memory,
starting from the address addr, as a Lua string len bytes long.

The definition of peek is as simple as possible, and it will happily
segfault when given a bad addr.

C objects
=========
If "t" is a type with a sizeof, the a "C object with type "t" in
memory" can be seen as a triple: {addr=a, type="t", value=v}, where a
is an integer - the address where the object starts in the memory -
and v is its "value", as a sequence of bytes (a string).

If "t" is a type without a sizeof - for example, "char[]" - then we
can represent a C object of type "t" in memory as just a pair {addr=a,
type="t"}.

We can represent an "immediate object" of type "t" - for example, an
integer that is the result of an expression - as a pair {type="t",
value=v}, with v being a string sizeof "t" bytes long.

We can't have an immediate object of type "t" when "t" doesn't have a
sizeof: it wouldn't have an addr, and it couldn't have a value.

A possible notation for C objects: (type) value at addr. Examples:

  (char[5]) {'@', 'A', 'B', 'C', 0} at 1000
  (char[5]) $4041424300 at 1000
  (char) '@' at 1000
  (char) $40 at 1000
  (char*) 1000 at 2000
  (char*) 1000
  (char[]) at 1000

Function types
==============

Consider the following program in C:

  char a[] = {'@', 'A', 'B', 'C', 0};
  char f(int i) {
    return a[i];
  }
  char (*fp)(int i) = f;

The linker sess "a" as being a certain (fixed) position in the
initialized data segment - the beginning of the five bytes of the
array - and "f" as being a certain (fixed) position in the code
segment. Also,

  a[2] is a char,
  f(2) is a char,
  (*fp)[2] is a char -

so arrays and functions are similar, and if we write the "(...)"s at
the left as we did with the "[...]"s, we have that

  "[2]a" is of type "char",
     "a" is of type "char[]",
  "(2)f" is of type "char",
     "f" is of type "char(int:i)",
  "(2)*fp" is of type "char",
     "*fp" is of type "char(int:i)",
      "fp" is of type "char(int:i)*".

The rule for constructing function types is this: if "t" is either a
type with a sizeof or "void", and if "u", "w", and "w" are either
types with sizeofs or types of the form "x[]", and if "a", "b", and
"c" are names for variables, then

  "t(u:a,v:b,w:c)",
  "t(u:a,v:b,w:c,...)",
  "t(void)",
  "t()"

are types with no sizeofs.

Dereferencing
=============

In C arrays are "dereferenced" into pointers when they are used as
values, and if "t" is a type with a sizeof, then "t*" and "t[]" as
almost equivalent when used as types in argument lists of functions.

The code generated for the functions g1 and g2 below is the same:

  char a[] = {'@', 'A', 'B', 'C', 0};
  char b[] = {'@', 'A', 'B', 'C', 0};
  int g1(char *cp) {
    return cp[2];
  }
  int g2(char cp[]) {
    return cp[2];
  }
  int h() { g1(a); g2(a); }

[Two differences: inside g1 we could add a line like "cp = b", but
inside g2 that would be invalid; and inside g1 and g2 the "cp"s would
react differently to "&" - give details using a notation like
"(char*)1000" and "(char[]) at 1000"...]






  +--------+
  |        |
  |  Code  |
  |        |
  +--------+

The "real" code has been moved to:

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

Old stuff:

* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)

TD = {}
newctype = function (kind, typename, sizeof, td)
    td.kind = kind
    td.type = typename
    td.sizeof = sizeof
    TD[typename] = td
    PP(td)
  end

BaseType = function (new, sizeof)
    newctype("base", new, sizeof, {})
  end
ArrayOf = function (old, new, n)
    newctype("array", new, n and (n * TD[old].sizeof), {star=old})
  end
PointerTo = function (old, new, n)
    newctype("pointer", new, 4, {star=old})
  end

eachfielddecl = function (str) return each2(split(str, "([^%s;]+)")) end
StructOrUnion = function (kind, fielddecls, shortname)
    local totalsize = 0
    local fields = {}
    local descriptions = {}
    for type,varname in eachfielddecl(fielddecls) do
        local fieldsize = TD[type].sizeof
        local offset = (kind=="union") and 0 or totalsize
        table.insert(descriptions, type..":"..varname)
        table.insert(fields, {type=type, name=varname, offset=offset})
        fields[varname] = table.getn(fields)
	totalsize = (kind=="union")
                    and math.max(totalsize, fieldsize)
	             or totalsize + fieldsize
      end
    local longname = kind.."{"..table.concat(descriptions, ",").."}"
    newctype(kind, longname, totalsize, {fields=fields})
    if shortname then
      newctype(kind, shortname, totalsize, {fields=fields})
    end
  end
StructOf = function (fielddecls, shortname)
    StructOrUnion("struct", fielddecls, shortname)
  end
UnionOf = function (fielddecls, shortname)
    StructOrUnion("union", fielddecls, shortname)
  end

BaseType ("int",  4)
BaseType ("char", 1)
BaseType ("void", nil)
PointerTo("void",        "void*")
PointerTo("char",        "char*")
PointerTo("char*",       "char**")
ArrayOf  ("char*",       "char*[7]",    7)
ArrayOf  ("char*[7]",    "char*[7][4]", 4)
PointerTo("char*[7][4]", "char*[7][4]*")
StructOf ("int i; char c;", "struct:ic")
UnionOf  ("int ii; char cc;", "union:iicc")
-- TypedefTo("struct:ic", "ic")  -- not yet

--[[
 {"kind"="base", "sizeof"=4, "type"="int"}
 {"kind"="base", "sizeof"=1, "type"="char"}
 {"kind"="base", "type"="void"}
 {"kind"="pointer", "sizeof"=4, "star"="void", "type"="void*"}
 {"kind"="pointer", "sizeof"=4, "star"="char", "type"="char*"}
 {"kind"="pointer", "sizeof"=4, "star"="char*", "type"="char**"}
 {"kind"="array", "sizeof"=28, "star"="char*", "type"="char*[7]"}
 {"kind"="array", "sizeof"=112, "star"="char*[7]", "type"="char*[7][4]"}
 {"kind"="pointer", "sizeof"=4, "star"="char*[7][4]", "type"="char*[7][4]*"}
 {"fields"={1={"name"="i", "offset"=0, "type"="int"},
            2={"name"="c", "offset"=4, "type"="char"},
            "c"=2, "i"=1},
  "kind"="struct", "sizeof"=5, "type"="struct{int:i,char:c}"}
 {"fields"={1={"name"="i", "offset"=0, "type"="int"},
            2={"name"="c", "offset"=4, "type"="char"},
            "c"=2, "i"=1},
  "kind"="struct", "sizeof"=5, "type"="struct:ic"}
 {"fields"={1={"name"="ii", "offset"=0, "type"="int"},
            2={"name"="cc", "offset"=0, "type"="char"},
            "cc"=2, "ii"=1},
  "kind"="union", "sizeof"=4, "type"="union{int:ii,char:cc}"}
 {"fields"={1={"name"="ii", "offset"=0, "type"="int"},
            2={"name"="cc", "offset"=0, "type"="char"},
            "cc"=2, "ii"=1},
  "kind"="union", "sizeof"=4, "type"="union:iicc"}
--]]


methods = {}
methods.base    = {}
methods.typedef = {}
methods.array   = {}
methods.pointer = {}
methods.struct  = {}
methods.union   = {}
methods.generic = {}

cobject_meta = {
  __index = function (cobj, key)
      local td = TD[cobj,type]
      local mt = methods[td.kind]
      return td[key] or mt[key] or methods.generic[key]
    end
  }

methods.array.star = function (cobj)
    return CObject {type=cobj.star, addr=cobj:getvalue()}
  end
methods.pointer.star = function (cobj)
    return CObject {type=cobj.star, addr=cobj.addr}
  end
methods.array.plus = function (cobj)
  end
methods.pointer.plus = function (cobj)
  end
methods.generic.amp = function (cobj)
    return CObject {type=cobj.type.."*", value=assert(cobj.addr)}
  end


   


  +-------------------------+
  |                         |
  |  Stuff to write about:  | 
  |                         |
  +-------------------------+
  
                    (char[5])                       
            ------| {'@','A','B','C',0} |--         
           /        at 1000                \         
        * /              -                  \ weaken       
         /               | +0                \      
        v       &        v          +0        v     
  (char) '@' |----> (char*) 1000 <-------| (char[]) 
  at 1000    <----|      ^         deref   at 1000  
        ^       *        |                        
         \               | +0                     
        * \              -                      
           -------| (char*) 1000                 
                    at 2000                     


PrimitiveType("int",  4)
PrimitiveType("char", 1)
PrimitiveType("void", nil)

PointerTo ("void",        "void*")
PointerTo ("char",        "char*")
PointerTo ("char*",       "char**")
ArrayOf   ("char*",       "char*[7]",    7)
ArrayOf   ("char*[7]",    "char*[7][4]", 4)
PointerTo ("char*[7][4]", "char*[7][4]*")
StructOf  ("int i; char c;", "struct:ic")
TypedefTo ("struct:ic",   "ic")

-- Methods (not implemented yet!!!):
--   :star()
--   :amp()
--   :plus(k)
--   :field(fieldname)
--   :peek()
--   :box(k)
--   :arrow(fieldname)
--   :value()



-- (gdb) ptype month
-- type = char *[4][7]
-- (gdb) ptype &month
-- type = char *(*)[4][7]
-- (gdb) p     month
-- $1 = {{0x8048468 "Aa", 0x804846b "Bb", 0x804846e "Cc", 0x8048471 "Dd",
--        0x8048474 "Ee", 0x8048477 "Ff", 0x804847a "Gg"},
--       {0x804847d "Hh", 0x8048480 "Ii", 0x8048483 "Jj", 0x8048486 "Kk",
--        0x8048489 "Ll", 0x804848c "Mm", 0x804848f "Nn"},
--       {0x8048492 "Oo", 0x8048495 "Pp", 0x8048498 "Qq", 0x804849b "Rr",
--        0x804849e "Ss", 0x80484a1 "Tt", 0x80484a4 "Uu"},
--       {0x80484a7 "Vv", 0x80484aa "Ww", 0x80484ad "Xx", 0x80484b0 "Yy",
--        0x80484b3 "Zz", 0x80484b6 ";:", 0x80484b9 ",."}}
-- (gdb) p     &month
-- $2 = (char *(*)[4][7]) 0x8049600


-- int i;
-- i === {addr=1000000, , type="int", value="\00\00\00\42"}






#####
#
# peek.lua - random notes
# 2007jul26
#
#####

# A tool for introspection
# Inspired by: (find-es "ruby" "evil.rb")
# (find-lua51file "src/")

* (eepitch-gdb-lua-kill)
* (eepitch-gdb-lua)

# (find-node "(gdb)Print Settings")
# (find-node "(gdb)Debugging C")
# (find-node "(gdb)Assignment" "values into arbitrary places")
show print union
ptype UpVal

# (find-lua51file "src/lua.h")
ptype lua_State
ptype lua_CFunction
ptype lua_Reader
ptype lua_Writer
ptype lua_Alloc
ptype lua_Number
ptype lua_Integer
ptype lua_Debug
ptype lua_Hook
#
# (find-lua51file "src/llimits.h")
ptype lu_int32
ptype lu_mem
ptype l_mem
ptype lu_byte
ptype L_Umaxalign
ptype l_uacNumber
ptype Instruction
#
# (find-lua51file "src/lobject.h")
ptype GCObject
ptype GCheader
ptype Value
ptype TValue
ptype StkId
ptype TString
ptype Udata
ptype Proto
ptype LocVar
ptype UpVal
ptype CClosure
ptype LClosure
ptype Closure
ptype TKey
ptype Node
ptype Table







(gdb) 
(gdb) # (find-lua51file "src/lua.h")
(gdb) ptype lua_State
type = struct lua_State {
    GCObject* next;
    lu_byte tt;
    lu_byte marked;
    lu_byte status;
    StkId top;
    StkId base;
    global_State* l_G;
    CallInfo* ci;
    Instruction* savedpc;
    StkId stack_last;
    StkId stack;
    CallInfo* end_ci;
    CallInfo* base_ci;
    int stacksize;
    int size_ci;
    shortunsignedint nCcalls;
    lu_byte hookmask;
    lu_byte allowhook;
    int basehookcount;
    int hookcount;
    lua_Hook hook;
    TValue l_gt;
    TValue env;
    GCObject* openupval;
    GCObject* gclist;
    struct:lua_longjmp* errorJmp;
    ptrdiff_t errfunc;
}
(gdb) ptype lua_CFunction
type = int(*)(lua_State*)
(gdb) ptype lua_Reader
type = char*(*)(lua_State*,void*,size_t*)
(gdb) ptype lua_Writer
type = int(*)(lua_State*,void*,size_t,void*)
(gdb) ptype lua_Alloc
type = void*(*)(void*,void*,size_t,size_t)
(gdb) ptype lua_Number
type = double
(gdb) ptype lua_Integer
type = int
(gdb) ptype lua_Debug
type = struct lua_Debug {
    int event;
    char* name;
    char* namewhat;
    char* what;
    char* source;
    int currentline;
    int nups;
    int linedefined;
    int lastlinedefined;
    char[60] short_src;
    int i_ci;
}
(gdb) ptype lua_Hook
type = void(*)(lua_State*,lua_Debug*)
(gdb) #
(gdb) # (find-lua51file "src/llimits.h")
(gdb) ptype lu_int32
type = unsignedint
(gdb) ptype lu_mem
type = unsignedint
(gdb) ptype l_mem
type = int
(gdb) ptype lu_byte
type = unsignedchar
(gdb) ptype L_Umaxalign
type = union {
    double u;
    void* s;
    longint l;
}
(gdb) ptype l_uacNumber
No symbol "l_uacNumber" in current context.
(gdb) ptype Instruction
type = unsigned int
(gdb) #
(gdb) # (find-lua51file "src/lobject.h")
(gdb) ptype GCObject
type = union GCObject {
    GCheader gch;
    union:TString ts;
    union:Udata u;
    union:Closure cl;
    struct:Table h;
    struct:Proto p;
    struct:UpVal uv;
    struct:lua_State th;
}
(gdb) ptype GCheader
type = struct GCheader {
    GCObject* next;
    lu_byte tt;
    lu_byte marked;
}
(gdb) ptype Value
type = union {
    GCObject* gc;
    void* p;
    lua_Number n;
    int b;
}
(gdb) ptype TValue
type = struct lua_TValue {
    Value value;
    int tt;
}
(gdb) ptype StkId
type = struct lua_TValue {
    Value value;
    int tt;
} *
(gdb) ptype TString
type = union TString {
    L_Umaxalign dummy;
    struct {
        GCObject* next;
        lu_byte tt;
        lu_byte marked;
        lu_byte reserved;
        unsignedint hash;
        size_t len;
    } tsv;
}
(gdb) ptype Udata
type = union Udata {
    L_Umaxalign dummy;
    struct {
        GCObject* next;
        lu_byte tt;
        lu_byte marked;
        struct:Table* metatable;
        struct:Table* env;
        size_t len;
    } uv;
}
(gdb) ptype Proto
type = struct Proto {
    GCObject* next;
    lu_byte tt;
    lu_byte marked;
    TValue* k;
    Instruction* code;
    struct:Proto** p;
    int* lineinfo;
    struct:LocVar* locvars;
    TString** upvalues;
    TString* source;
    int sizeupvalues;
    int sizek;
    int sizecode;
    int sizelineinfo;
    int sizep;
    int sizelocvars;
    int linedefined;
    int lastlinedefined;
    GCObject* gclist;
    lu_byte nups;
    lu_byte numparams;
    lu_byte is_vararg;
    lu_byte maxstacksize;
}
(gdb) ptype LocVar
No symbol "LocVar" in current context.
(gdb) ptype UpVal
type = struct UpVal {
    GCObject *next;
    lu_byte tt;
    lu_byte marked;
    TValue *v;
    union {
        TValue value;
        struct {...} l;
    } u;
}
(gdb) ptype CClosure
type = struct CClosure {
    GCObject *next;
    lu_byte tt;
    lu_byte marked;
    lu_byte isC;
    lu_byte nupvalues;
    GCObject *gclist;
    struct Table *env;
    lua_CFunction f;
    TValue upvalue[1];
}
(gdb) ptype LClosure
type = struct LClosure {
    GCObject *next;
    lu_byte tt;
    lu_byte marked;
    lu_byte isC;
    lu_byte nupvalues;
    GCObject *gclist;
    struct Table *env;
    struct Proto *p;
    UpVal *upvals[1];
}
(gdb) ptype Closure
type = union Closure {
    CClosure c;
    LClosure l;
}
(gdb) ptype TKey
type = union TKey {
    struct {
        Value value;
        int tt;
        struct Node *next;
    } nk;
    TValue tvk;
}
(gdb) ptype Node
type = struct Node {
    TValue i_val;
    TKey i_key;
}
(gdb) ptype Table
type = struct Table {
    GCObject *next;
    lu_byte tt;
    lu_byte marked;
    lu_byte flags;
    lu_byte lsizenode;
    struct Table *metatable;
    TValue *array;
    Node *node;
    Node *lastfree;
    GCObject *gclist;
    int sizearray;
}
(gdb) 
type = struct Table {
    GCObject *next;
    lu_byte tt;
    lu_byte marked;
    lu_byte flags;
    lu_byte lsizenode;
    struct Table *metatable;
    TValue *array;
    Node *node;
    Node *lastfree;
    GCObject *gclist;
    int sizearray;
}
(gdb) 
type = struct Table {
    GCObject *next;
    lu_byte tt;
    lu_byte marked;
    lu_byte flags;
    lu_byte lsizenode;
    struct Table *metatable;
    TValue *array;
    Node *node;
    Node *lastfree;
    GCObject *gclist;
    int sizearray;
}
(gdb) 












# (find-lua51file "src/lua.h")

* (eepitch-gdb-lua-kill)
* (eepitch-gdb-lua)
ptype Proto
ptype GCObject
ptype   GCheader

ptype TString

ptype    L_Umaxalign
p sizeof(L_Umaxalign)
p sizeof(double)
p sizeof(void *)
p sizeof(long int)

ptype lu_byte
ptype size_t


ctype["unsignedchar"] = { sizeof = 1 }
ctype["lu_byte"]      = { sizeof = 1 }
ctype["GCObject*"]    = { sizeof = 4 }





#####
#
# lcmd.lua
# 2007jul27
#
#####

# (find-es "lua5" "lua-ex")




#####
#
# debugging wish
# 2007aug13
#
#####

# «debugging-wish»  (to ".debugging-wish")
# (find-es "tcl" "luatclbridge")
# (find-tk84file "")
# (find-tk84file "odb")
# (find-tk84file "odb" "-o wish")
# (find-tk84file ".files" "unix/libtk8.4.so")
# (find-tk84sh "cd unix; ldd ./wish")
# (find-angg ".zshrc" "tcl-tk")
# (find-angg ".emacs" "tcl-tk")

* (setenv "LD_LIBRARY_PATH" (getenv "TCLTK_LD_LIBRARY_PATH"))
* (eepitch-gdb-wish)
* (eepitch-gdb-wish-kill)
* (eepitch-gdb-wish)
br Tcl_FindExecutable
y
run
p argv0

# (find-sh "objdump -xasf $TKSRCDIR/wish")
# (find-node "(stabs)Top")
# (find-node "(stabs)C Example")
# (find-node "(stabs)Assembly Code")

# (find-angg "LUA/luatclbridge.c")



lua-l, 2008nov03, Peter Cawley:
If you want to do this, and make it feel natural to Lua, then it is a
bit of a pig to do: Create a table (T), assign it a fresh metatable
(MT), add an __index metamethod to MT which reads the value from the C
structure and then add a __newindex metatable to MT which writes the
value to the C structure.



http://trac.clozure.com/openmcl/wiki/OpenMclFfi





#  Local Variables:
#  coding:               utf-8-unix
#  End: