Page 3 of 7

Re: Порт LUA

Posted: Thu Mar 10, 2011 7:23 pm
by Serge
Что значит "не хотят" ?

Re: Порт LUA

Posted: Thu Mar 10, 2011 7:34 pm
by SoUrcerer
Значит, что у меня кривые руки. Подключаю kolibri.h из shell, получаю падение приложения при вызове элементарной kol_board_puts.

Re: Порт LUA

Posted: Thu Mar 10, 2011 7:52 pm
by Serge
Sorcerer
Хочешь console.obj подключить ?
>>kol_board_puts А чем printf() не устраивает ? Тоже на доску пишет.

Re: Порт LUA

Posted: Thu Mar 10, 2011 8:05 pm
by SoUrcerer
Не только console.obj. Там же куча всяких полезных функций, которые неплохо бы вызывать из lua например вот так: kolibri.define_window.
А printf всем устраивает, но kol_board_puts - самая наглядно показывающая что все работает функция.
upd: В который раз убеждаюсь, что нужно больше кушать и спать. Передавать указатель на стек параметров lua вместо указателя на строку было не лучшей идеей. Надеюсь, к выходным сделаю обертки для некоторого минимума оберток функций Колибри. Было бы здорово, если бы получилось сделать загрузку библиотек. Тогда можно было бы подключить libPNG, boxlib и всё такое.

Re: Порт LUA

Posted: Fri Mar 11, 2011 10:34 am
by SoUrcerer
:roll: Что-то я туплю.

1) Код в kolibri.c:

Code: Select all

unsigned kol_event_wait(){asm ("int $0x40"::"a"(10));}
Код в моей библиотеке:

Code: Select all

static int luaB__waitevent (lua_State *L){
lua_pushnumber(L, kol_event_wait());
return 1;}
Замечательно работает.

2) Код в kolibri.c:

Code: Select all

unsigned kol_key_get(){asm ("int $0x40"::"a"(2));}
Код в моей библиотеке:

Code: Select all

static int luaB__getkey (lua_State *L){
lua_pushnumber(L, kol_key_get());
return 1;}
Возвращает число в 256 раз большее (т.е. сдвиг на байт). Аналогичная история с kol_btn_get(). Причем число в 256 раз большее возвращается именно функцией, код Lua отношения к таким чудесам не имеет.

3) Код в kolibri.c:

Code: Select all

void kol_paint_string(unsigned x, unsigned y,  unsigned c, char *s)
{asm ("int $0x40"::"a"(4), "b"(x*65536+y), "c"(c), "d"(s));}
Код в моей библиотеке:

Code: Select all

static int luaB__textout (lua_State *L){
  int n = lua_gettop(L);  /* number of arguments */
  int i, r[n];
  const  char * s;
  lua_getglobal(L, "tostring");
  for (i=1; i<=n; i++) {
    lua_pushvalue(L, -1);  /* function to be called */
    lua_pushvalue(L, i);   /* value to print */
    lua_call(L, 1, 1);
    s = lua_tostring(L, -1);
    r[i]=atoi(s);
    lua_pop(L, 1);  /* pop result */}
  printf ("%s \n", s);
  kol_paint_string (r[1],r[2],r[3],s);
  return 0;}
На доску отладки выводятся правильные значения. То есть я даю команду textout(3,13,0, "LuaCalc") и получаю на доске LuaCalc, и больше ничего лишнего. Однако в окне наблюдаю следующее:
Снимок.png
Снимок.png (2.52 KiB)
Viewed 8748 times
Дело в несоответствии типов (unsigned/int и static char */char *)? Если да, то как бороться?

Re: Порт LUA

Posted: Fri Mar 11, 2011 10:58 am
by Serge
Sorcerer

kol_key_get() возвращает код формате ф.2 - регистре ah.
kol_paint_string (r[1],r[2],r[3],s); - проверь r[3]

textout(3,13,0, "LuaCalc") - ага, у тебя в вызове ф.4 выводится esi символов.
ecx = 0xX0RRGGBB, где
RR, GG, BB задают цвет текста
X=ABnn (биты):
nn задает используемый шрифт: 0=системный моноширинный, 1=системный шрифт переменной ширины
A=0 - выводить esi символов, A=1 - выводить ASCIIZ-строку
B=1 - закрашивать фон цветом edi

Re: Порт LUA

Posted: Fri Mar 11, 2011 2:26 pm
by SoUrcerer
Ок,понятно. Там, где значение больше в 256 раз, можно просто делить?

Re: Порт LUA

Posted: Fri Mar 11, 2011 2:45 pm
by Serge
Там надо правильно разбирать возвращаемое значение или в самом LUA, или адаптировать функцию

Code: Select all

если буфер пуст, возвращается eax=1 
если буфер непуст, то возвращается al=0, ah=код нажатой клавиши, старшее слово регистра eax обнулено 
если есть "горячая клавиша", то возвращается al=2, ah=сканкод нажатой клавиши (0 для управляющих клавиш), старшее слово регистра eax содержит состояние управляющих клавиш в момент нажатия горячей клавиши 

Re: Порт LUA

Posted: Fri Mar 11, 2011 9:30 pm
by SoUrcerer
Понятно. Тот, кто не читает мануалы (то есть я) - ССЗБ.

Code: Select all

* старшие 24 бита eax содержат идентификатор кнопки
      (в частности, в ah оказывается младший байт идентификатора;
      если все кнопки имеют идентификатор, меньший 256,
      то для различения достаточно ah)
    * al = 0 - кнопка была нажата левой кнопкой мыши
    * al = бит, соответствующий нажавшей кнопке мыши, если не левой
Как будет выглядеть тогда eax побитово, если левой кнопкой мыши нажата кнопка с идентификатором 1?
Вот так: 00000000000000000000000100000000
То есть нужно брать первые 24 бита, и отбрасывать свойство "левая/правая кнопка была нажата". Или же менять функцию, чтобы она возвращала два параметра как таблицу.

Re: Порт LUA

Posted: Fri Mar 11, 2011 10:34 pm
by Serge
Не первые, а старшие.
mouse_button = button_id &0xFF;
button_id = button_id >>8;

Re: Порт LUA

Posted: Sat Mar 12, 2011 10:11 pm
by SoUrcerer
Пока что занимаюсь перетягиванием функций Колибри в LUA, но на самом деле даже версия, собранная Serge, вполне работоспособна. А пока что покажу пару вкусностей, которые могут быть полезны (для второй из них можно легко написать графический интерфейс, как только я допилю вывод текста и обработку клавиатуры, а осталось, я верю, совсем немного).

1) Парсер XML. Я использовал его, чтобы распарсить SVG-файл, и это удалось мне без проблем. Код взят с luaforge

Code: Select all

function parseargs(s)
local arg = {}
string.gsub(s, "(%w+)=([\"'])(.-)%2", function (w, _, a)
arg[w] = a
end
return arg
end

function collect(s)
local stack = {}
local top = {}
table.insert(stack, top)
local ni,c,label,xarg, empty
local i, j = 1, 1
while true do
ni,j,c,label,xarg, empty = string.find(s, "<(%/?)(%w+)(.-)(%/?)>", i)
if not ni then break end
local text = string.sub(s, i, ni-1)
if not string.find(text, "^%s*$") then
table.insert(top, text)
end
if empty == "/" then -- empty element tag
table.insert(top, {label=label, xarg=parseargs(xarg), empty=1})
elseif c == "" then -- start tag
top = {label=label, xarg=parseargs(xarg)}
table.insert(stack, top) -- new level
else -- end tag
local toclose = table.remove(stack) -- remove top
top = stack[#stack]
if #stack < 1 then
error("nothing to close with "..label)
end
if toclose.label ~= label then
error("trying to close "..toclose.label.." with "..label)
end
table.insert(top, toclose)
end
i = j+1
end
local text = string.sub(s, i)
if not string.find(text, "^%s*$") then
table.insert(stack[#stack], text)
end
if #stack > 1 then
error("unclosed "..stack[stack.n].label)
end
return stack[1]
end

--Открываем файл picture.svg
fi=io.open("picture.svg","r")
--Читаем из него всё
all=fi:read("*a")
--Можно закрыть, но это будет сделано автоматически при завершении программы

--Даем команду распарсить
var=collect(all)

for key, value in pairs(var) do --переберем все поля таблицы первого уровня вложенности
	print ("\n")    
	print(key, value)
end
Результат работы программы - таблица var, содержащая в себе много-много вложенных таблиц с полями XML.

2) HTML-парсер. Конвертирует HTML-страницы в текстовые файлы, все ссылки записываются как сноски.

Code: Select all

--[[
HTML Parser in Lua
Inspired by this C# code:
http://www.codeproject.com/useritems/HTML_to_Plain_Text.asp

It does exactly the same as described there.
Only converts offline files.

Distributed under a modified BSD license, see at the end of the file]]

-- What is the desired newline?
nl = "\n"

filename = "Kolibri.html"

function HTML_ToText (file)
  -- Declare variables, load the file. Make tags lowercase.
  local text
  local f=io.open (file)
  if f then
    if f:seek("end") <= 0 then return end
    f:seek("set")
    text = f:read ("*a")
    f:close()
  end
  text = string.gsub (text,"(<([^>]-)>)",function (str) return str:lower() end)
  --[[
  First we kill the developer formatting (tabs, CR, LF)
  and produce a long string with no newlines and tabs.
  We also kill repeated spaces as browsers ignore them anyway.
  ]]
  local devkill=
    {
      ["("..string.char(10)..")"] = " ",
      ["("..string.char(13)..")"] = " ",
      ["("..string.char(15)..")"] = "",
      ["(%s%s+)"]=" ",
    }
  for pat, res in pairs (devkill) do
    text = string.gsub (text, pat, res)
  end
  -- Then we remove the header. We do this by stripping it first.
  text = string.gsub (text, "(<%s*head[^>]*>)", "<head>")
  text = string.gsub (text, "(<%s*%/%s*head%s*>)", "</head>")
  text = string.gsub (text, "(<head>,*<%/head>)", "")
  -- Kill all scripts. First we nuke their attribs.
  text = string.gsub (text, "(<%s*script[^>]*>)", "<script>")
  text = string.gsub (text, "(<%s*%/%s*script%s*>)", "</script>")
  text = string.gsub (text, "(<script>,*<%/script>)", "")
  -- Ok, same for styles.
  text = string.gsub (text, "(<%s*style[^>]*>)", "<style>")
  text = string.gsub (text, "(<%s*%/%s*style%s*>)", "</style>")
  text = string.gsub (text, "(<style>.*<%/style>)", "")
 
  -- Replace <td> and <th> with tabulators.
  text = string.gsub (text, "(<%s*td[^>]*>)","\t")
  text = string.gsub (text, "(<%s*th[^>]*>)","\t")
 
  -- Replace <br> with linebreaks.
  text = string.gsub (text, "(<%s*br%s*%/%s*>)",nl)
 
  -- Replace <li> with an asterisk surrounded by spaces.
  -- Replace </li> with a newline.
  text = string.gsub (text, "(<%s*li%s*%s*>)"," *  ")
  text = string.gsub (text, "(<%s*/%s*li%s*%s*>)",nl)
 
  -- <p>, <div>, <tr>, <ul> will be replaced to a double newline.
  text = string.gsub (text, "(<%s*div[^>]*>)", nl..nl)
  text = string.gsub (text, "(<%s*p[^>]*>)", nl..nl)
  text = string.gsub (text, "(<%s*tr[^>]*>)", nl..nl)
  text = string.gsub (text, "(<%s*%/*%s*ul[^>]*>)", nl..nl)
   
  -- Some petting with the <a> tags. :-P
  local addresses,c = {},0
  text=string.gsub(text,"<%s*a.-href=[\'\"](%S+)[\'\"][^>]*>(.-)<%s*%/*%s*a[^>]->", -- gets URL from a tag, and the enclosed name
  function (url,name)
    c = c + 1
    name = string.gsub (name, "<([^>]-)>","") -- strip name from tags (e. g. images as links)
   
    -- We only consider the URL valid if the name contains alphanumeric characters.
    if name:find("%w") then print(url, name, c) table.insert (addresses, {url, name}) return name.."["..#addresses.."]" else return "" end   
  end)

  -- Nuke all other tags now.
  text = string.gsub (text, "(%b<>)","")
 
  -- Replace entities to their correspondant stuff where applicable.
  -- C# is owned badly here by using a table. :-P
  -- A metatable secures entities, so you can add them natively as keys.
  -- Enclosing brackets also get added automatically (capture!)
  local entities = {}
  setmetatable (entities,
  {
    __newindex = function (tbl, key, value)
      key = string.gsub (key, "(%#)" , "%%#")
      key = string.gsub (key, "(%&)" , "%%&")
      key = string.gsub (key, "(%;)" , "%%;")
      key = string.gsub (key, "(.+)" , "("..key..")")
      rawset (tbl, key, value)
    end
  })
  entities =
  {
    [" "] = " ",
    ["•"] = " *  ",
    ["‹"] = "<",
    ["›"] = ">",
    ["™"] = "(tm)",
    ["⁄"] = "/",
    ["<"] = "<",
    [">"] = ">",
    ["©"] = "(c)",
    ["®"] = "(r)",
    -- Then kill all others.
    -- You can customize this table if you would like to,
    -- I just got bored of copypasting. :-)
    -- http://hotwired.lycos.com/webmonkey/reference/special_characters/
    ["%&.+%;"] = "",
  }
  for entity, repl in pairs (entities) do
    text = string.gsub (text, entity, repl)
  end
--   text = text..nl..nl..("-"):rep(27)..nl..nl
--   
--   for k,v in ipairs (addresses) do
--     text = text.."["..k.."] "..v[1]..nl
--   end
  if #addresses > 0 then
    text=text..nl:rep(2)..("-"):rep(2)..nl
    for key, tbl in ipairs(addresses) do
      text = text..nl.."["..key.."]"..tbl[1]
    end
  end
 
  return text
 
end

local f=io.open(filename..".txt", "w")
f:write(HTML_ToText (filename))
f:close()

--[[
Copyright (c) 2007, bastya_elvtars

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 the author nor the names of contributors may be used
      to endorse or promote products derived from this code without specific
      prior written permission.

THIS CODE 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
CODE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
]]
Сайт kolibrios.org выглядит так:

Code: Select all

 KolibriOS 0.7.7.0       

 	 KolibriOS 0.7.7.0   

 	 previous releases[1]   

 	 Kolibri is a small x86 assembler hobby operating system. It forked off MenuetOS[2] in 2004 and has mostly been developed by ex-USSR community since. API and ABI is being enreached with developer-friendly features. User interface is not that good yet but we are trying to improve it as well. Your feedback is very appreciated, although help would always be much more valuable.   

 	      

 	 Current 0.7.7.0 release introduces several kernel, applications and libraries updates. We thank everyone participated and tried making this release a better one. Huge networking code changes, ATI video driver, HTMLV and DOWNLOADER integration for convenient web browsing and many other improvements - that is what we would like to get you excited today. Full list of changes could be found at a special wiki page[3].   

 	   	 Floppy image to be used for various virtual machines, writing on diskette or putting to hard disk to boot from.  	     

 	   	 Compact disk (LiveCD) image to be used for various virtual machines or burning to CDs to boot from.  	     

 	   	 Kernel, applications and libraries source code at the time of release.  	    

 	   	 Software development kit (SDK) for people interested in developing applications for Kolibri.  	    

 	 For feedback and support, please visit our bug-tracker[4], forums[5] or IRC channel[6]. You can also drop us an e-mail[7].   

 	  2004-2009 KolibriOS team    

--

[1]http://kolibrios.org/releases.html
[2]http://menuetos.net/
[3]http://wiki.kolibrios.org/wiki/changes_in_0770
[4]http://bugs.kolibrios.org/
[5]http://board.kolibrios.org/
[6]irc://irc.freenode.net/kolibrios

Как запустить эти программы в Колибри:
Spoiler:1. Код каждой из программ нужно сохранить в отдельный файл с любым именем. Неплохой идеей будет сделать у этого файла расширение lua, но это не обязательно.
2. Затем нужно взять файл lua.kex, выложенный в этой теме на прошлой странице (он в архиве lua52.7z).
3. Для работы программ нужны xml и html файлы. В качестве xml подойдет, например, какой-нибудь svg рисунок. В качестве htm - любая веб-страница htm.
4. Сейчас xml-парсер открывает picture.svg, а html-парсер - kolibri.html, но это можно изменить, исправив исходный код.
5. Нужно поместить файлы на дискету с Колибри, или же упаковать в образ дискеты для загрузки. А можно просто положить эти файлы на жесткий диск, который видится в Колибри - все в одну папку. (Я пользуюсь qemu и образом дискеты,а добавляю файлы в образ командой mcopy)
6. Теперь нужно загрузиться в Колибри, запустить программу RUN и дать команду:
/путь/к/папке/в/которой/всё/лежит/lua.kex имя_программы

Например, если вы сохранили html-парсер в файл html.lua, и положили все файлы на рам-диск, то команда будет такой:
/rd/1/lua.kex html.lua

Результат работы HTML-парсера - файл с тем же именем, что и исходная страница, но с расширением txt.
Результат работы XML-парсера выводится на доску отладки. Если он будет "1 table 2 table 3 table", то это нормально.

Re: Порт LUA

Posted: Sun Mar 13, 2011 10:52 pm
by kogemyaka
Маленький вопрос: как правильно использовать for ... do ... end

Я так понял

Code: Select all

i=1
k=5
step=1

For i,k,step, do .... end
Т.е. это будет эквивалентно

Code: Select all

for i:=1 to 5 step 1 do ...

Re: Порт LUA

Posted: Sun Mar 13, 2011 11:03 pm
by SoUrcerer
Синтаксис for выглядит так:
for i=start,end,step do ... end

Руководство на русском языке есть на lua.ru, оно подходит практически полностью (только в lua 4 другие команды работы с файлами, а в 5.2 еще нет части нужных функций).

p.s. неясно, почему не работает require, хотя это может быть вызвано тем, что компилировался ansi-вариант, ОС-независимый, и внешние библиотеки могут отсутствовать как класс.

Re: Порт LUA

Posted: Mon Mar 14, 2011 11:10 am
by SoUrcerer
Свеженькая версия lua 5.2 с поддержкой некоторых функций Колибри. В архиве так же "учебный" калькулятор на lua.
lua52-lib.7z (92.6 KiB)
Downloaded 327 times

Функции Колибри ОС (изменений по сравнению с версией lua4lib мало):
paintstart() --начать перерисовку
paintend() --закончить перерисовку
window(10,10,153,180,65069280) --задать окно
textout(3,13,0,"LuaCalc") --вывести текст
makebutton(6,60,20,20,17,13619151) --создать/удалить кнопку
waitevent() --ждать события
checkevent() --проверить наличие нового события
getkey() --получить код нажатой клавиши
getbutton() --получить код нажатой кнопки
sysexit() --завершить программу

Команда print теперь выводит текст на доску отладки.
Какие еще функции системы нужны /я имею в виду в первую очередь/?

Re: Порт LUA

Posted: Mon Mar 14, 2011 11:49 am
by kogemyaka
Получение текущего времени и даты.