-- libgen ver. 1.1a -- lua ver. 5.3 compliant -- you need 9lua -- update: 2015/03/04 -- coded by Kenar (Kenji arisawa) -- some generic stuffs -- str=require("str") sub = string.sub gsub = string.gsub find = string.find match = string.match format = string.format split = str.split local function dbg(...) if DBG then print(...) end end -- for debugging function chk_G(mod) local t={} local u for k,v in pairs(_G) do t[k]=true end u=require(mod) for k,v in pairs(_G) do if t[k]==nil then print(k,t[k]) end end return u end function printf(fmt,...) io.write(format(fmt,...)) end -- donn't use dprint. we may discard this one in future function dprint(fmt,...) io.write(format(fmt.."\n",...)) end function fatal(fmt,...) io.write(format(fmt.."\n",...)) os.exit() end function basename(path,sep) -- usage: d,f = basename(path) -- d.."/"..f is equivalent to the path if "/" exist local m1,m2 sep=sep or "/" m1,m2=match(path,"^(.-)"..sep.."([^"..sep.."]*)$") if m1==nil then m1,m2=nil,path end return m1,m2 end function readf(file) local f,s f=io.open(file) if f == nil then return nil end s = f:read("a") f:close() return s end function readn(fd,m) -- simulate Plan 9 readn local n = m local t,s,r t = "" repeat s,r = p9.read(fd,n) if s == nil then if r == nil then return t,"eof" -- premature eof end return nil,r -- read error end n = n - #s t = t .. s until n == 0 return t end function date(t,time) -- t: type of date format, "http", "iso" local mon = {[1]="Jan",[2]="Feb",[3]="Mar",[4]="Apr",[5]="May",[6]="Jun", [7]="Jul",[8]="Aug",[9]="Sep",[10]="Oct",[11]="Nov",[12]="Dec"} local wday={[1]="Sun",[2]="Mon",[3]="Tue",[4]="Wed",[5]="Thu",[6]="Fri",[7]="Sat"} if t == nil or t == "%c" then return os.date("%c",time) end local tm = os.date("!*t",time) -- GMT time -- year (four digits), month (1--12), day (1--31), hour (0--23), min (0--59), -- sec (0--61), wday (weekday, Sunday is 1), yday (day of the year) if t == "http" then -- http date defined in rfc2068 used in "getlastmodified" return format("%s, %02d %s %d %02d:%02d:%02d GMT", wday[tm.wday],tm.day,mon[tm.month],tm.year,tm.hour,tm.min,tm.sec) elseif t == "iso" then -- ISO 8601 date used in "creationdate property" return format("%d-%02d-%02dT%02d:%02d:%02dZ", tm.year,tm.month,tm.day,tm.hour,tm.min,tm.sec) end end --[[ -- under construction argopt() separate option part and argument part. the usage is: args,opts,err = argopt(arg,opt) opt gives flag list. the format is simply, for example, opt="abc:de:fgh" where ":" separate flags into three parts, the first (abc in opt) is flags the second (de in opt) is flags that are followed by an argument the third (fgh in opt) is flags that is like second but allows multiple value like keywords in sort command the following syntax is OK "abc" ":de" "abc::fgh" "abc:de" named options are given by, for example: command -tabsize:4 or command '-tabsize=4' # '' is required for Plan9 rc names need not be registered in opt empty option "-" terminate options part with command args: -badalice - -e bob carol a,t,r=argopt(arg,"abc:de:k") we get for a: 1 -e 2 bob 3 carol -1 foo 0 ./foo and for t: 1 abc 2 de a true d alice b true --]] -- args,opts,err = argopt(arg,opt) function argopt(arg,opt) local t,t1,t2,t3,o,o1,o2,o3,c,r,x,n if opt == nil then return arg,nil end t,t1,t2,t3 = {},{},{},{} o = split(opt,":") o1,o2,o3 = o[1],o[2],o[3] if o2 == nil then o2 = "" end if o3 == nil then o3 = "" end for i=1,#o1 do t1[sub(o1,i,i)] = true end for i=1,#o2 do t2[sub(o2,i,i)] = true end for i=1,#o3 do t3[sub(o3,i,i)] = true end while #arg > 0 and sub(arg[1],1,1) == "-" do x = sub(arg[1],2) if #x == 0 then table.remove(arg,1) break end n = find(x,"([=:])") if n then t[sub(x,1,n-1)] = sub(x,n+1) else for i=1,#x do c = sub(x,i,i) if t1[c] then t[c] = true elseif t2[c] or t3[c] then --t[c] = sub(x,i+1) local u = sub(x,i+1) if u == "" then table.remove(arg,1) u = arg[1] end if t2[c] then if t[c] then r = format("#error: option %s: used more then once",c) return nil,nil,r end t[c] = u else -- then t3[c] ~= nil if t[c] == nil then t[c] = {} end table.insert(t[c],u) end if t[c] == nil or sub(u,1,1) == "-" then r = format("#error: no arg for %s",c) return nil,nil,r end break else r = "#error: bad option: "..c return nil,nil,r end end end table.remove(arg,1) end return arg,t,r end function dumpstr(s) if type(s)=="string" then local repl={["\n"]="\\n",["\t"]="\\t"} return gsub(s,"(%c)",repl) end return s end spectype={} spectype["string"]=true spectype["number"]=true spectype["boolean"]=true -- under construction function prtab(t,n,done) -- print table if n==nil then done={} n="" end if t==nil then return end done[t]=true for k,v in pairs(t) do if type(v) == "table" then if done[v] then printf("%s%s\t%s # done\n",n,k,v) else printf("%s%s\t%s\n",n,k,v) prtab(v,n.."\t",done) end elseif spectype[type(v)] then printf("%s%s\t%s: %s\n",n,k,type(v),dumpstr(v)) else printf("%s%s\t%s\n",n,k,v) end end end -- tprint should expand recursively. but currently not. -- I reserved tabprint for recursive tprint -- prtab is the trial for tabprint but under construction local function tprint(...) local a a = {...} -- table for n,u in ipairs(a) do if type(u) == "table" then for k,v in pairs(u) do print(k,v) end else print(u) end end end return { readf=readf, printf=printf, dprint=dprint, basename=basename, argopt=argopt, date=date, chk_G=chk_G, prtab=prtab, tprint=tprint, dbg=dbg, dumpstr=dumpstr, } --[[ NG code below We want to call functions by name return { readf, printf, dprint, basename, argopt, prtab, date, chk_G } --]]