Exibindo erros em scripts #NCLua. #TVD #Ginga #NCL #Lua

Como muitos desenvolvedores NCLua já devem ter notado, em algumas situações no Ginga Virtual Set-top Box (pelo menos até a versão  0.12.4), quando algo está errado no código Lua, o Ginga não mostra nada no terminal, simplesmente parando a execução da aplicação. Isto é um "Gingantesco" problema, pois ficamos no escuro sem saber o que está errado e é muito trabalhoso encontrar o erro, só na base da depuração usando print :(.

Erros comuns são a tentativa de acessar um campo em uma tabela que não existe (por ter digitado o nome da tabela incorretamente, por exemplo), chamar funções sem passar todos os parâmetros requeridos, etc.

Assim, estudando o problema, encontrei uma solução paleativa para o mesmo, pois o correto seria que a mensagem de erro aparecesse no terminal.

Desta forma, considerem o seguinte código, que deveria apenas mostrar um texto centralizado na tela, usando o módulo canvas de NCLua:

  canvas:attrFont("vera",32)
  canvas:attrColor(255,255,255,255)
  local w, h = canvas:attrSize()
  canvas:drawRect("fill", 0,0, w, h)
  canvas:attrColor(0,0,0,0,255)
  local text = "Desenhando com NCLua canvas"

  --ERRO: nome da função está errada
  local wText, hText = canvas:meansureText(text) 

  --ERRO: faltou definir valor para y
  local x, y = math.floor((w-wText)/2) 

  --Sem um valor para y, ocorrerá erro aqui
  canvas:drawText(x,y,text)
  canvas:flush()

Observe que há erros nas linhas 8 e 9. Na linha 8 o nome da função está errada (não deve ter a letra n) e na linha 9 faltou definir um valor para a variável y (que dará erro ao ser usada na linha seguinte).

No entanto, se você incluir este script como uma mídia numa aplicação NCL e rodar no Ginga Virtual STB, provavelmente nenhum erro será apresentado e a aplicação apenas para de executar, dificultando saber onde o problema ocorreu. Para fazer as mensagens de erro aparecerem, uma solução paleativa simples é a seguinte, considerando que você tem um arquivo main.lua, coloque todo o código dele dentro de uma função chamada main, como mostrado abaixo:

function main()
  --insira aqui todo o código da listagem acima
end

Agora, no lugar de chamar a função main diretamente, vamos usar a função pcall para chamar ela em modo protegido. Desta forma, a função pcall é que chamará a função main, não propagando nenhum erro ocorrido dentro dela. Como a função main não possui nenhum parâmetro, para fazer a função pcall chamá-la, basta usar o código a seguir:

local ok, res = pcall(main)

A função pcall retorna pelo menos um valor:

Caso a função chamada pelo pcall gere algum erro, o segundo valor retornado pelo pcall será a mensagem de erro. Desta forma, após a linha de código mostrada acima, podemos verificar se ocorreu erro usando o código abaixo:

if not ok then
   print("\n\nError: "..res, "\n\n")
   return -1
end

É importante frisar que isto não está fazendo um tratamento de erros adequado, pois quando se captura um erro não fatal, é porque deseja-se contorná-lo (por exemplo, mostrando uma mensagem na interface gráfica para o usuário) e continuar a execução da aplicação normalmente. Neste caso, qualquer erro ocorrido fará com que a aplicação seja finalizada (como já acontecia caso você não tome nenhuma iniciativa para tratar o erro).

Pronto, é isso. Espero que seja útil enquanto não sai uma correção. Comentários e outras soluções são bem vindas.

Read more...

Executando Port Scan no Linux com netcat (nc)

Um post rápido hoje, pra não dizerem que o blog morreu :) Vou mostrar rapidamente como realizar um port scan no Linux usando o comando netcat (nc). Veja comando abaixo:

nc -z -v IpOuHostname PortaInicial-PortaFinal

Ao executar o comando nc passando o parâmetro -z, solicitamos a execução de um port scanning. O parâmetro -v é para mostrar a saída no terminal. No lugar de IpOuHostname informe o IP ou nome da máquina onde deseja fazer o port scanning. E no lugar de PortaInicial e PortaFinal indique a faixa de portas desejadas para realizar o escaneamento. Bem simples né? :)

Se desejar exibir apenas as mensagens que indiquem portas abertas, use o comando como mostrado abaixo:

nc -z -v IpOuHostname PortaInicial-PortaFinal 2>&1 | grep succeeded

Veja o exemplo a seguir, que procura portas abertas no host de IP 10.1.1.1, desde a porta 1 até a 65535, exibindo apenas as mensagens de conexão bem sucedida (ou seja, porta aberta):

nc -z -v 10.1.1.1 1-65535 2>&1 | grep succeeded

O 2>&1 no comando acima indica que a saída de erro (2) deve ser direcionada pra saída padrão (1). Usando o grep, filtramos então as mensagens que contenham a palavra succeeded e pronto.

Referências:

Manual do netcat Prompt do Linux: stdin, stdout, stderr e seus truques

Read more...

Lendo XML em Lua com LuaXML: parser totalmente Lua. #TVD #GingaNCL

Tenho visto ainda nos fóruns de discussão algumas perguntas de como ler arquivos XML em Lua. Existem alguns módulos Lua que utilizam bibliotecas em C para fazer isto, como o LuaXML do site viremo.eludi.net.

No entanto, no Ginga-NCL (subsistema do middleware Ginga do Sistema Brasileiro de TV Digital), não é possível usar módulos em C em aplicações enviadas via broadcast. Assim, para fazer o parse de arquivos XML em aplicações Lua para TVD, é preciso usar um parser escrito inteiramente em Lua.

No site LuaUsers existem algumas opções de parsers XML para Lua, alguns deles usam módulos escritos em C também. Na seção Lua-only XML parsers existem algumas opções de módulos escritos inteiramente em Lua. Destes, o que acho mais completo e fácil de usar é o módulo LuaXML (isso mesmo, o mesmo nome do anterior, por isso há certa confusão quando se fala em LuaXML) . Com tal módulo é possível fazer o parse de um XML carregado a partir de um arquivo no disco, obtido via HTTP, ou estaticamente definido em uma variável string. O módulo transforma o arquivo XML em uma tabela Lua, assim, fica muito simples de manipular.

Na página do LuaXML no LuaUsers existe a versão original do módulo para Lua 4. Uma versão para Lua 5, adaptada por mim a partir da versão original está disponível para download no GitHub.

Usando o módulo LuaXML

Vamos criar agora uma aplicação para mostrar como usar tal módulo. Primeiro crie um arquivo de nome dados.xml com o conteúdo abaixo:

<?xml version="1.0" encoding="ISO-8859-1"?>
<pessoas>
  <pessoa tipo="F">
    <nome>Manoel</nome>
    <cidade>Palmas-TO</cidade>
  </pessoa>
  <pessoa tipo="F">
    <nome>Breno</nome>
    <cidade>Palmas-TO</cidade>
  </pessoa>
  <pessoa tipo="J">
    <nome>UnB</nome>
    <cidade>Brasília-DF</cidade>
  </pessoa>
</pessoas>

O arquivo XML armazena dados de pessoas físicas e jurídicas. Cada tag pessoa tem um atributo tipo que identifica isto.

Bem, depois de baixar o LuaXML do LuaUsers no link mostrado anteriormente, descompacte ele na raiz da pasta da aplicação e em seguida renomeie seu diretório para LuaXML.

Agora crie um arquivo de nome main.lua, na mesma pasta do dados.xml. A aplicação Lua é bem simples, e como não usa nenhum recurso do Ginga, pode ser executada diretamente no interpretador Lua no seu computador e funcionar em qualquer plataforma.

O código de main.lua é mostrado abaixo, e comentado em seguida: (arquivo disponível no pacote para download no final do artigo)

dofile("LuaXML/xml.lua")
dofile("LuaXML/handler.lua")

---Imprime uma tabela, de forma recursiva
--@param tb A tabela a ser impressa
--@param level Apenas usado internamente para
--imprimir espaços para representar os níveis
--dentro da tabela.
function printable(tb, level)
  level = level or 1
  local spaces = string.rep(' ', level*2)
  for k,v in pairs(tb) do
      if type(v) ~= "table" then
         print(spaces .. k..'='..v)
      else
         print(spaces .. k)
         level = level + 1
         printable(v, level)
      end
  end
end

local filename = "dados.xml"
local xmltext = ""
local f, e = io.open(filename, "r")
if f then
  --Lê todo o conteúdo do arquivo
  xmltext = f:read("*a")
else
  error(e)
end

--Instancia o objeto que é responsável por
--armazenar o XML em forma de uma table lua
local xmlhandler = simpleTreeHandler()

--Instancia o objeto que faz o parser do XML para uma table lua.
--O xmlhandler foi instanciado lá no início do código
local xmlparser = xmlParser(xmlhandler)
xmlparser:parse(xmltext)

--Imprimindo a tabela recursivamente
--printable(xmlhandler.root)

--Imprimindo manualmente (uma vez que a estrutura do XML é conhecida previamente)
for k, p in pairs(xmlhandler.root.pessoas.pessoa) do
  print("Nome:", p.nome, "Cidade:", p.cidade, "Tipo:", p._attr.tipo)
end

Nas linhas 1 e 2 o módulo é carregado. Como o mesmo não foi implementado usando o recurso module da linguagem Lua, o mesmo não pode ser carregado com require.

Entre as linhas 4 e 21 é definida a função printable, que imprime uma tabela no terminal. Ela percorre toda a estrutura da tabela recursivamente e imprime cada elemento encontrado. Assim, fica fácil exibir o conteúdo de um arquivo XML após executar o parse com o LuaXML. Desta forma, não é preciso saber a estrutura do XML, basta passar a tabela resultante do parse para a função. Isto será demonstrado em seguida.

Algumas linhas são auto-explicativas e não serão comentadas. Entre as linhas 23 e 31 é feito o carregamento do arquivo XML do disco.

Com o conteúdo do XML em memória (em uma variável string), podemos agora instanciar o parser. As linhas 33 a 39 fazem isso.

A linha 40 executa o parse do XML armazenado na variável xmltext, gerando uma tabela lua que representa o XML. Para acessar tal tabela, basta usar a variável xmlhandler.root.

A linha 43 (que está comentada), chama a função printable para imprimir a tabela que representa o XML (xmlhandler.root). A função é útil quando você não conhece previamente a estrutura do XML e deseja exibir seu conteúdo na tela, de forma estruturada.

Quando você conhece previamente a estrutura do XML, pode usar um código mais personalizado para acessar e imprimir os elementos, como mostra o código entre as linhas 45 a 48. Neste trecho, simplesmente é usado um for para percorrer a tabela. Como xmlhandler.root e a tabela que representa o XML, os itens dela são as tags do XML. Como nosso XML tem um elemento raiz de nome pessoas, e este possui várias tags pessoa, na tabela Lua, pessoa funcionará como um array (vetor). Assim, na linha 46 o array pessoa é acessado a partir do elemento pessoas. Com isto, a variável p do for representa cada pessoa dentro da tag pessoas. Agora fica fácil acessar as tags de cada pessoa (nome e cidade) na linha 47. Como nosso arquivo XML possui um atributo para cada tag pessoa, tais atributos são armazenados em um elemento _attr no item que representa a tag pessoa no XML. Assim, cada atributo será acessado por _attr.nome_do_atributo, como mostra a linha 47.

Conclusão

Como pôde ser visto, fazer o parse de arquivos XML em Lua com o LuaXML do LuaUsers é bem simples e intuitivo. Um tutorial em PDF, elaborado por Johnny Moreira Gomes, está disponível neste link.

Read more...

Destacando sintaxe de códigos Lua em Latex

Bem, nunca falei de Latex antes aqui no blog, principalmente por falta de tempo e porque não sou um profundo conhecedor da ferramenta.

Mas como tenho usado muito a mesma, resolvi falar dela hoje. Vou mostrar uma dica bastante útil para programadores Lua que estejam no meio acadêmico e também usem Latex em trabalhos desta categoria.

O Latex possui um pacote denominado listings que permite destaquer a sintaxe de trechos de códigos fonte em diferentes linguagens. No entanto, o suporte à Linguagem Lua parece ainda não ser oficial. Buscando na Web encontrei uma implementação de Roland Smith. Para usá-la, precisaremos baixar os fontes do pacote listings e adicionar tal suporte. Então vamos lá. Vou mostrar como fazer isso em linux. Estou utilizando o Ubuntu 10.10 já com Latex instalado.

Instalação

Obs.: Se desejar baixar o pacote listings já com as modificações (inclusão de suporte à linguagem Lua e adição de 3 estilos), baixe o mesmo no final do post e siga os passos a partir do número 5.

  1. Primeiro baixe o arquivo listings.zip e descompacte em algum diretório.
  2. Baixe o arquivo lua.def e salve no mesmo diretório onde descompactou o listings.zip. O arquivo é para o módulo listings 1.3 ou anterior.
  3. Abra o arquivo lua.def. Como o pacote listings baixado no link informado é a versão 1.4, precisaremos fazer uma pequena alteração neste arquivo. Procure o texto lstdefinelanguage e altere para **lst@definelanguage **(deixe a \ que existe no início da linha) Copie todo o conteúdo deste arquivo.
  4. Abra o arquivo lstdrvrs.dtx. Este arquivo contém o código da definição do estilo de de destaque para cada linguagem suportada. Procure pelo texto lst@definelanguage.  Antes da linha onde ele for encontrado, cole o conteúdo copiado do arquivo lua.def e salve
  5. Agora, abra um terminal no diretório onde estão os arquivos do pacote descompactado e execute o comando **make **para compilar o mesmo
  6. Por fim, basta copiar os arquivo *.cfg e *.sty para o diretório /usr/share/texmf-texlive/tex/latex/listings (se o diretório não existir, crie).

Pode ser necessário executar o comando texhash para que o novo módulo seja reconhecido (não sei, mas por via das dúvidas, execute o mesmo).

Pronto, módulo instalado. Para usar é bem simples, no seu arquivo tex, inclua o pacote com o comando \usepackage{listings}.

Com o comando \lstset, que precisa ser chamado apenas uma vez (antes de você incluir um trecho de código fonte para ser destacado pelo módulo) você deve configurar o estilo da listagem de código. Veja exemplo abaixo:

\lstset{
%Numeração de linhas à esquerda
numbers=left,

%Incrementa o número de linhas de 1 em 1
stepnumber=1,

%Número da primeira linha
firstnumber=1,

%Tamanho da numeração das linhas
numberstyle=\tiny,

extendedchars=true,
frame=none,
basicstyle=\footnotesize,
stringstyle=\ttfamily,
showstringspaces=false,
breaklines=true,
breakautoindent=true,

%Estilos de comentários de Lua para uma e várias linhas
morecomment=[l]{--},
morecomment=[s]{--[[}{--]]}}

Para destacar a sintaxe de um trecho de código Lua (nosso objetivo final), é bem simples, como mostrado a seguir:

\begin{lstlisting}[[caption=Título do trecho de código, label=list:meu-codigo-lua, language=lua]]
--Inclua seu código Lua aqui
\end{lstlisting}

O atributo caption é para você definir um título para o seu trecho de código. Label define um rótulo que você pode usar para fazer referências a tal trecho de código com o comando \ref{nome-do-rotulo}, onde no exemplo, definimos como list:meu-codigo-lua. Por fim, language=lua define que o código é em linguagem Lua (poderia ser Java, C e várias outras que já são padrões no módulo listings).

A imagem a seguir mostra um exemplo de como o código Lua ficará no PDF gerado a partir do tex.

O pacote listings também suporta estilos de formatação (que funciona com qualquer linguagem). O colega Renato Maia deu uma grande contribuição disponibilizando três estilos que adicionei ao pacote: monochrome, colorful e numbered. No final deste artigo existe um arquivo zip com o pacote listings já com suporte à linguagem Lua e com tais temas incorporados, bastando instalar o mesmo.

Para usar algum tema é bem simples. Basta alterar a linha \begin{listings} do exemplo anterior para a linha mostrada abaixo:

\begin{lstlisting}[[caption=Título do trecho de código, label=list:meu-codigo-lua, language=lua, style=colorful,style=numbered]]

Para usar o estilo colorful, é preciso adicionar o pacote color no seu documento tex. A figura a seguir mostra como o código ficará no PDF gerado a partir do documento tex.

Então é isso, espero que seja útil.

Read more...

Instalando #LuaProfiler no #Ginga Virtual Set-top Box. #TVD

O LuaProfiler é um módulo que permite fazer o profilling de um programa escrito em Lua. Com tal ferramenta é possível identificar gargalos em sua aplicação, ou seja, partes do código fonte que levem mais tempo para executar que o normal, e assim poder melhorar tal código para tentar ganhar desempenho.

A forma mais fácil de instalar módulos Lua em uma distribuição Linux, como no caso do Ginga Virtual Set-top Box 0.11.2 que utiliza Ubuntu, é por meio do LuaRocks. No entanto, alguns módulos como o LuaProfiler não funcionam no Ginga se instalados com o LuaRocks, que automatiza o processo de instalação de módulos da mesma forma que a ferramenta apt-get (existente em várias distribuições Linux).

Assim, para usar o LuaProfiler no Ginga Virtual STB, precisaremos compilar o código fonte e fazer uma pequena alteração em tal processo.

É importante lembrar que o LuaProfiler é um módulo Lua que utiliza um módulo escrito em C, assim, seu uso deve ser apenas em ambientes de desenvolvimento e teste, como o Ginga Virtual Set-top Box. A aplicação a ser distribuída não deve ter referência alguma a tal módulo.

Iniciando processo de instalação

Para iniciar o processo de instalação do LuaProfiler no Ginga Virtual Set-top Box, primeiro conecte via SSH no mesmo. Este tutorial foi feito com a versão 0.11.2.

No terminal SSH, baixe o LuaProfiler 2.0.2 com o comando a seguir (você também pode baixar uma versão modificada para o Ginga-NCL no final deste artigo):

wget http://luaforge.net/frs/download.php/3400/luaprofiler-2.0.2.tar.gz

Agora descompacte o arquivo baixado:

tar -zxvf luaprofiler-2.0.2.tar.gz

Entre no diretório criado:

cd luaprofiler-2.0.2

Edite o arquivo config.linux com o editor pico:

pico config.linux

Altere o texto /usr/local/include/lua51 para /usr/local/include/ Este é o caminho dos arquivos header do Lua dentro do Ginga. Para sair do pico, pressione CTRL+X, depois Y e ENTER para salvar

Edite o arquivo Makefile.linux com o pico:

pico Makefile.linux

Altere a linha

mkdir -p bin && $(LD) -Bshareable -o $(PROFILER_OUTPUT) $(OBJS)

para o valor abaixo

mkdir -p bin && $(LD) -Bshareable -o $(PROFILER_OUTPUT) $(OBJS) /usr/local/lib/liblua.a

Isto fará com que as bibliotecas padrões de Lua sejam linkadas no módulo luaprofiler.so que será criado na compilação. Tal alteração é necessária pois, com a instalação padrão ou usando LuaRocks, provavelmente você receberá o erro "undefined symbol: luaL_openlib" quando tentar executar o LuaProfiler em uma aplicação NCLua, indicando que a função luaL_openlib não existe no interpretador Lua utilizado no Ginga. Procurando na web vi que tal função foi substituída por luaL_register, mas alterando o código para esta função também não compila, indicando que tal função não existe.

Provavelmente isto é devido à forma como o interpretador Lua foi compilado no Ginga, que é resolvido linkando a biblioteca liblua.a no módulo luaprofiler.so, tornando o LuaProfiler independente das bibliotecas de Lua do interpretador no Ginga. Ele mesmo já carregará tais bibliotecas. Isto não é o ideal e nem aconselhável, mas como estamos em um ambiente de testes, resolve o problema.

Feita a alteração, saia do editor pressionando CTRL+X, depois Y e ENTER para salvar.

Agora faça uma cópia do arquivo Makefile.linux com o nome de Makefile (pois o comando make procurará um arquivo com este nome):

cp Makefile.linux Makefile

Compile os fontes e instale o módulo com os comandos abaixo:

make && make install

Usando o LuaProfiler

Para usar o LuaProfiler em uma aplicação Lua, basta incluir um require "profiler" para usar o módulo. Para iniciar o profilling, no local desejado inclua a linha profiler.start("profiler.log") (que pode ser antes da chamada de uma determinada função ou no início do script). Esta linha iniciará a análise do tempo de execução de cada função no script Lua da sua aplicação e gerará um relatório com o nome de profiler.log.

Para finalizar o processo, você deve incluir no local desejado a linha **profiler.stop() **(que pode ser quando a aplicação receber um evento para ser finalizada ou depois da chamada de alguma função que desejar ).

Analisando os resultados

Após encerrar a aplicação, basta abrir o arquivo profiler.log em um editor como o pico e analisar o resultado. O arquivo mostra cada chamada de função, a linha em que foi chamada, o tempo de execução e outros dados. Tal arquivo pode ser bem extenso dependendo do tamanho do seu script lua. Assim, sua análise pode ser mais complicada.

No entanto, existe o script summary.lua, dentro dos fontes do LuaProfiler, que agrupa as chamadas de cada função registrada no arquivo de saída do módulo (no nosso caso, profiler.log), o que pode facilitar a análise. O script fica no sub-diretório src/analyzer, dentro do diretório onde você descompactou os fontes do LuaProfiler. No entanto, ao utilizar tal script ocorreram alguns erros que foram corrigidos. A versão disponível para download já possui tal correção.

Usar o script summary.lua é bem simples. Para facilitar, copie o mesmo para o diretório onde está o arquivo de saída do LuaProfiler (que definimos o nome de profiler.log anteriormente, dentro da chamada a profiler.start()).

Agora, estando dentro do diretório do arquivo profiler.log, basta executar o comando abaixo:

lua summary.lua -v profiler.log > summary.xls

Tal comando vai ler o arquivo profiler.log e agrupar os resultados, gerando um arquivo summary.xls. Tal arquivo pode ser aberto em um aplicativo de planilhas eletrônicas como o OpenOffice Calc. O arquivo tem as colunas separadas por TAB. Assim, ao abrir no OpenOffice, será mostrada uma janela para importar o summary.xls para uma planilha. Nesta tela você deve informar que as colunas estão separadas por TAB. Após importar o arquivo, basta salvar para o formato nativo do OpenOffice ou do Microsoft Office.

Read more...