Lion4ever

Read Only Tables

May 31st, 2015
461
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.09 KB | None | 0 0
  1. local blockTables = {getfenv()}
  2. --local blockTables = {_G,getfenv()} --blocks _G even in a sub program
  3.  
  4. local FakeToRealTableMap = {} --shadowTable: fake --> orig mapping
  5. local RealToFakeTableMap = {} --reverse
  6.  
  7. local tEnv
  8.  
  9. local ErrorOnIndex = function( tableToIndex,key,value )
  10.   error(
  11.     string.format( "attempt to %s global %s %q%s",
  12.       FakeToRealTableMap[ tableToIndex ] and FakeToRealTableMap[ tableToIndex ][ key ] ~= nil and "change" or "create",
  13.       type( FakeToRealTableMap[ tableToIndex ] and FakeToRealTableMap[ tableToIndex ][ key ] or value ),
  14.       key or "Unknown",tableToIndex==_G and " in _G" or ( tableToIndex==getfenv(  ) or tableToIndex==tEnv ) and " in the current environment" or ""
  15.      ),
  16.   2 )
  17. end
  18. local writeBlockingMetatable
  19. local createNewBlockedTable = function(  ) return setmetatable( {},writeBlockingMetatable ) end
  20. local localType = type
  21. local blockingIndex = function( tableToIndex,key )
  22.   if localType( FakeToRealTableMap[ tableToIndex ][ key ] ) == "table" then
  23.     if RealToFakeTableMap[ FakeToRealTableMap[ tableToIndex ][ key ] ] then
  24.       return RealToFakeTableMap[ FakeToRealTableMap[ tableToIndex ][ key ] ]
  25.     else
  26.       local newBlockedTable = createNewBlockedTable(  )
  27.       FakeToRealTableMap[ newBlockedTable ] = FakeToRealTableMap[ tableToIndex ][ key ]
  28.       RealToFakeTableMap[ FakeToRealTableMap[ tableToIndex ][ key ] ] = newBlockedTable
  29.       return newBlockedTable
  30.     end
  31.   else
  32.     return FakeToRealTableMap[ tableToIndex ][ key ]
  33.   end
  34. end
  35. writeBlockingMetatable = {__index=blockingIndex,__newindex=ErrorOnIndex,__metatable="Allready used"}
  36.  
  37. local args = {...}
  38.  
  39. local localPairs=pairs
  40. local localRawset = rawset
  41. local localGetmetatable = getmetatable
  42. local localSetmetatable = setmetatable
  43. local localNext = _G.next
  44. _G.setmetatable = function( ... ) return select( 2,pcall( localSetmetatable,... ) ) end
  45.  
  46. if #args > 0 then
  47. local env = {shell=shell,multishell=multishell}
  48. setmetatable( env,{__index=_G} )
  49. tEnv = createNewBlockedTable(  )
  50. FakeToRealTableMap[ tEnv ] = env
  51. RealToFakeTableMap[ env ] = tEnv
  52. os.run( tEnv,shell.resolveProgram( args[ 1 ] ),unpack( args,2 ) )
  53. _G.setmetatable = localSetmetatable
  54. return
  55. end
  56.  
  57. _G.next = function( tableToIndex,key )
  58.   if FakeToRealTableMap[ tableToIndex ] then
  59.     return localNext( FakeToRealTableMap[ tableToIndex ],key )
  60.   else
  61.     return localNext( tableToIndex,key )
  62.   end
  63. end
  64. _G.pairs = function( tableToIndex ) return _G.next,tableToIndex,nil end
  65.  
  66. local CopyOfTable
  67. for taskNumber,oTable in localPairs( blockTables ) do
  68.   CopyOfTable = {}
  69.   for i,j in localPairs( oTable ) do
  70.     CopyOfTable[ i ] = j
  71.   end
  72.   FakeToRealTableMap[ oTable ]= CopyOfTable
  73.   RealToFakeTableMap[ CopyOfTable ] = oTable
  74.   local oldMeta = localGetmetatable( oTable )
  75.   if oldMeta and type( oldMeta.__index ) == "table" then
  76.     setmetatable( CopyOfTable,FakeToRealTableMap[ oldMeta.__index ] and rawset( oldMeta,"__index",FakeToRealTableMap[ oldMeta.__index ] ) or oldMeta )
  77.   end
  78.   setmetatable( oTable,writeBlockingMetatable )
  79.   for i in localPairs( CopyOfTable ) do
  80. localRawset( oTable,i,nil )
  81.   end
  82. end
Advertisement
Add Comment
Please, Sign In to add comment