[Iup-users] interpreter crash

Merick Merick_TeVaran at comcast.net
Mon Oct 8 20:53:28 GMT+3 2007


Alright, I'm having  trouble with my script crashing my interpreter in 
winXP. I'm trying to use the table.save functions from the code snippets 
in the lua users wiki:

http://lua-users.org/wiki/SaveTableToFile

When I use this with a a generic test script in my interpreter, it works 
fine. However, when I attempt to use it with a filename taken from an 
iup.filedlg popup, it crashes with a genereic error from winXP. Here's 
my code, I know it's a bit of a mess if someone could take a look at it 
(i've marked the spot where the crash happens)?

    --[[
       Save Table to File/Stringtable
       Load Table from File/Stringtable
       v 0.94
      
       Lua 5.1 compatible
      
       Userdata and indices of these are not saved
       Functions are saved via string.dump, so make sure it has no upvalues
       References are saved
       ----------------------------------------------------
       table.save( table [, filename] )
      
       Saves a table so it can be called via the table.load function again
       table must a object of type 'table'
       filename is optional, and may be a string representing a filename 
or true/1
      
       table.save( table )
          on success: returns a string representing the table (stringtable)
          (uses a string as buffer, ideal for smaller tables)
       table.save( table, true or 1 )
          on success: returns a string representing the table (stringtable)
          (uses io.tmpfile() as buffer, ideal for bigger tables)
       table.save( table, "filename" )
          on success: returns 1
          (saves the table to file "filename")
       on failure: returns as second argument an error msg
       ----------------------------------------------------
       table.load( filename or stringtable )
      
       Loads a table that has been saved via the table.save function
      
       on success: returns a previously saved table
       on failure: returns as second argument an error msg
       ----------------------------------------------------
      
       chillcode, http://lua-users.org/wiki/SaveTableToFile
       Licensed under the same terms as Lua itself.
    ]]--
    do
       -- declare local variables
       --// exportstring( string )
       --// returns a "Lua" portable version of the string
       local function exportstring( s )
          s = string.format( "%q",s )
          -- to replace
          s = string.gsub( s,"\\\n","\\n" )
          s = string.gsub( s,"\r","\\r" )
          s = string.gsub( s,string.char(26),"\"..string.char(26)..\"" )
          return s
       end
    --// The Save Function
    function table.save(  tbl,filename )
       local charS,charE = "   ","\n"
       local file,err
       -- create a pseudo file that writes to a string and return the string
       if not filename then
          file =  { write = function( self,newstr ) self.str = 
self.str..newstr end, str = "" }
          charS,charE = "",""
       -- write table to tmpfile
       elseif filename == true or filename == 1 then
          charS,charE,file = "","",io.tmpfile()
       -- write table to file
       -- use io.open here rather than io.output, since in windows when 
clicking on a file opened with io.output will create an error
       else
          file,err = io.open( filename, "w" )
          if err then return _,err end
       end
       -- initiate variables for save procedure
       local tables,lookup = { tbl },{ [tbl] = 1 }
       file:write( "return {"..charE )
       for idx,t in ipairs( tables ) do
          if filename and filename ~= true and filename ~= 1 then
             file:write( "-- Table: {"..idx.."}"..charE )
          end
          file:write( "{"..charE )
          local thandled = {}
          for i,v in ipairs( t ) do
             thandled[i] = true
             -- escape functions and userdata
             if type( v ) ~= "userdata" then
                -- only handle value
                if type( v ) == "table" then
                   if not lookup[v] then
                      table.insert( tables, v )
                      lookup[v] = #tables
                   end
                   file:write( charS.."{"..lookup[v].."},"..charE )
                elseif type( v ) == "function" then
                   file:write( 
charS.."loadstring("..exportstring(string.dump( v )).."),"..charE )
                else
                   local value =  ( type( v ) == "string" and 
exportstring( v ) ) or tostring( v )
                   file:write(  charS..value..","..charE )
                end
             end
          end
          for i,v in pairs( t ) do
             -- escape functions and userdata
             if (not thandled[i]) and type( v ) ~= "userdata" then
                -- handle index
                if type( i ) == "table" then
                   if not lookup[i] then
                      table.insert( tables,i )
                      lookup[i] = #tables
                   end
                   file:write( charS.."[{"..lookup[i].."}]=" )
                else
                   local index = ( type( i ) == "string" and 
"["..exportstring( i ).."]" ) or string.format( "[%d]",i )
                   file:write( charS..index.."=" )
                end
                -- handle value
                if type( v ) == "table" then
                   if not lookup[v] then
                      table.insert( tables,v )
                      lookup[v] = #tables
                   end
                   file:write( "{"..lookup[v].."},"..charE )
                elseif type( v ) == "function" then
                   file:write( "loadstring("..exportstring(string.dump( 
v )).."),"..charE )
                else
                   local value =  ( type( v ) == "string" and 
exportstring( v ) ) or tostring( v )
                   file:write( value..","..charE )
                end
             end
          end
          file:write( "},"..charE )
       end
       file:write( "}" )
       -- Return Values
       -- return stringtable from string
       if not filename then
          -- set marker for stringtable
          return file.str.."--|"
       -- return stringttable from file
       elseif filename == true or filename == 1 then
          file:seek ( "set" )
          -- no need to close file, it gets closed and removed automatically
          -- set marker for stringtable
          return file:read( "*a" ).."--|"
       -- close file and return 1
       else
          file:close()
          return 1
       end
    end

    --// The Load Function
    function table.load( sfile )
       -- catch marker for stringtable
       if string.sub( sfile,-3,-1 ) == "--|" then
          tables,err = loadstring( sfile )
       else
          tables,err = loadfile( sfile )
       end
       if err then return _,err
       end
       tables = tables()
       for idx = 1,#tables do
          local tolinkv,tolinki = {},{}
          for i,v in pairs( tables[idx] ) do
             if type( v ) == "table" and tables[v[1]] then
                table.insert( tolinkv,{ i,tables[v[1]] } )
             end
             if type( i ) == "table" and tables[i[1]] then
                table.insert( tolinki,{ i,tables[i[1]] } )
             end
          end
          -- link values, first due to possible changes of indices
          for _,v in ipairs( tolinkv ) do
             tables[idx][v[1]] = v[2]
          end
          -- link indices
          for _,v in ipairs( tolinki ) do
             tables[idx][v[2]],tables[idx][v[1]] =  tables[idx][v[1]],nil
          end
       end
       return tables[1]
    end
    -- close do
    end



-- my editor code starts here

iup.SetLanguage("ENGLISH")

lfs.chdir(exepath()..[[\scripts]])
current_file = lfs.currentdir()..[[\new.lua]]
file_tab = {}
function setdir()
    local pos     = 0
    local current = 0

    repeat
          current = string.find(current_file, [[\]], pos)
          if current ~= nil then pos = current + 1 end
    until (current == nil)

    current_dir = string.gsub (current_file, string.sub (current_file, 
pos-1), [[]])
    lfs.chdir(current_dir)
    return current_dir
end   


open_dlg = iup.filedlg{dialogtype = "OPEN", title = "Open Lua Script",
                      filter = "*.lua", filterinfo = "Lua Scripts",
                      directory = setdir()}

save_as_dlg = iup.filedlg{dialogtype = "SAVE", title = "Save Lua Script",
                      filter = "*.lua", filterinfo = "Lua Scripts",
                      directory = setdir()}

item_new = iup.item {title = "New", key = "N"}
item_open = iup.item {title = "Open", key = "O"}
item_save = iup.item {title = "Save", key = "S"}
item_save_as = iup.item {title = "Save As", key = "A"}
item_exit = iup.item {title = "Exit", key = "x"}

function item_new:action()
    edit_box.value = ""
    current_file = nil
    return iup.DEFAULT
end

function item_open:action()
    open_dlg:popup (iup.CENTER, iup.CENTER)
    if open_dlg.status == "0" and open_dlg.fileexist == "YES" then
        current_file = open_dlg.value
        c_file_name = string.gsub(current_file, ".+\\", "")
        local file = io.open(open_dlg.value, "r")
        local text = file:read("*a")
        edit_box.value = text
        file:close()
        dlg.title = c_file_name
    end
    open_dlg.directory = setdir()
    return iup.DEFAULT
end

function item_save:action()
    if current_file:find("new.lua") or current_file == nil then
        save_as_dlg:popup (iup.CENTER, iup.CENTER)
        if save_as_dlg.status ~= "-1" then
            current_file = save_as_dlg.value
            setdir()
        end
    end
   
    save_file(current_file, edit_box.value)

    return iup.DEFAULT
end

function item_save_as:action()
    save_as_dlg.file = current_file
    save_as_dlg:popup (iup.CENTER, iup.CENTER)
    if save_as_dlg.status ~= "-1" then
        current_file = save_as_dlg.value
        c_file_name = string.gsub(current_file, ".+\\", "")
        dlg.title = c_file_name
        save_file(current_file, edit_box.value)
        setdir(current_file)
    end
    return iup.DEFAULT
end

function item_exit:action()
  return iup.CLOSE
end


-- function to save files
function save_file(file_name, file_text)
    local file = io.open(file_name, "w+")
    file:write(file_text)
    file:flush()
    file:close()
end   

item_run_fblua = iup.item {title = "with FB Lua", key = "F"}
item_run_luaplayer = iup.item {title = "with Lua Player", key = "L"}

--run with fblua menu item
function item_run_fblua:action()
    save_file("luatemp.lua", edit_box.value)
    msgs, errmsg = io.popen(exepath().."\\fblua luatemp.lua catch")
    if msgs then
        error_box.value = error_box.value.."\n\nFB Lua output:"
        for Line in msgs:lines() do
            error_box.value = error_box.value.."\n"..Line
        end
        msgs:close()
    else
        error_box.value = error_box.value.."\n"..errmsg
    end
    os.remove("luatemp.lua")
    return iup.DEFAULT
end

--run with lua player menu item
function item_run_luaplayer:action()
    save_file("luatemp.lua", edit_box.value)
    msgs, errmsg = 
io.popen(exepath().."\\luaplayerwindows\\luaplayer.exe luatemp.lua")
    if msgs then
        error_box.value = error_box.value.."\n\nLua Player output:"
        for Line in msgs:lines() do
            error_box.value = error_box.value.."\n"..Line
        end
        msgs:close()
    else
        error_box.value = error_box.value.."\n"..errmsg
    end
    os.remove("luatemp.lua")
    return iup.DEFAULT
end

edit_box = iup.multiline{
        size = "400x250",
        value = "" ,
        expand = "YES",
        tabsize = "15",
        font = "COURIER_NORMAL_12"
    }

error_label = iup.label{title="Interpreter output:"}
error_box = iup.multiline{
        size = "x50",
        value = "" ,
        expand = "YES",
        tabsize = "15",
        font = "COURIER_NORMAL_12",
        readonly = "YES"
    }
error_b = iup.sbox{iup.vbox{error_label,error_box}, direction = "NORTH"}

color_mat = iup.matrix{numcol=8, numlin=32, numcol_visible=8, 
numlin_visible=8, widthdef=5, alignment = "ACENTER"}
function color_mat:action_cb() return iup.IGNORE end
function color_mat:click_cb(line, col, button)
    if tonumber(button) == 3 then
        r, g, b = iup.GetColor(iup.CENTER,iup.CENTER, 255, 255, 255)
        if r ~= nil then
            name = iup.Scanf("Name This Color:\nName:%15.15%s\n","")
            self["BGCOLOR"..line..":"..col] = r.." "..g.." "..b
            colors[line][col].name = name
            colors[line][col].red = r
            colors[line][col].green = g
            colors[line][col].blue = b
        end
    end
    self.redraw = "ALL"
    edit_box.value = line..":"..col.."  button = "..button.." color id = 
"..colors[line][col].name
    return iup.IGNORE
end

colors = {}
counter = 1
for i = 1, 32 do
    colors[i] = {}
    for j = 1, 8 do
        colors[i][j] = {id = counter, name = "", red = 255, green = 255, 
blue = 255}
        color_mat["BGCOLOR".. i ..":".. j] = colors[i][j].red.." 
"..colors[i][j].green.." "..colors[i][j].blue
        counter = counter +1
    end
end

color_save = iup.button{title = "Save Colors"}
save_colors = iup.filedlg{dialogtype = "SAVE", title = "Save Custom 
Color file",
                      filter = "*.cf", filterinfo = "Color File",
                      file = exepath().."/apps/editor/colors.cf"
                      }
                     
function color_save.action()
    save_colors:popup (iup.CENTER, iup.CENTER)
        if save_colors.status ~= "-1" then
------------------------------------------------
            table.save(colors, save_colors.value)    ----- this line is 
where it  crashes
------------------------------------------------
        end
end

color_load = iup.button{title = "Load Colors"}
function color_load.action()
    open_dlg:popup (iup.CENTER, iup.CENTER)
    if open_dlg.status == "0" and open_dlg.fileexist == "YES" then
        colors = nil
        colors = table.load(open_dlg.value)
    end
end


color_tab = iup.vbox{
        color_mat,
        color_save,
        color_load,
        expand = "NO",
        tabtitle = "Colors"
    }



-- assemble menu items
submenu_file = iup.submenu {iup.menu {item_new, item_open, item_save, 
item_save_as, iup.separator{}, item_exit}; title = "File"}
submenu_run = iup.submenu {iup.menu {item_run_fblua, 
item_run_luaplayer}; title = "Run"}

-- assemble dialog elements
menu = iup.menu {submenu_file, submenu_run}
func_panel = iup.sbox{iup.tabs{color_tab}, direction = "WEST"}
main_panel = iup.vbox{edit_box, error_b}
main_frame = iup.hbox{main_panel, func_panel}

dlg = iup.dialog{main_frame; title="FB Lua Script Editor", menu=menu, 
error_box}

-- shows the editor window
dlg:showxy(iup.CENTER,iup.CENTER)
edit_box.size = "" -- removes initial size from the edit box, allowing 
it to be resized

-- blocks the script while allowing the dialogs to remain interactive
iup.MainLoop()

dlg:destroy()



More information about the iup-users mailing list