Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local index_table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
- local arg = {...}
- if shell then
- arg[0] = shell.getRunningProgram()
- elseif not arg[0] then
- arg[0] = "gunzip"
- end
- local computercraft = false
- if not io.stdin then
- io.stdin = io.input()
- end
- if not fs then
- fs = {}
- function fs.makeDir()
- -- nothing
- return 1
- end
- end
- if not io.stdout then
- io.stdout = io.output()
- end
- if not io.stderr then
- io.stderr = io.output()
- end
- if not os.exit then
- os.exit = error
- end
- if os.loadAPI then
- computercraft = true
- end
- if not os.remove then
- os.remove = function (t) fs.delete(t) return true end
- end
- function to_binary(integer)
- local remaining = tonumber(integer)
- local bin_bits = ''
- for i = 7, 0, -1 do
- local current_power = math.pow(2, i)
- if remaining >= current_power then
- bin_bits = bin_bits .. '1'
- remaining = remaining - current_power
- else
- bin_bits = bin_bits .. '0'
- end
- end
- return bin_bits
- end
- function from_binary(bin_bits)
- return tonumber(bin_bits, 2)
- end
- function to_base64(to_encode)
- local bit_pattern = ''
- local encoded = ''
- local trailing = ''
- for i = 1, string.len(to_encode) do
- bit_pattern = bit_pattern .. to_binary(string.byte(string.sub(to_encode, i, i)))
- end
- -- Check the number of bytes. If it's not evenly divisible by three,
- -- zero-pad the ending & append on the correct number of ``=``s.
- if math.mod(string.len(bit_pattern), 3) == 2 then
- trailing = '=='
- bit_pattern = bit_pattern .. '0000000000000000'
- elseif math.mod(string.len(bit_pattern), 3) == 1 then
- trailing = '='
- bit_pattern = bit_pattern .. '00000000'
- end
- for i = 1, string.len(bit_pattern), 6 do
- local byte = string.sub(bit_pattern, i, i+5)
- local offset = tonumber(from_binary(byte))
- encoded = encoded .. string.sub(index_table, offset+1, offset+1)
- end
- return string.sub(encoded, 1, -1 - string.len(trailing)) .. trailing
- end
- function from_base64(to_decode)
- local padded = to_decode:gsub("%s", "")
- local unpadded = padded:gsub("=", "")
- local bit_pattern = ''
- local decoded = ''
- for i = 1, string.len(unpadded) do
- local char = string.sub(to_decode, i, i)
- local offset, _ = string.find(index_table, char)
- if offset == nil then
- error("Invalid character '" .. char .. "' found.")
- end
- bit_pattern = bit_pattern .. string.sub(to_binary(offset-1), 3)
- end
- for i = 1, string.len(bit_pattern), 8 do
- local byte = string.sub(bit_pattern, i, i+7)
- decoded = decoded .. string.char(from_binary(byte))
- end
- local padding_length = padded:len()-unpadded:len()
- if (padding_length == 1 or padding_length == 2) then
- decoded = decoded:sub(1,-2)
- end
- return decoded
- end
- function optparse()
- --[[
- LUA MODULE
- pythonic.optparse - Lua-based partial reimplementation of Python's
- optparse [2-3] command-line parsing module.
- SYNOPSIS
- local OptionParser = require "pythonic.optparse" . OptionParser
- local opt = OptionParser{usage="%prog [options] [gzip-file...]",
- version="foo 1.23", add_help_option=false}
- opt.add_option{"-h", "--help", action="store_true", dest="help",
- help="give this help"}
- opt.add_option{
- "-f", "--force", dest="force", action="store_true",
- help="force overwrite of output file"}
- local options, args = opt.parse_args()
- if options.help then opt.print_help(); os.exit(1) end
- if options.force then print 'f' end
- for _, name in ipairs(args) do print(name) end
- DESCRIPTION
- This library provides a command-line parsing[1] similar to Python optparse [2-3].
- Note: Python also supports getopt [4].
- STATUS
- This module is fairly basic but could be expanded.
- API
- See source code and also compare to Python's docs [2,3] for details because
- the following documentation is incomplete.
- opt = OptionParser {usage=usage, version=version, add_help_option=add_help_option}
- Create command line parser.
- opt.add_options{shortflag, longflag, action=action, metavar=metavar, dest=dest, help=help}
- Add command line option specification. This may be called multiple times.
- opt.parse_args() --> options, args
- Perform argument parsing.
- DEPENDENCIES
- None (other than Lua 5.1 or 5.2)
- REFERENCES
- [1] http://lua-users.org/wiki/CommandLineParsing
- [2] http://docs.python.org/lib/optparse-defining-options.html
- [3] http://blog.doughellmann.com/2007/08/pymotw-optparse.html
- [4] http://docs.python.org/lib/module-getopt.html
- LICENSE
- (c) 2008-2011 David Manura. Licensed under the same terms as Lua (MIT).
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- (end license)
- --]]
- local M = {_TYPE='module', _NAME='pythonic.optparse', _VERSION='0.3.20111128'}
- local ipairs = ipairs
- local unpack = table.unpack
- local io = io
- local table = table
- local os = os
- local arg = arg
- local function OptionParser(t)
- local usage = t.usage
- --local version = t.version
- local o = {}
- local option_descriptions = {}
- local option_of = {}
- function o.fail(s) -- extension
- io.stderr:write(s .. '\n')
- os.exit(1)
- end
- function o.add_option(optdesc)
- option_descriptions[#option_descriptions+1] = optdesc
- for _,v in ipairs(optdesc) do
- option_of[v] = optdesc
- end
- end
- function o.parse_args()
- -- expand options (e.g. "--input=file" -> "--input", "file")
- local arg = {unpack(arg)}
- for i=#arg,1,-1 do local v = arg[i]
- local flag, val = v:match('^(%-%-%w+)=(.*)')
- if flag then
- arg[i] = flag
- table.insert(arg, i+1, val)
- end
- end
- local options = {}
- local args = {}
- local i = 1
- while i <= #arg do local v = arg[i]
- local optdesc = option_of[v]
- if optdesc then
- local action = optdesc.action
- local val
- if action == 'store' or action == nil then
- i = i + 1
- val = arg[i]
- if not val then o.fail('option requires an argument ' .. v) end
- elseif action == 'store_true' then
- val = true
- elseif action == 'store_false' then
- val = false
- end
- options[optdesc.dest] = val
- else
- if v:match('^%-') then o.fail('invalid option ' .. v) end
- args[#args+1] = v
- end
- i = i + 1
- end
- if options.help then
- o.print_help()
- os.exit()
- end
- if options.version then
- print(t.version+"\n")
- os.exit()
- end
- return options, args
- end
- local function flags_str(optdesc)
- local sflags = {}
- local action = optdesc.action
- for _,flag in ipairs(optdesc) do
- local sflagend
- if action == nil or action == 'store' then
- local metavar = optdesc.metavar or optdesc.dest:upper()
- sflagend = #flag == 2 and ' ' .. metavar
- or '=' .. metavar
- else
- sflagend = ''
- end
- sflags[#sflags+1] = flag .. sflagend
- end
- return table.concat(sflags, ', ')
- end
- function o.print_help()
- print("Usage: " .. usage:gsub('%%prog', arg[0]) .. "\n")
- print("\n")
- print("Options:\n")
- local maxwidth = 0
- for _,optdesc in ipairs(option_descriptions) do
- maxwidth = math.max(maxwidth, #flags_str(optdesc))
- end
- for _,optdesc in ipairs(option_descriptions) do
- print(" " .. ('%-'..maxwidth..'s '):format(flags_str(optdesc))
- .. optdesc.help .. "\n")
- end
- end
- if t.add_help_option == nil or t.add_help_option == true then
- o.add_option{"--help", action="store_true", dest="help",
- help="show this help message and exit"}
- end
- if t.version then
- o.add_option{"--version", action="store_true", dest="version",
- help="output version info."}
- end
- return o
- end
- M.OptionParser = OptionParser
- return M
- end
- function numberlua()
- --[[
- LUA MODULE
- bit.numberlua - Bitwise operations implemented in pure Lua as numbers,
- with Lua 5.2 'bit32' and (LuaJIT) LuaBitOp 'bit' compatibility interfaces.
- --]]
- local M = {_TYPE='module', _NAME='bit.numberlua', _VERSION='0.3.1.20120131'}
- local floor = math.floor
- local MOD = 2^32
- local MODM = MOD-1
- local function memoize(f)
- local mt = {}
- local t = setmetatable({}, mt)
- function mt:__index(k)
- local v = f(k); t[k] = v
- return v
- end
- return t
- end
- local function make_bitop_uncached(t, m)
- local function bitop(a, b)
- local res,p = 0,1
- while a ~= 0 and b ~= 0 do
- local am, bm = a%m, b%m
- res = res + t[am][bm]*p
- a = (a - am) / m
- b = (b - bm) / m
- p = p*m
- end
- res = res + (a+b)*p
- return res
- end
- return bitop
- end
- local function make_bitop(t)
- local op1 = make_bitop_uncached(t,2^1)
- local op2 = memoize(function(a)
- return memoize(function(b)
- return op1(a, b)
- end)
- end)
- return make_bitop_uncached(op2, 2^(t.n or 1))
- end
- -- ok? probably not if running on a 32-bit int Lua number type platform
- function M.tobit(x)
- return x % 2^32
- end
- M.bxor = make_bitop {[0]={[0]=0,[1]=1},[1]={[0]=1,[1]=0}, n=4}
- local bxor = M.bxor
- function M.bnot(a) return MODM - a end
- local bnot = M.bnot
- function M.band(a,b) return ((a+b) - bxor(a,b))/2 end
- local band = M.band
- function M.bor(a,b) return MODM - band(MODM - a, MODM - b) end
- local bor = M.bor
- local lshift, rshift -- forward declare
- function M.rshift(a,disp) -- Lua5.2 insipred
- if disp < 0 then return lshift(a,-disp) end
- return floor(a % 2^32 / 2^disp)
- end
- rshift = M.rshift
- function M.lshift(a,disp) -- Lua5.2 inspired
- if disp < 0 then return rshift(a,-disp) end
- return (a * 2^disp) % 2^32
- end
- lshift = M.lshift
- function M.tohex(x, n) -- BitOp style
- n = n or 8
- local up
- if n <= 0 then
- if n == 0 then return '' end
- up = true
- n = - n
- end
- x = band(x, 16^n-1)
- return ('%0'..n..(up and 'X' or 'x')):format(x)
- end
- local tohex = M.tohex
- function M.extract(n, field, width) -- Lua5.2 inspired
- width = width or 1
- return band(rshift(n, field), 2^width-1)
- end
- local extract = M.extract
- function M.replace(n, v, field, width) -- Lua5.2 inspired
- width = width or 1
- local mask1 = 2^width-1
- v = band(v, mask1) -- required by spec?
- local mask = bnot(lshift(mask1, field))
- return band(n, mask) + lshift(v, field)
- end
- local replace = M.replace
- function M.bswap(x) -- BitOp style
- local a = band(x, 0xff); x = rshift(x, 8)
- local b = band(x, 0xff); x = rshift(x, 8)
- local c = band(x, 0xff); x = rshift(x, 8)
- local d = band(x, 0xff)
- return lshift(lshift(lshift(a, 8) + b, 8) + c, 8) + d
- end
- local bswap = M.bswap
- function M.rrotate(x, disp) -- Lua5.2 inspired
- disp = disp % 32
- local low = band(x, 2^disp-1)
- return rshift(x, disp) + lshift(low, 32-disp)
- end
- local rrotate = M.rrotate
- function M.lrotate(x, disp) -- Lua5.2 inspired
- return rrotate(x, -disp)
- end
- local lrotate = M.lrotate
- M.rol = M.lrotate -- LuaOp inspired
- M.ror = M.rrotate -- LuaOp insipred
- function M.arshift(x, disp) -- Lua5.2 inspired
- local z = rshift(x, disp)
- if x >= 0x80000000 then z = z + lshift(2^disp-1, 32-disp) end
- return z
- end
- local arshift = M.arshift
- function M.btest(x, y) -- Lua5.2 inspired
- return band(x, y) ~= 0
- end
- --
- -- Start Lua 5.2 "bit32" compat section.
- --
- M.bit32 = {} -- Lua 5.2 'bit32' compatibility
- local function bit32_bnot(x)
- return (-1 - x) % MOD
- end
- M.bit32.bnot = bit32_bnot
- local function bit32_bxor(a, b, c, ...)
- local z
- if b then
- a = a % MOD
- b = b % MOD
- z = bxor(a, b)
- if c then
- z = bit32_bxor(z, c, ...)
- end
- return z
- elseif a then
- return a % MOD
- else
- return 0
- end
- end
- M.bit32.bxor = bit32_bxor
- local function bit32_band(a, b, c, ...)
- local z
- if b then
- a = a % MOD
- b = b % MOD
- z = ((a+b) - bxor(a,b)) / 2
- if c then
- z = bit32_band(z, c, ...)
- end
- return z
- elseif a then
- return a % MOD
- else
- return MODM
- end
- end
- M.bit32.band = bit32_band
- local function bit32_bor(a, b, c, ...)
- local z
- if b then
- a = a % MOD
- b = b % MOD
- z = MODM - band(MODM - a, MODM - b)
- if c then
- z = bit32_bor(z, c, ...)
- end
- return z
- elseif a then
- return a % MOD
- else
- return 0
- end
- end
- M.bit32.bor = bit32_bor
- function M.bit32.btest(...)
- return bit32_band(...) ~= 0
- end
- function M.bit32.lrotate(x, disp)
- return lrotate(x % MOD, disp)
- end
- function M.bit32.rrotate(x, disp)
- return rrotate(x % MOD, disp)
- end
- function M.bit32.lshift(x,disp)
- if disp > 31 or disp < -31 then return 0 end
- return lshift(x % MOD, disp)
- end
- function M.bit32.rshift(x,disp)
- if disp > 31 or disp < -31 then return 0 end
- return rshift(x % MOD, disp)
- end
- function M.bit32.arshift(x,disp)
- x = x % MOD
- if disp >= 0 then
- if disp > 31 then
- return (x >= 0x80000000) and MODM or 0
- else
- local z = rshift(x, disp)
- if x >= 0x80000000 then z = z + lshift(2^disp-1, 32-disp) end
- return z
- end
- else
- return lshift(x, -disp)
- end
- end
- function M.bit32.extract(x, field, ...)
- local width = ... or 1
- if field < 0 or field > 31 or width < 0 or field+width > 32 then error 'out of range' end
- x = x % MOD
- return extract(x, field, ...)
- end
- function M.bit32.replace(x, v, field, ...)
- local width = ... or 1
- if field < 0 or field > 31 or width < 0 or field+width > 32 then error 'out of range' end
- x = x % MOD
- v = v % MOD
- return replace(x, v, field, ...)
- end
- --
- -- Start LuaBitOp "bit" compat section.
- --
- M.bit = {} -- LuaBitOp "bit" compatibility
- function M.bit.tobit(x)
- x = x % MOD
- if x >= 0x80000000 then x = x - MOD end
- return x
- end
- local bit_tobit = M.bit.tobit
- function M.bit.tohex(x, ...)
- return tohex(x % MOD, ...)
- end
- function M.bit.bnot(x)
- return bit_tobit(bnot(x % MOD))
- end
- local function bit_bor(a, b, c, ...)
- if c then
- return bit_bor(bit_bor(a, b), c, ...)
- elseif b then
- return bit_tobit(bor(a % MOD, b % MOD))
- else
- return bit_tobit(a)
- end
- end
- M.bit.bor = bit_bor
- local function bit_band(a, b, c, ...)
- if c then
- return bit_band(bit_band(a, b), c, ...)
- elseif b then
- return bit_tobit(band(a % MOD, b % MOD))
- else
- return bit_tobit(a)
- end
- end
- M.bit.band = bit_band
- local function bit_bxor(a, b, c, ...)
- if c then
- return bit_bxor(bit_bxor(a, b), c, ...)
- elseif b then
- return bit_tobit(bxor(a % MOD, b % MOD))
- else
- return bit_tobit(a)
- end
- end
- M.bit.bxor = bit_bxor
- function M.bit.lshift(x, n)
- return bit_tobit(lshift(x % MOD, n % 32))
- end
- function M.bit.rshift(x, n)
- return bit_tobit(rshift(x % MOD, n % 32))
- end
- function M.bit.arshift(x, n)
- return bit_tobit(arshift(x % MOD, n % 32))
- end
- function M.bit.rol(x, n)
- return bit_tobit(lrotate(x % MOD, n % 32))
- end
- function M.bit.ror(x, n)
- return bit_tobit(rrotate(x % MOD, n % 32))
- end
- function M.bit.bswap(x)
- return bit_tobit(bswap(x % MOD))
- end
- return M
- end
- function crc32lua()
- --[[
- LUA MODULE
- digest.crc32 - CRC-32 checksum implemented entirely in Lua.
- --]]
- local M = {_TYPE='module', _NAME='digest.crc32', _VERSION='0.3.20111128'}
- local type = type
- --local require = require
- local setmetatable = setmetatable
- --[[
- Requires the first module listed that exists, else raises like `require`.
- If a non-string is encountered, it is returned.
- Second return value is module name loaded (or '').
- local function requireany(...)
- local errs = {}
- for _,name in ipairs{...} do
- if type(name) ~= 'string' then return name, '' end
- local ok, mod = pcall(require, name)
- if ok then return mod, name end
- errs[#errs+1] = mod
- end
- error(table.concat(errs, '\n'), 2)
- end
- --]]
- --local bit, name_ = requireany('bit', 'bit32', 'bit.numberlua')
- local bit = numberlua()
- local bxor = bit.bxor
- local bnot = bit.bnot
- local band = bit.band
- local rshift = bit.rshift
- -- CRC-32-IEEE 802.3 (V.42)
- local POLY = 0xEDB88320
- -- Memoize function pattern (like http://lua-users.org/wiki/FuncTables ).
- local function memoize(f)
- local mt = {}
- local t = setmetatable({}, mt)
- function mt:__index(k)
- local v = f(k); t[k] = v
- return v
- end
- return t
- end
- -- CRC table.
- local crc_table = memoize(function(i)
- local crc = i
- for _=1,8 do
- local b = band(crc, 1)
- crc = rshift(crc, 1)
- if b == 1 then crc = bxor(crc, POLY) end
- end
- return crc
- end)
- function M.crc32_byte(byte, crc)
- crc = bnot(crc or 0)
- local v1 = rshift(crc, 8)
- local v2 = crc_table[bxor(crc % 256, byte)]
- return bnot(bxor(v1, v2))
- end
- local M_crc32_byte = M.crc32_byte
- function M.crc32_string(s, crc)
- crc = crc or 0
- for i=1,#s do
- crc = M_crc32_byte(s:byte(i), crc)
- end
- return crc
- end
- local M_crc32_string = M.crc32_string
- function M.crc32(s, crc)
- if type(s) == 'string' then
- return M_crc32_string(s, crc)
- else
- return M_crc32_byte(s, crc)
- end
- end
- M.bit = bit -- bit library used
- return M
- end
- function deflatelua()
- --[[
- LUA MODULE
- compress.deflatelua - deflate (and gunzip/zlib) implemented in Lua.
- --]]
- local M = {_TYPE='module', _NAME='compress.deflatelua', _VERSION='0.3.20111128'}
- local assert = assert
- local error = error
- local ipairs = ipairs
- local pairs = pairs
- local print = print
- --local require = require
- local tostring = tostring
- local type = type
- local setmetatable = setmetatable
- local io = io
- local math = math
- local table_sort = table.sort
- local math_max = math.max
- local string_char = string.char
- --[[
- Requires the first module listed that exists, else raises like `require`.
- If a non-string is encountered, it is returned.
- Second return value is module name loaded (or '').
- local function requireany(...)
- local errs = {}
- for i = 1, select('#', ...) do local name = select(i, ...)
- if type(name) ~= 'string' then return name, '' end
- local ok, mod = pcall(require, name)
- if ok then return mod, name end
- errs[#errs+1] = mod
- end
- error(table.concat(errs, '\n'), 2)
- end
- --]]
- --local crc32 = require "digest.crc32lua" . crc32_byte
- local crc32 = crc32lua() . crc32_byte
- --local bit, name_ = requireany('bit', 'bit32', 'bit.numberlua', nil)
- local bit = numberlua()
- local DEBUG = false
- -- Whether to use `bit` library functions in current module.
- -- Unlike the crc32 library, it doesn't make much difference in this module.
- local NATIVE_BITOPS = (bit ~= nil)
- local band, lshift, rshift
- if NATIVE_BITOPS then
- band = bit.band
- lshift = bit.lshift
- rshift = bit.rshift
- end
- local function warn(s)
- io.stderr:write(s, '\n')
- end
- local function debug(...)
- print('DEBUG', ...)
- end
- local function runtime_error(s, level)
- level = level or 1
- error({s}, level+1)
- end
- local function make_outstate(outbs)
- local outstate = {}
- outstate.outbs = outbs
- outstate.window = {}
- outstate.window_pos = 1
- return outstate
- end
- local function output(outstate, byte)
- -- debug('OUTPUT:', s)
- local window_pos = outstate.window_pos
- outstate.outbs(byte)
- outstate.window[window_pos] = byte
- outstate.window_pos = window_pos % 32768 + 1 -- 32K
- end
- local function noeof(val)
- return assert(val, 'unexpected end of file')
- end
- local function hasbit(bits, bit)
- return bits % (bit + bit) >= bit
- end
- local function memoize(f)
- local mt = {}
- local t = setmetatable({}, mt)
- function mt:__index(k)
- local v = f(k)
- t[k] = v
- return v
- end
- return t
- end
- -- small optimization (lookup table for powers of 2)
- local pow2 = memoize(function(n) return 2^n end)
- --local tbits = memoize(
- -- function(bits)
- -- return memoize( function(bit) return getbit(bits, bit) end )
- -- end )
- -- weak metatable marking objects as bitstream type
- local is_bitstream = setmetatable({}, {__mode='k'})
- -- DEBUG
- -- prints LSB first
- --[[
- local function bits_tostring(bits, nbits)
- local s = ''
- local tmp = bits
- local function f()
- local b = tmp % 2 == 1 and 1 or 0
- s = s .. b
- tmp = (tmp - b) / 2
- end
- if nbits then
- for i=1,nbits do f() end
- else
- while tmp ~= 0 do f() end
- end
- return s
- end
- --]]
- local function bytestream_from_file(fh)
- local o = {}
- function o:read()
- local sb = fh:read(1)
- if not computercraft and sb then return sb:byte() end
- return sb
- end
- return o
- end
- local function bytestream_from_string(s)
- local i = 1
- local o = {}
- function o:read()
- local by
- if i <= #s then
- by = s:byte(i)
- i = i + 1
- end
- return by
- end
- return o
- end
- local function bytestream_from_function(f)
- local i = 0
- local buffer = ''
- local o = {}
- function o:read()
- i = i + 1
- if i > #buffer then
- buffer = f()
- if not buffer then return end
- i = 1
- end
- return buffer:byte(i,i)
- end
- return o
- end
- local function bitstream_from_bytestream(bys)
- local buf_byte = 0
- local buf_nbit = 0
- local o = {}
- function o:nbits_left_in_byte()
- return buf_nbit
- end
- if NATIVE_BITOPS then
- function o:read(nbits)
- nbits = nbits or 1
- while buf_nbit < nbits do
- local byte = bys:read()
- if not byte then return end -- note: more calls also return nil
- buf_byte = buf_byte + lshift(byte, buf_nbit)
- buf_nbit = buf_nbit + 8
- end
- local bits
- if nbits == 0 then
- bits = 0
- elseif nbits == 32 then
- bits = buf_byte
- buf_byte = 0
- else
- bits = band(buf_byte, rshift(0xffffffff, 32 - nbits))
- buf_byte = rshift(buf_byte, nbits)
- end
- buf_nbit = buf_nbit - nbits
- return bits
- end
- else
- function o:read(nbits)
- nbits = nbits or 1
- while buf_nbit < nbits do
- local byte = bys:read()
- if not byte then return end -- note: more calls also return nil
- buf_byte = buf_byte + pow2[buf_nbit] * byte
- buf_nbit = buf_nbit + 8
- end
- local m = pow2[nbits]
- local bits = buf_byte % m
- buf_byte = (buf_byte - bits) / m
- buf_nbit = buf_nbit - nbits
- return bits
- end
- end
- is_bitstream[o] = true
- return o
- end
- local function get_bitstream(o)
- local bs
- if is_bitstream[o] then
- return o
- elseif io.type(o) == 'file' then
- bs = bitstream_from_bytestream(bytestream_from_file(o))
- elseif type(o) == 'string' then
- bs = bitstream_from_bytestream(bytestream_from_string(o))
- elseif type(o) == 'function' then
- bs = bitstream_from_bytestream(bytestream_from_function(o))
- else
- runtime_error 'unrecognized type'
- end
- return bs
- end
- local function get_obytestream(o)
- local bs
- if io.type(o) == 'file' then
- bs = function(sbyte) if computercraft then o:write(sbyte) else o:write(string_char(sbyte)) end end
- elseif type(o) == 'function' then
- bs = o
- else
- runtime_error('unrecognized type: ' .. tostring(o))
- end
- return bs
- end
- local function HuffmanTable(init, is_full)
- local t = {}
- if is_full then
- for val,nbits in pairs(init) do
- if nbits ~= 0 then
- t[#t+1] = {val=val, nbits=nbits}
- --debug('*',val,nbits)
- end
- end
- else
- for i=1,#init-2,2 do
- local firstval, nbits, nextval = init[i], init[i+1], init[i+2]
- --debug(val, nextval, nbits)
- if nbits ~= 0 then
- for val=firstval,nextval-1 do
- t[#t+1] = {val=val, nbits=nbits}
- end
- end
- end
- end
- table_sort(t, function(a,b)
- return a.nbits == b.nbits and a.val < b.val or a.nbits < b.nbits
- end)
- -- assign codes
- local code = 1 -- leading 1 marker
- local nbits = 0
- for i,s in ipairs(t) do
- if s.nbits ~= nbits then
- code = code * pow2[s.nbits - nbits]
- nbits = s.nbits
- end
- s.code = code
- --debug('huffman code:', i, s.nbits, s.val, code, bits_tostring(code))
- code = code + 1
- end
- local minbits = math.huge
- local look = {}
- for i,s in ipairs(t) do
- minbits = math.min(minbits, s.nbits)
- look[s.code] = s.val
- end
- --for _,o in ipairs(t) do
- -- debug(':', o.nbits, o.val)
- --end
- -- function t:lookup(bits) return look[bits] end
- local msb = NATIVE_BITOPS and function(bits, nbits)
- local res = 0
- for i=1,nbits do
- res = lshift(res, 1) + band(bits, 1)
- bits = rshift(bits, 1)
- end
- return res
- end or function(bits, nbits)
- local res = 0
- for i=1,nbits do
- local b = bits % 2
- bits = (bits - b) / 2
- res = res * 2 + b
- end
- return res
- end
- local tfirstcode = memoize(
- function(bits) return pow2[minbits] + msb(bits, minbits) end)
- function t:read(bs)
- local code = 1 -- leading 1 marker
- local nbits = 0
- while 1 do
- if nbits == 0 then -- small optimization (optional)
- code = tfirstcode[noeof(bs:read(minbits))]
- nbits = nbits + minbits
- else
- local b = noeof(bs:read())
- nbits = nbits + 1
- code = code * 2 + b -- MSB first
- --[[NATIVE_BITOPS
- code = lshift(code, 1) + b -- MSB first
- --]]
- end
- --debug('code?', code, bits_tostring(code))
- local val = look[code]
- if val then
- --debug('FOUND', val)
- return val
- end
- end
- end
- return t
- end
- local function parse_gzip_header(bs)
- -- local FLG_FTEXT = 2^0
- local FLG_FHCRC = 2^1
- local FLG_FEXTRA = 2^2
- local FLG_FNAME = 2^3
- local FLG_FCOMMENT = 2^4
- local id1 = bs:read(8)
- local id2 = bs:read(8)
- if id1 ~= 31 or id2 ~= 139 then
- runtime_error 'not in gzip format'
- end
- local cm = bs:read(8) -- compression method
- local flg = bs:read(8) -- FLaGs
- local mtime = bs:read(32) -- Modification TIME
- local xfl = bs:read(8) -- eXtra FLags
- local os = bs:read(8) -- Operating System
- if DEBUG then
- debug("CM=", cm)
- debug("FLG=", flg)
- debug("MTIME=", mtime)
- -- debug("MTIME_str=",os.date("%Y-%m-%d %H:%M:%S",mtime)) -- non-portable
- debug("XFL=", xfl)
- debug("OS=", os)
- end
- if not os then runtime_error 'invalid header' end
- if hasbit(flg, FLG_FEXTRA) then
- local xlen = bs:read(16)
- local extra = 0
- for i=1,xlen do
- extra = bs:read(8)
- end
- if not extra then runtime_error 'invalid header' end
- end
- local function parse_zstring(bs)
- repeat
- local by = bs:read(8)
- if not by then runtime_error 'invalid header' end
- until by == 0
- end
- if hasbit(flg, FLG_FNAME) then
- parse_zstring(bs)
- end
- if hasbit(flg, FLG_FCOMMENT) then
- parse_zstring(bs)
- end
- if hasbit(flg, FLG_FHCRC) then
- local crc16 = bs:read(16)
- if not crc16 then runtime_error 'invalid header' end
- -- IMPROVE: check CRC. where is an example .gz file that
- -- has this set?
- if DEBUG then
- debug("CRC16=", crc16)
- end
- end
- end
- local function parse_zlib_header(bs)
- local cm = bs:read(4) -- Compression Method
- local cinfo = bs:read(4) -- Compression info
- local fcheck = bs:read(5) -- FLaGs: FCHECK (check bits for CMF and FLG)
- local fdict = bs:read(1) -- FLaGs: FDICT (present dictionary)
- local flevel = bs:read(2) -- FLaGs: FLEVEL (compression level)
- local cmf = cinfo * 16 + cm -- CMF (Compresion Method and flags)
- local flg = fcheck + fdict * 32 + flevel * 64 -- FLaGs
- if cm ~= 8 then -- not "deflate"
- runtime_error("unrecognized zlib compression method: " + cm)
- end
- if cinfo > 7 then
- runtime_error("invalid zlib window size: cinfo=" + cinfo)
- end
- local window_size = 2^(cinfo + 8)
- if (cmf*256 + flg) % 31 ~= 0 then
- runtime_error("invalid zlib header (bad fcheck sum)")
- end
- if fdict == 1 then
- runtime_error("FIX:TODO - FDICT not currently implemented")
- local dictid_ = bs:read(32)
- end
- return window_size
- end
- local function parse_huffmantables(bs)
- local hlit = bs:read(5) -- # of literal/length codes - 257
- local hdist = bs:read(5) -- # of distance codes - 1
- local hclen = noeof(bs:read(4)) -- # of code length codes - 4
- local ncodelen_codes = hclen + 4
- local codelen_init = {}
- local codelen_vals = {
- 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}
- for i=1,ncodelen_codes do
- local nbits = bs:read(3)
- local val = codelen_vals[i]
- codelen_init[val] = nbits
- end
- local codelentable = HuffmanTable(codelen_init, true)
- local function decode(ncodes)
- local init = {}
- local nbits
- local val = 0
- while val < ncodes do
- local codelen = codelentable:read(bs)
- --FIX:check nil?
- local nrepeat
- if codelen <= 15 then
- nrepeat = 1
- nbits = codelen
- --debug('w', nbits)
- elseif codelen == 16 then
- nrepeat = 3 + noeof(bs:read(2))
- -- nbits unchanged
- elseif codelen == 17 then
- nrepeat = 3 + noeof(bs:read(3))
- nbits = 0
- elseif codelen == 18 then
- nrepeat = 11 + noeof(bs:read(7))
- nbits = 0
- else
- error 'ASSERT'
- end
- for i=1,nrepeat do
- init[val] = nbits
- val = val + 1
- end
- end
- local huffmantable = HuffmanTable(init, true)
- return huffmantable
- end
- local nlit_codes = hlit + 257
- local ndist_codes = hdist + 1
- local littable = decode(nlit_codes)
- local disttable = decode(ndist_codes)
- return littable, disttable
- end
- local tdecode_len_base
- local tdecode_len_nextrabits
- local tdecode_dist_base
- local tdecode_dist_nextrabits
- local function parse_compressed_item(bs, outstate, littable, disttable)
- local val = littable:read(bs)
- --debug(val, val < 256 and string_char(val))
- if val < 256 then -- literal
- output(outstate, val)
- elseif val == 256 then -- end of block
- return true
- else
- if not tdecode_len_base then
- local t = {[257]=3}
- local skip = 1
- for i=258,285,4 do
- for j=i,i+3 do t[j] = t[j-1] + skip end
- if i ~= 258 then skip = skip * 2 end
- end
- t[285] = 258
- tdecode_len_base = t
- --for i=257,285 do debug('T1',i,t[i]) end
- end
- if not tdecode_len_nextrabits then
- local t = {}
- if NATIVE_BITOPS then
- for i=257,285 do
- local j = math_max(i - 261, 0)
- t[i] = rshift(j, 2)
- end
- else
- for i=257,285 do
- local j = math_max(i - 261, 0)
- t[i] = (j - (j % 4)) / 4
- end
- end
- t[285] = 0
- tdecode_len_nextrabits = t
- --for i=257,285 do debug('T2',i,t[i]) end
- end
- local len_base = tdecode_len_base[val]
- local nextrabits = tdecode_len_nextrabits[val]
- local extrabits = bs:read(nextrabits)
- local len = len_base + extrabits
- if not tdecode_dist_base then
- local t = {[0]=1}
- local skip = 1
- for i=1,29,2 do
- for j=i,i+1 do t[j] = t[j-1] + skip end
- if i ~= 1 then skip = skip * 2 end
- end
- tdecode_dist_base = t
- --for i=0,29 do debug('T3',i,t[i]) end
- end
- if not tdecode_dist_nextrabits then
- local t = {}
- if NATIVE_BITOPS then
- for i=0,29 do
- local j = math_max(i - 2, 0)
- t[i] = rshift(j, 1)
- end
- else
- for i=0,29 do
- local j = math_max(i - 2, 0)
- t[i] = (j - (j % 2)) / 2
- end
- end
- tdecode_dist_nextrabits = t
- --for i=0,29 do debug('T4',i,t[i]) end
- end
- local dist_val = disttable:read(bs)
- local dist_base = tdecode_dist_base[dist_val]
- local dist_nextrabits = tdecode_dist_nextrabits[dist_val]
- local dist_extrabits = bs:read(dist_nextrabits)
- local dist = dist_base + dist_extrabits
- --debug('BACK', len, dist)
- for i=1,len do
- local pos = (outstate.window_pos - 1 - dist) % 32768 + 1 -- 32K
- output(outstate, assert(outstate.window[pos], 'invalid distance'))
- end
- end
- return false
- end
- local function parse_block(bs, outstate)
- local bfinal = bs:read(1)
- local btype = bs:read(2)
- local BTYPE_NO_COMPRESSION = 0
- local BTYPE_FIXED_HUFFMAN = 1
- local BTYPE_DYNAMIC_HUFFMAN = 2
- local BTYPE_RESERVED_ = 3
- if DEBUG then
- debug('bfinal=', bfinal)
- debug('btype=', btype)
- end
- if btype == BTYPE_NO_COMPRESSION then
- bs:read(bs:nbits_left_in_byte())
- local len = bs:read(16)
- local nlen_ = noeof(bs:read(16))
- for i=1,len do
- local by = noeof(bs:read(8))
- output(outstate, by)
- end
- elseif btype == BTYPE_FIXED_HUFFMAN or btype == BTYPE_DYNAMIC_HUFFMAN then
- local littable, disttable
- if btype == BTYPE_DYNAMIC_HUFFMAN then
- littable, disttable = parse_huffmantables(bs)
- else
- littable = HuffmanTable {0,8, 144,9, 256,7, 280,8, 288,nil}
- disttable = HuffmanTable {0,5, 32,nil}
- end
- repeat
- local is_done = parse_compressed_item(
- bs, outstate, littable, disttable)
- until is_done
- else
- runtime_error 'unrecognized compression type'
- end
- return bfinal ~= 0
- end
- function M.inflate(t)
- local bs = get_bitstream(t.input)
- local outbs = get_obytestream(t.output)
- local outstate = make_outstate(outbs)
- repeat
- local is_final = parse_block(bs, outstate)
- until is_final
- end
- local inflate = M.inflate
- function M.gunzip(t)
- local bs = get_bitstream(t.input)
- local outbs = get_obytestream(t.output)
- local disable_crc = t.disable_crc
- if disable_crc == nil then disable_crc = false end
- parse_gzip_header(bs)
- local data_crc32 = 0
- inflate{input=bs, output=
- disable_crc and outbs or
- function(byte)
- data_crc32 = crc32(byte, data_crc32)
- outbs(byte)
- end
- }
- bs:read(bs:nbits_left_in_byte())
- local expected_crc32 = bs:read(32)
- local isize = bs:read(32) -- ignored
- if DEBUG then
- debug('crc32=', expected_crc32)
- debug('isize=', isize)
- end
- if not disable_crc and data_crc32 then
- if data_crc32 ~= expected_crc32 then
- runtime_error('invalid compressed data--crc error')
- end
- end
- if bs:read() then
- warn 'trailing garbage ignored'
- end
- end
- function M.adler32(byte, crc)
- local s1 = crc % 65536
- local s2 = (crc - s1) / 65536
- s1 = (s1 + byte) % 65521
- s2 = (s2 + s1) % 65521
- return s2*65536 + s1
- end -- 65521 is the largest prime smaller than 2^16
- function M.inflate_zlib(t)
- local bs = get_bitstream(t.input)
- local outbs = get_obytestream(t.output)
- local disable_crc = t.disable_crc
- if disable_crc == nil then disable_crc = false end
- local window_size_ = parse_zlib_header(bs)
- local data_adler32 = 1
- inflate{input=bs, output=
- disable_crc and outbs or
- function(byte)
- data_adler32 = M.adler32(byte, data_adler32)
- outbs(byte)
- end
- }
- bs:read(bs:nbits_left_in_byte())
- local b3 = bs:read(8)
- local b2 = bs:read(8)
- local b1 = bs:read(8)
- local b0 = bs:read(8)
- local expected_adler32 = ((b3*256 + b2)*256 + b1)*256 + b0
- if DEBUG then
- debug('alder32=', expected_adler32)
- end
- if not disable_crc then
- if data_adler32 ~= expected_adler32 then
- runtime_error('invalid compressed data--crc error')
- end
- end
- if bs:read() then
- warn 'trailing garbage ignored'
- end
- end
- return M
- end
- function dirlib()
- --- Generic utilities for handling pathnames.
- local dir = {}
- dir.separator = "/"
- --- Strip the path off a path+filename.
- -- @param pathname string: A path+name, such as "/a/b/c"
- -- or "\a\b\c".
- -- @return string: The filename without its path, such as "c".
- function dir.base_name(pathname)
- assert(type(pathname) == "string")
- local base = pathname:gsub("[/\\]*$", ""):match(".*[/\\]([^/\\]*)")
- return base or pathname
- end
- --- Strip the name off a path+filename.
- -- @param pathname string: A path+name, such as "/a/b/c".
- -- @return string: The filename without its path, such as "/a/b".
- -- For entries such as "/a/b/", "/a" is returned. If there are
- -- no directory separators in input, "" is returned.
- function dir.dir_name(pathname)
- assert(type(pathname) == "string")
- return (pathname:gsub("/*$", ""):match("(.*)[/]+[^/]*")) or ""
- end
- --- Describe a path in a cross-platform way.
- -- Use this function to avoid platform-specific directory
- -- separators in other modules. Removes trailing slashes from
- -- each component given, to avoid repeated separators.
- -- Separators inside strings are kept, to handle URLs containing
- -- protocols.
- -- @param ... strings representing directories
- -- @return string: a string with a platform-specific representation
- -- of the path.
- function dir.path(...)
- local t = {...}
- while t[1] == "" do
- table.remove(t, 1)
- end
- return (table.concat(t, "/"):gsub("([^:])/+", "%1/"):gsub("^/+", "/"):gsub("/*$", ""))
- end
- --- Split protocol and path from an URL or local pathname.
- -- URLs should be in the "protocol://path" format.
- -- For local pathnames, "file" is returned as the protocol.
- -- @param url string: an URL or a local pathname.
- -- @return string, string: the protocol, and the pathname without the protocol.
- function dir.split_url(url)
- assert(type(url) == "string")
- local protocol, pathname = url:match("^([^:]*)://(.*)")
- if not protocol then
- protocol = "file"
- pathname = url
- end
- return protocol, pathname
- end
- --- Normalize a url or local path.
- -- URLs should be in the "protocol://path" format. System independent
- -- forward slashes are used, removing trailing and double slashes
- -- @param url string: an URL or a local pathname.
- -- @return string: Normalized result.
- function dir.normalize(name)
- local protocol, pathname = dir.split_url(name)
- pathname = pathname:gsub("\\", "/"):gsub("(.)/*$", "%1"):gsub("//", "/")
- if protocol ~= "file" then pathname = protocol .."://"..pathname end
- return pathname
- end
- return dir
- end
- function untar()
- --- A pure-Lua implementation of untar (unpacking .tar archives)
- local tar = {}
- local dir = dirlib()
- local blocksize = 512
- local function get_typeflag(flag)
- if flag == "0" or flag == "\0" then return "file"
- elseif flag == "1" then return "link"
- elseif flag == "2" then return "symlink" -- "reserved" in POSIX, "symlink" in GNU
- elseif flag == "3" then return "character"
- elseif flag == "4" then return "block"
- elseif flag == "5" then return "directory"
- elseif flag == "6" then return "fifo"
- elseif flag == "7" then return "contiguous" -- "reserved" in POSIX, "contiguous" in GNU
- elseif flag == "x" then return "next file"
- elseif flag == "g" then return "global extended header"
- elseif flag == "L" then return "long name"
- elseif flag == "K" then return "long link name"
- end
- return "unknown"
- end
- local function octal_to_number(octal)
- local exp = 0
- local number = 0
- for i = #octal,1,-1 do
- local digit = tonumber(octal:sub(i,i))
- if digit then
- number = number + (digit * 8^exp)
- exp = exp + 1
- end
- end
- return number
- end
- local function checksum_header(block)
- local sum = 256
- for i = 1,148 do
- sum = sum + (block:byte(i) or 0)
- end
- for i = 157,500 do
- sum = sum + (block:byte(i) or 0)
- end
- return sum
- end
- local function nullterm(s)
- return s:match("^[^%z]*")
- end
- local function read_header_block(block)
- local header = {}
- header.name = nullterm(block:sub(1,100))
- header.mode = nullterm(block:sub(101,108))
- header.uid = octal_to_number(nullterm(block:sub(109,116)))
- header.gid = octal_to_number(nullterm(block:sub(117,124)))
- header.size = octal_to_number(nullterm(block:sub(125,136)))
- header.mtime = octal_to_number(nullterm(block:sub(137,148)))
- header.chksum = octal_to_number(nullterm(block:sub(149,156)))
- header.typeflag = get_typeflag(block:sub(157,157))
- header.linkname = nullterm(block:sub(158,257))
- header.magic = block:sub(258,263)
- header.version = block:sub(264,265)
- header.uname = nullterm(block:sub(266,297))
- header.gname = nullterm(block:sub(298,329))
- header.devmajor = octal_to_number(nullterm(block:sub(330,337)))
- header.devminor = octal_to_number(nullterm(block:sub(338,345)))
- header.prefix = block:sub(346,500)
- if header.magic ~= "ustar " and header.magic ~= "ustar\0" then
- return false, "Invalid header magic "..header.magic
- end
- if header.version ~= "00" and header.version ~= " \0" then
- return false, "Unknown version "..header.version
- end
- if not checksum_header(block) == header.chksum then
- return false, "Failed header checksum"
- end
- return header
- end
- local function bytestream_from_file(fh)
- if not fh then
- return nil
- end
- local o = {}
- function o:read_single()
- local sb = fh:read(1)
- if not computercraft and sb then return sb:byte() end
- return sb
- end
- function o:read(num)
- if o.finished then
- return nil
- end
- local buf = {}
- for i=1, num do
- local b_read = o:read_single()
- if not b_read then
- o.finished = true
- break
- end
- buf[#buf+1] = string.char(b_read)
- end
- return table.concat(buf)
- end
- function o:close()
- fh:close()
- end
- return o
- end
- function tar.untar(filename, destdir)
- assert(type(filename) == "string")
- assert(type(destdir) == "string")
- local tar_handle = bytestream_from_file(io.open(filename, "rb"))
- if not tar_handle then return nil, "Error opening file "..filename end
- local long_name, long_link_name
- while true do
- local block
- repeat
- block = tar_handle:read(blocksize)
- until (not block) or checksum_header(block) > 256
- if not block then break end
- local header, err = read_header_block(block)
- if not header then
- error(err)
- end
- local file_data = tar_handle:read(math.ceil(header.size / blocksize) * blocksize):sub(1,header.size)
- if header.typeflag == "long name" then
- long_name = nullterm(file_data)
- elseif header.typeflag == "long link name" then
- long_link_name = nullterm(file_data)
- else
- if long_name then
- header.name = long_name
- long_name = nil
- end
- if long_link_name then
- header.name = long_link_name
- long_link_name = nil
- end
- end
- local pathname = dir.path(destdir, header.name)
- if header.typeflag == "directory" then
- local ok, err = fs.makeDir(pathname)
- if not ok and not fs.combine then return nil, err end
- elseif header.typeflag == "file" then
- local dirname = dir.dir_name(pathname)
- if dirname ~= "" then
- local ok, err = fs.makeDir(dirname)
- if not ok and not fs.combine then return nil, err end
- end
- local file_handle = io.open(pathname, "wb")
- if not computercraft then
- file_handle:write(file_data)
- else
- for i = 1, #file_data do
- local c = file_data:sub(i,i)
- file_handle:write(c:byte())
- end
- end
- file_handle:close()
- --fs.set_time(pathname, header.mtime)
- if fs.chmod then
- fs.chmod(pathname, header.mode)
- end
- end
- --[[
- for k,v in pairs(header) do
- util.printout("[\""..tostring(k).."\"] = "..(type(v)=="number" and v or "\""..v:gsub("%z", "\\0").."\""))
- end
- util.printout()
- --]]
- end
- tar_handle:close()
- return true
- end
- return tar
- end
- function gunziplua()
- local assert = assert
- local error = error
- local ipairs = ipairs
- local xpcall = xpcall
- local type = type
- local io = io
- local os = os
- local string = string
- --local debug = require "debug"
- --os.loadAPI('debug')
- if not debug then
- debug = {}
- debug.traceback = function() return 1 end
- end
- local tar = untar()
- local debug_traceback = debug.traceback
- local _G = _G
- --local DEFLATE = require "compress.deflatelua"
- local DEFLATE = deflatelua()
- --local OptionParser = require "pythonic.optparse" . OptionParser
- local OptionParser = optparse().OptionParser
- local version = '0.1'
- local function runtime_assert(val, msg)
- if not val then error({msg}, val) end
- return val
- end
- local function runtime_error(s, level)
- level = level or 1
- error({s}, level+1)
- end
- local function file_exists(filename)
- local fh = io.open(filename)
- if fh then fh:close(); return true end
- return false
- end
- -- Run gunzip command, given command-line arguments.
- local function call(...)
- local opt = OptionParser{usage="%prog [options] [gzip-file...]",
- version=string.format("gunzip %s", version),
- add_help_option=false}
- opt.add_option{"-h", "--help", action="store_true", dest="help",
- help="give this help"}
- opt.add_option{
- "-c", "--stdout", dest="stdout", action="store_true",
- help="write on standard output, keep original files unchanged"}
- opt.add_option{
- "-f", "--force", dest="force", action="store_true",
- help="force overwrite of output file"}
- opt.add_option{
- "--disable-crc", dest="disable_crc", action="store_true",
- help="skip CRC check (faster performance)"}
- opt.add_option{"-b", "--decode-base64", dest="base64", action="store_true",
- help="decode file from base64 before decompression"}
- opt.add_option{"-x", "--untar", dest="untar", metavar="DIR",
- help="untars the input file into the specified directory"}
- local options, args = opt.parse_args()
- local gzipfiles = args
- if options.help then
- opt.print_help()
- os.exit()
- end
- if options.untar then
- local out_dir = options.untar
- if out_dir == "" then
- out_dir = "."
- end
- for _, my_file in pairs(gzipfiles) do
- local res, err = tar.untar(my_file,out_dir)
- if err then
- error(err)
- end
- end
- gzipfiles = {}
- os.exit()
- end
- local ok, err = xpcall(function()
- local outfile_of = {}
- local out_of = {}
- for _,gzipfile in ipairs(gzipfiles) do
- local base = gzipfile:match('(.+)%.[gG][zZ]$')
- if not base then
- runtime_error(gzipfile .. ': unknown suffix')
- end
- if (options.base64) then
- local fh1 = gzipfile and runtime_assert(io.open(gzipfile, 'r')) or assert(io.stdin)
- local content = fh1:read("*a")
- fh1:close()
- local newfile = gzipfile .. ".decode.gz"
- content = string.gsub(content, "%s", "")
- local decoded = from_base64(content)
- if not computercraft then
- local fh2 = newfile and runtime_assert(io.open(newfile, 'wb'))
- fh2:write(decoded)
- fh2:close()
- else
- local fh2 = io.open(newfile, 'wb')
- for i=1, #decoded do
- local b = string.byte(decoded:sub(i, i))
- fh2:write(b+0)
- end
- fh2:close()
- end
- gzipfile = newfile
- gzipfiles[_] = newfile
- end
- outfile_of[gzipfile] = base
- out_of[gzipfile] =
- (options.stdout or not gzipfile) and assert(io.stdout)
- or outfile_of[gzipfile]
- if type(out_of[gzipfile]) == 'string' then
- if file_exists(out_of[gzipfile]) then
- io.stderr:write(out_of[gzipfile] ..
- ' already exists; do you wish to overwrite(y or n)? ')
- if not io.stdin:read'*l':match'^[yY]' then
- runtime_error 'not overwritten'
- end
- end
- end
- end
- for _,gzipfile in ipairs(gzipfiles) do
- local fh = gzipfile and runtime_assert(io.open(gzipfile, 'rb'))
- or assert(io.stdin)
- local ofh = type(out_of[gzipfile]) == 'string' and
- runtime_assert(io.open(out_of[gzipfile], 'wb'))
- or out_of[gzipfile]
- DEFLATE.gunzip {input=fh, output=ofh,
- disable_crc=options.disable_crc}
- fh:close()
- ofh:close()
- end
- if not options.stdout then
- for _,gzipfile in ipairs(gzipfiles) do
- assert(os.remove(gzipfile))
- end
- end
- end, debug_traceback)
- if not ok then
- if type(err) == 'table' then err = err[1] end
- io.stderr:write('error: ' .. err, '\n')
- end
- end
- return call
- end
- --[[
- -- gunziplua command-line utility
- package.path = '../lua-digest-crc32lua/lmod/?.lua;' .. package.path
- package.path = '../lua-pythonic-optparse/lmod/?.lua;' .. package.path
- package.path = '../lua-bit-numberlua/lmod/?.lua;' .. package.path
- package.path = 'lmod/?.lua;' .. package.path
- --require 'bin.gunziplua' (...)
- --]]
- local mod0000 = gunziplua()(...)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement