#!/usr/bin/env lua local i=string local e=math local ee=table local k=require local m=print local p=i.sub local Q=i.gmatch local X=i.match local b=package.preload local l=_G local Z={html="html generates a HTML file for checking globals",sloc="sloc calculates SLOC for given source file",}local z={'html','sloc',}b.llex=function()module"llex"local r=l.require"string"local s=r.find local u=r.match local a=r.sub local p={}for e in r.gmatch([[ and break do else elseif end false for function if in local nil not or repeat return then true until while]],"%S+")do p[e]=true end local e,f,o,i,c local function t(n,l)local e=#tok+1 tok[e]=n seminfo[e]=l tokln[e]=c end local function d(n,i)local a=a local l=a(e,n,n)n=n+1 local e=a(e,n,n)if(e=="\n"or e=="\r")and(e~=l)then n=n+1 l=l..e end if i then t("TK_EOL",l)end c=c+1 o=n return n end function init(l,n)e=l f=n o=1 c=1 tok={}seminfo={}tokln={}local l,a,e,n=s(e,"^(#[^\r\n]*)(\r?\n?)")if l then o=o+#e t("TK_COMMENT",e)if#n>0 then d(o,true)end end end function chunkid()if f and u(f,"^[=@]")then return a(f,2)end return"[string]"end function errorline(o,n)local e=error or l.error e(r.format("%s:%d: %s",chunkid(),n or c,o))end local c=errorline local function h(n)local t=a local a=t(e,n,n)n=n+1 local l=#u(e,"=*",n)n=n+l o=n return(t(e,n,n)==a)and l or(-l)-1 end local function T(r,f)local n=o+1 local t=a local l=t(e,n,n)if l=="\r"or l=="\n"then n=d(n)end while true do local l,s,a=s(e,"([\r\n%]])",n)if not l then c(r and"unfinished long string"or"unfinished long comment")end n=l if a=="]"then if h(n)==f then i=t(e,i,o)o=o+1 return i end n=o else i=i.."\n"n=d(n)end end end local function m(f)local n=o local r=s local a=a while true do local t,s,l=r(e,"([\n\r\\\"'])",n)if t then if l=="\n"or l=="\r"then c("unfinished string")end n=t if l=="\\"then n=n+1 l=a(e,n,n)if l==""then break end t=r("abfnrtv\n\r",l,1,true)if t then if t>7 then n=d(n)else n=n+1 end elseif r(l,"%D")then n=n+1 else local o,e,l=r(e,"^(%d%d?%d?)",n)n=e+1 if l+1>256 then c("escape sequence too large")end end else n=n+1 if l==f then o=n return a(e,i,n-1)end end else break end end c("unfinished string")end function llex()local r=s local f=u while true do local n=o while true do local u,b,s=r(e,"^([_%a][_%w]*)",n)if u then o=n+#s if p[s]then t("TK_KEYWORD",s)else t("TK_NAME",s)end break end local s,p,u=r(e,"^(%.?)%d",n)if s then if u=="."then n=n+1 end local u,i,d=r(e,"^%d*[%.%d]*([eE]?)",n)n=i+1 if#d==1 then if f(e,"^[%+%-]",n)then n=n+1 end end local i,n=r(e,"^[_%w]*",n)o=n+1 local e=a(e,s,n)if not l.tonumber(e)then c("malformed number")end t("TK_NUMBER",e)break end local u,p,s,l=r(e,"^((%s)[ \t\v\f]*)",n)if u then if l=="\n"or l=="\r"then d(n,true)else o=p+1 t("TK_SPACE",s)end break end local l=f(e,"^%p",n)if l then i=n local d=r("-[\"'.=<>~",l,1,true)if d then if d<=2 then if d==1 then local c=f(e,"^%-%-(%[?)",n)if c then n=n+2 local l=-1 if c=="["then l=h(n)end if l>=0 then t("TK_LCOMMENT",T(false,l))else o=r(e,"[\n\r]",n)or(#e+1)t("TK_COMMENT",a(e,i,o-1))end break end else local e=h(n)if e>=0 then t("TK_LSTRING",T(true,e))elseif e==-1 then t("TK_OP","[")else c("invalid long string delimiter")end break end elseif d<=5 then if d<5 then o=n+1 t("TK_STRING",m(l))break end l=f(e,"^%.%.?%.?",n)else l=f(e,"^%p=?",n)end end o=n+#l t("TK_OP",l)break end local e=a(e,n,n)if e~=""then o=n+1 t("TK_OP",e)break end t("TK_EOS","")return end end end end b.lparser=function()module"lparser"local _=l.require"string"local v,L,w,y,i,s,B,n,A,d,p,m,o,Y,N,P,f,E,x,I local O,c,K,R,S,g local e=_.gmatch local C={}for e in e("else elseif end until ","%S+")do C[e]=true end local M={}local W={}for e,l,n in e([[ {+ 6 6}{- 6 6}{* 7 7}{/ 7 7}{% 7 7} {^ 10 9}{.. 5 4} {~= 3 3}{== 3 3} {< 3 3}{<= 3 3}{> 3 3}{>= 3 3} {and 2 2}{or 1 1} ]],"{(%S+)%s(%d+)%s(%d+)}")do M[e]=l+0 W[e]=n+0 end local ne={["not"]=true,["-"]=true,["#"]=true,}local ee=8 local function t(e,n)local l=error or l.error l(_.format("(source):%d: %s",n or d,e))end local function e()B=w[i]n,A,d,p=v[i],L[i],w[i],y[i]i=i+1 end local function Z()return v[i]end local function r(l)local e=n if e~=""and e~=""then if e==""then e=A end e="'"..e.."'"end t(l.." near "..e)end local function h(e)r("'"..e.."' expected")end local function t(l)if n==l then e();return true end end local function D(e)if n~=e then h(e)end end local function a(n)D(n);e()end local function j(e,n)if not e then r(n)end end local function u(e,l,n)if not t(e)then if n==d then h(e)else r("'"..e.."' expected (to close '"..l.."' at line "..n..")")end end end local function T()D("")local n=A m=p e()return n end local function q(e,n)e.k="VK"end local function G(e)q(e,T())end local function h(t,l)local n=o.bl local e if n then e=n.locallist else e=o.locallist end local n=#f+1 f[n]={name=t,xref={m},decl=m,}if l then f[n].isself=true end local l=#E+1 E[l]=n x[l]=e end local function k(e)local n=#E while e>0 do e=e-1 local e=n-e local l=E[e]local n=f[l]local o=n.name n.act=p E[e]=nil local t=x[e]x[e]=nil local e=t[o]if e then n=f[e]n.rem=-l end t[o]=l end end local function V()local n=o.bl local e if n then e=n.locallist else e=o.locallist end for n,e in l.pairs(e)do local e=f[e]e.rem=p end end local function p(e,n)if _.sub(e,1,1)=="("then return end h(e,n)end local function U(o,l)local n=o.bl local e if n then e=n.locallist while e do if e[l]then return e[l]end n=n.prev e=n and n.locallist end end e=o.locallist return e[l]or-1 end local function _(n,o,e)if n==nil then e.k="VGLOBAL"return"VGLOBAL"else local l=U(n,o)if l>=0 then e.k="VLOCAL"e.id=l return"VLOCAL"else if _(n.prev,o,e)=="VGLOBAL"then return"VGLOBAL"end e.k="VUPVAL"return"VUPVAL"end end end local function F(l)local n=T()_(o,n,l)if l.k=="VGLOBAL"then local e=P[n]if not e then e=#N+1 N[e]={name=n,xref={m},}P[n]=e else local e=N[e].xref e[#e+1]=m end else local e=l.id local e=f[e].xref e[#e+1]=m end end local function m(n)local e={}e.isbreakable=n e.prev=o.bl e.locallist={}o.bl=e end local function _()local e=o.bl V()o.bl=e.prev end local function Q()local e if not o then e=Y else e={}end e.prev=o e.bl=nil e.locallist={}o=e end local function H()V()o=o.prev end local function U(n)local l={}e()G(l)n.k="VINDEXED"end local function J(n)e()c(n)a("]")end local function z(e)local e,l={},{}if n==""then G(e)else J(e)end a("=")c(l)end local function l(e)if e.v.k=="VVOID"then return end e.v.k="VVOID"end local function V(e)c(e.v)end local function X(l)local o=d local e={}e.v={}e.t=l l.k="VRELOCABLE"e.v.k="VVOID"a("{")repeat if n=="}"then break end local n=n if n==""then if Z()~="="then V(e)else z(e)end elseif n=="["then z(e)else V(e)end until not t(",")and not t(";")u("}","{",o)end local function Z()local l=0 if n~=")"then repeat local n=n if n==""then h(T())l=l+1 elseif n=="..."then e()o.is_vararg=true else r(" or '...' expected")end until o.is_vararg or not t(",")end k(l)end local function z(a)local l={}local t=d local o=n if o=="("then if t~=B then r("ambiguous syntax (function call x new statement)")end e()if n==")"then l.k="VVOID"else O(l)end u(")","(",t)elseif o=="{"then X(l)elseif o==""then q(l,A)e()else r("function arguments expected")return end a.k="VCALL"end local function B(l)local n=n if n=="("then local n=d e()c(l)u(")","(",n)elseif n==""then F(l)else r("unexpected symbol")end end local function V(l)B(l)while true do local n=n if n=="."then U(l)elseif n=="["then local e={}J(e)elseif n==":"then local n={}e()G(n)z(l)elseif n=="("or n==""or n=="{"then z(l)else return end end end local function G(l)local n=n if n==""then l.k="VKNUM"elseif n==""then q(l,A)elseif n=="nil"then l.k="VNIL"elseif n=="true"then l.k="VTRUE"elseif n=="false"then l.k="VFALSE"elseif n=="..."then j(o.is_vararg==true,"cannot use '...' outside a vararg function");l.k="VVARARG"elseif n=="{"then X(l)return elseif n=="function"then e()S(l,false,d)return else V(l)return end e()end local function A(o,t)local l=n local a=ne[l]if a then e()A(o,ee)else G(o)end l=n local n=M[l]while n and n>t do local o={}e()local e=A(o,W[l])l=e n=M[l]end return l end function c(e)A(e,0)end local function M(e)local n={}local e=e.v.k j(e=="VLOCAL"or e=="VUPVAL"or e=="VGLOBAL"or e=="VINDEXED","syntax error")if t(",")then local e={}e.v={}V(e.v)M(e)else a("=")O(n)return end n.k="VNONRELOC"end local function l(e,n)a("do")m(false)k(e)K()_()end local function G(e)local n=s p("(for index)")p("(for limit)")p("(for step)")h(e)a("=")R()a(",")R()if t(",")then R()else end l(1,true)end local function z(e)local n={}p("(for generator)")p("(for state)")p("(for control)")h(e)local e=1 while t(",")do h(T())e=e+1 end a("in")local o=s O(n)l(e,false)end local function q(e)local l=false F(e)while n=="."do U(e)end if n==":"then l=true U(e)end return l end function R()local e={}c(e)end local function l()local e={}c(e)end local function A()e()l()a("then")K()end local function R()local n,e={}h(T())n.k="VLOCAL"k(1)S(e,false,d)end local function U()local e=0 local n={}repeat h(T())e=e+1 until not t(",")if t("=")then O(n)else n.k="VVOID"end k(e)end function O(e)c(e)while t(",")do c(e)end end function S(l,n,e)Q()a("(")if n then p("self",true)k(1)end Z()a(")")g()u("end","function",e)H()end function K()m(false)g()_()end local function p()local o=s m(true)e()local l=T()local e=n if e=="="then G(l)elseif e==","or e=="in"then z(l)else r("'=' or 'in' expected")end u("end","for",o)_()end local function h()local n=s e()l()m(true)a("do")K()u("end","while",n)_()end local function T()local n=s m(true)m(false)e()g()u("until","repeat",n)l()_()_()end local function k()local l=s local o={}A()while n=="elseif"do A()end if n=="else"then e()K()end u("end","if",l)end local function _()local l={}e()local e=n if C[e]or e==";"then else O(l)end end local function m()local n=o.bl e()while n and not n.isbreakable do n=n.prev end if not n then r("no loop to break")end end local function c()local n=i-1 local e={}e.v={}V(e.v)if e.v.k=="VCALL"then I[n]="call"else e.prev=nil M(e)I[n]="assign"end end local function r()local o=s local l,n={},{}e()local e=q(l)S(n,e,o)end local function l()local n=s e()K()u("end","do",n)end local function a()e()if t("function")then R()else U()end end local a={["if"]=k,["while"]=h,["do"]=l,["for"]=p,["repeat"]=T,["function"]=r,["local"]=a,["return"]=_,["break"]=m,}local function l()s=d local e=n local n=a[e]if n then I[i-1]=e n()if e=="return"or e=="break"then return true end else c()end return false end function g()local e=false while not e and not C[n]do e=l()t(";")end end function parser()Q()o.is_vararg=true e()g()D("")H()return{globalinfo=N,localinfo=f,statinfo=I,toklist=v,seminfolist=L,toklnlist=w,xreflist=y,}end function init(e,t,a)i=1 Y={}local n=1 v,L,w,y={},{},{},{}for l=1,#e do local e=e[l]local o=true if e=="TK_KEYWORD"or e=="TK_OP"then e=t[l]elseif e=="TK_NAME"then e=""L[n]=t[l]elseif e=="TK_NUMBER"then e=""L[n]=0 elseif e=="TK_STRING"or e=="TK_LSTRING"then e=""L[n]=""elseif e=="TK_EOS"then e=""else o=false end if o then v[n]=e w[n]=a[l]y[n]=l n=n+1 end end N,P,f={},{},{}E,x={},{}I={}end end b.optlex=function()module"optlex"local u=l.require"string"local t=u.match local e=u.sub local r=u.find local d=u.rep local p error=l.error warn={}local a,o,f local m={TK_KEYWORD=true,TK_NAME=true,TK_NUMBER=true,TK_STRING=true,TK_LSTRING=true,TK_OP=true,TK_EOS=true,}local _={TK_COMMENT=true,TK_LCOMMENT=true,TK_EOL=true,TK_SPACE=true,}local c local function E(e)local n=a[e-1]if e<=1 or n=="TK_EOL"then return true elseif n==""then return E(e-1)end return false end local function K(n)local e=a[n+1]if n>=#a or e=="TK_EOL"or e=="TK_EOS"then return true elseif e==""then return K(n+1)end return false end local function w(l)local n=#t(l,"^%-%-%[=*%[")local l=e(l,n+1,-(n-1))local e,n=1,0 while true do local l,a,t,o=r(l,"([\r\n])([\r\n]?)",e)if not l then break end e=l+1 n=n+1 if#o>0 and t~=o then e=e+1 end end return n end local function L(i,r)local l=t local n,e=a[i],a[r]if n=="TK_STRING"or n=="TK_LSTRING"or e=="TK_STRING"or e=="TK_LSTRING"then return""elseif n=="TK_OP"or e=="TK_OP"then if(n=="TK_OP"and(e=="TK_KEYWORD"or e=="TK_NAME"))or(e=="TK_OP"and(n=="TK_KEYWORD"or n=="TK_NAME"))then return""end if n=="TK_OP"and e=="TK_OP"then local n,e=o[i],o[r]if(l(n,"^%.%.?$")and l(e,"^%."))or(l(n,"^[~=<>]$")and e=="=")or(n=="["and(e=="["or e=="="))then return" "end return""end local n=o[i]if e=="TK_OP"then n=o[r]end if l(n,"^%.%.?%.?$")then return" "end return""else return" "end end local function T()local r,i,l={},{},{}local e=1 for n=1,#a do local t=a[n]if t~=""then r[e],i[e],l[e]=t,o[n],f[n]e=e+1 end end a,o,f=r,i,l end local function S(r)local n=o[r]local n=n local a if t(n,"^0[xX]")then local e=l.tostring(l.tonumber(n))if#e<=#n then n=e else return end end if t(n,"^%d+%.?0*$")then n=t(n,"^(%d+)%.?0*$")if n+0>0 then n=t(n,"^0*([1-9]%d*)$")local o=#t(n,"0*$")local l=l.tostring(o)if o>#l+1 then n=e(n,1,#n-o).."e"..l end a=n else a="0"end elseif not t(n,"[eE]")then local o,n=t(n,"^(%d*)%.(%d+)$")if o==""then o=0 end if n+0==0 and o==0 then a="0"else local i=#t(n,"0*$")if i>0 then n=e(n,1,#n-i)end if o+0>0 then a=o.."."..n else a="."..n local o=#t(n,"^0*")local o=#n-o local l=l.tostring(#n)if o+2+#l<1+#n then a=e(n,-o).."e-"..l end end end else local n,o=t(n,"^([^eE]+)[eE]([%+%-]?%d+)$")o=l.tonumber(o)local i,r=t(n,"^(%d*)%.(%d*)$")if i then o=o-#r n=i..r end if n+0==0 then a="0"else local i=#t(n,"^0*")n=e(n,i+1)i=#t(n,"0*$")if i>0 then n=e(n,1,#n-i)o=o+i end local l=l.tostring(o)if o==0 then a=n elseif o>0 and(o<=1+#l)then a=n..d("0",o)elseif o<0 and(o>=-#n)then i=#n+o a=e(n,1,i).."."..e(n,i+1)elseif o<0 and(#l>=-o-#n)then i=-o-#n a="."..d("0",i)..n else a=n.."e"..o end end end if a and a~=o[r]then if c then p(" (line "..f[r]..") "..o[r].." -> "..a)c=c+1 end o[r]=a end end local function v(s)local n=o[s]local i=e(n,1,1)local T=(i=="'")and'"'or"'"local n=e(n,2,-2)local l=1 local h,d=0,0 while l<=#n do local s=e(n,l,l)if s=="\\"then local o=l+1 local c=e(n,o,o)local a=r("abfnrtv\\\n\r\"'0123456789",c,1,true)if not a then n=e(n,1,l-1)..e(n,o)l=l+1 elseif a<=8 then l=l+2 elseif a<=10 then local t=e(n,o,o+1)if t=="\r\n"or t=="\n\r"then n=e(n,1,l).."\n"..e(n,o+2)elseif a==10 then n=e(n,1,l).."\n"..e(n,o+1)end l=l+2 elseif a<=12 then if c==i then h=h+1 l=l+2 else d=d+1 n=e(n,1,l-1)..e(n,o)l=l+1 end else local a=t(n,"^(%d%d?%d?)",o)o=l+1+#a local f=a+0 local c=u.char(f)local r=r("\a\b\f\n\r\t\v",c,1,true)if r then a="\\"..e("abfnrtv",r,r)elseif f<32 then if t(e(n,o,o),"%d")then a="\\"..a else a="\\"..f end elseif c==i then a="\\"..c h=h+1 elseif c=="\\"then a="\\\\"else a=c if c==T then d=d+1 end end n=e(n,1,l-1)..a..e(n,o)l=l+#a end else l=l+1 if s==T then d=d+1 end end end if h>d then l=1 while l<=#n do local o,a,t=r(n,"(['\"])",l)if not o then break end if t==i then n=e(n,1,o-2)..e(n,o)l=o else n=e(n,1,o-1).."\\"..e(n,o)l=o+2 end end i=T end n=i..n..i if n~=o[s]then if c then p(" (line "..f[s]..") "..o[s].." -> "..n)c=c+1 end o[s]=n end end local function A(s)local n=o[s]local c=t(n,"^%[=*%[")local l=#c local u=e(n,-l,-1)local i=e(n,l+1,-(l+1))local a=""local n=1 while true do local l,o,c,r=r(i,"([\r\n])([\r\n]?)",n)local o if not l then o=e(i,n)elseif l>=n then o=e(i,n,l-1)end if o~=""then if t(o,"%s+$")then warn.LSTRING="trailing whitespace in long string near line "..f[s]end a=a..o end if not l then break end n=l+1 if l then if#r>0 and c~=r then n=n+1 end if not(n==1 and n==l)then a=a.."\n"end end end if l>=3 then local e,n=l-1 while e>=2 do local l="%]"..d("=",e-2).."%]"if not t(a,l)then n=e end e=e-1 end if n then l=d("=",n-2)c,u="["..l.."[","]"..l.."]"end end o[s]=c..a..u end local function O(s)local l=o[s]local c=t(l,"^%-%-%[=*%[")local n=#c local f=e(l,-(n-2),-1)local i=e(l,n+1,-(n-1))local a=""local l=1 while true do local o,n,c,r=r(i,"([\r\n])([\r\n]?)",l)local n if not o then n=e(i,l)elseif o>=l then n=e(i,l,o-1)end if n~=""then local l=t(n,"%s*$")if#l>0 then n=e(n,1,-(l+1))end a=a..n end if not o then break end l=o+1 if o then if#r>0 and c~=r then l=l+1 end a=a.."\n"end end n=n-2 if n>=3 then local e,l=n-1 while e>=2 do local n="%]"..d("=",e-2).."%]"if not t(a,n)then l=e end e=e-1 end if l then n=d("=",l-2)c,f="--["..n.."[","]"..n.."]"end end o[s]=c..a..f end local function k(l)local n=o[l]local t=t(n,"%s*$")if#t>0 then n=e(n,1,-(t+1))end o[l]=n end local function N(o,n)if not o then return false end local l=t(n,"^%-%-%[=*%[")local l=#l local t=e(n,-l,-1)local e=e(n,l+1,-(l-1))if r(e,o,1,true)then return true end end function optimize(n,i,t,r)local u=n["opt-comments"]local s=n["opt-whitespace"]local h=n["opt-emptylines"]local b=n["opt-eols"]local I=n["opt-strings"]local x=n["opt-numbers"]local g=n["opt-experimental"]local R=n.KEEP c=n.DETAILS and 0 p=p or l.print if b then u=true s=true h=true elseif g then s=true end a,o,f=i,t,r local n=1 local l,r local i local function t(t,l,e)e=e or n a[e]=t or""o[e]=l or""end if g then while true do l,r=a[n],o[n]if l=="TK_EOS"then break elseif l=="TK_OP"and r==";"then t("TK_SPACE"," ")end n=n+1 end T()end n=1 while true do l,r=a[n],o[n]local c=E(n)if c then i=nil end if l=="TK_EOS"then break elseif l=="TK_KEYWORD"or l=="TK_NAME"or l=="TK_OP"then i=n elseif l=="TK_NUMBER"then if x then S(n)end i=n elseif l=="TK_STRING"or l=="TK_LSTRING"then if I then if l=="TK_STRING"then v(n)else A(n)end end i=n elseif l=="TK_COMMENT"then if u then if n==1 and e(r,1,1)=="#"then k(n)else t()end elseif s then k(n)end elseif l=="TK_LCOMMENT"then if N(R,r)then if s then O(n)end i=n elseif u then local e=w(r)if _[a[n+1]]then t()l=""else t("TK_SPACE"," ")end if not h and e>0 then t("TK_EOL",d("\n",e))end if s and l~=""then n=n-1 end else if s then O(n)end i=n end elseif l=="TK_EOL"then if c and h then t()elseif r=="\r\n"or r=="\n\r"then t("TK_EOL","\n")end elseif l=="TK_SPACE"then if s then if c or K(n)then t()else local l=a[i]if l=="TK_LCOMMENT"then t()else local e=a[n+1]if _[e]then if(e=="TK_COMMENT"or e=="TK_LCOMMENT")and l=="TK_OP"and o[i]=="-"then else t()end else local e=L(i,n+1)if e==""then t()else t("TK_SPACE"," ")end end end end end else error("unidentified token encountered")end n=n+1 end T()if b then n=1 if a[1]=="TK_COMMENT"then n=3 end while true do l,r=a[n],o[n]if l=="TK_EOS"then break elseif l=="TK_EOL"then local l,e=a[n-1],a[n+1]if m[l]and m[e]then local n=L(n-1,n+1)if n==""or e=="TK_EOS"then t()end end end n=n+1 end T()end if c and c>0 then p()end return a,o,f end end b.optparser=function()module"optparser"local a=l.require"string"local K=l.require"table"local t="etaoinshrdlucmfwypvbgkqjxz_ETAOINSHRDLUCMFWYPVBGKQJXZ"local d="etaoinshrdlucmfwypvbgkqjxz_0123456789ETAOINSHRDLUCMFWYPVBGKQJXZ"local w={}for e in a.gmatch([[ and break do else elseif end false for function if in local nil not or repeat return then true until while self]],"%S+")do w[e]=true end local r,u,i,L,_,N,o,T,E,S,O,c local function I(e)local t={}for a=1,#e do local n=e[a]local o=n.name if not t[o]then t[o]={decl=0,token=0,size=0,}end local e=t[o]e.decl=e.decl+1 local t=n.xref local l=#t e.token=e.token+l e.size=e.size+l*#o if n.decl then n.id=a n.xcount=l if l>1 then n.first=t[2]n.last=t[l]end else e.id=a end end return t end local function x(e)local i=a.byte local a=a.char local n={TK_KEYWORD=true,TK_NAME=true,TK_NUMBER=true,TK_STRING=true,TK_LSTRING=true,}if not e["opt-comments"]then n.TK_COMMENT=true n.TK_LCOMMENT=true end local l={}for e=1,#r do l[e]=u[e]end for e=1,#o do local e=o[e]local n=e.xref for e=1,e.xcount do local e=n[e]l[e]=""end end local e={}for n=0,255 do e[n]=0 end for o=1,#r do local o,l=r[o],l[o]if n[o]then for n=1,#l do local n=i(l,n)e[n]=e[n]+1 end end end local function l(o)local n={}for l=1,#o do local o=i(o,l)n[l]={c=o,freq=e[o],}end K.sort(n,function(n,e)return n.freq>e.freq end)local e={}for l=1,#n do e[l]=a(n[l].c)end return K.concat(e)end t=l(t)d=l(d)end local function y()local n local i,r=#t,#d local e=O if ee local o=e%i e=(e-o)/i o=o+1 n=a.sub(t,o,o)while l>1 do local o=e%r e=(e-o)/r o=o+1 n=n..a.sub(d,o,o)l=l-1 end end O=O+1 return n,E[n]~=nil end local function R(A,x,S,t)local e=m or l.print local n=a.format local p=t.DETAILS if t.QUIET then return end local T,m,b,w,N,k,_,h,v,I,i,u,f,O,g,r,s,d,E,L=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 local function t(e,n)if e==0 then return 0 end return n/e end for n,e in l.pairs(A)do T=T+1 i=i+e.token r=r+e.size end for n,e in l.pairs(x)do m=m+1 _=_+e.decl u=u+e.token s=s+e.size end for n,e in l.pairs(S)do b=b+1 h=h+e.decl f=f+e.token d=d+e.size end w=T+m v=k+_ O=i+u E=r+s N=T+b I=k+h g=i+f L=r+d if p then local p={}for n,e in l.pairs(A)do e.name=n p[#p+1]=e end K.sort(p,function(n,e)return n.size>e.size end)local l,m="%8s%8s%10s %s","%8d%8d%10.2f %s"local T=a.rep("-",44)e("*** global variable list (sorted by size) ***\n"..T)e(n(l,"Token","Input","Input","Global"))e(n(l,"Count","Bytes","Average","Name"))e(T)for l=1,#p do local l=p[l]e(n(m,l.token,l.size,t(l.token,l.size),l.name))end e(T)e(n(m,i,r,t(i,r),"TOTAL"))e(T.."\n")local l,p="%8s%8s%8s%10s%8s%10s %s","%8d%8d%8d%10.2f%8d%10.2f %s"local a=a.rep("-",70)e("*** local variable list (sorted by allocation order) ***\n"..a)e(n(l,"Decl.","Token","Input","Input","Output","Output","Global"))e(n(l,"Count","Count","Bytes","Average","Bytes","Average","Name"))e(a)for l=1,#c do local i=c[l]local l=S[i]local r,a=0,0 for n=1,#o do local e=o[n]if e.name==i then r=r+e.xcount a=a+e.xcount*#e.oldname end end e(n(p,l.decl,l.token,a,t(r,a),l.size,t(l.token,l.size),i))end e(a)e(n(p,h,f,s,t(u,s),d,t(f,d),"TOTAL"))e(a.."\n")end local c,o="%-16s%8s%8s%8s%8s%10s","%-16s%8d%8d%8d%8d%10.2f"local l=a.rep("-",58)e("*** local variable optimization summary ***\n"..l)e(n(c,"Variable","Unique","Decl.","Token","Size","Average"))e(n(c,"Types","Names","Count","Count","Bytes","Bytes"))e(l)e(n(o,"Global",T,k,i,r,t(i,r)))e(l)e(n(o,"Local (in)",m,_,u,s,t(u,s)))e(n(o,"TOTAL (in)",w,v,O,E,t(O,E)))e(l)e(n(o,"Local (out)",b,h,f,d,t(f,d)))e(n(o,"TOTAL (out)",N,I,g,L,t(g,L)))e(l.."\n")end local function f()local function o(e)local n=i[e+1]or""local l=i[e+2]or""local e=i[e+3]or""if n=="("and l==""and e==")"then return true end end local l={}local e=1 while e<=#i do local n=T[e]if n=="call"and o(e)then l[e+1]=true l[e+3]=true e=e+3 end e=e+1 end local n,e,o=1,1,#i local t={}while e<=o do if l[n]then t[_[n]]=true n=n+1 end if n>e then if n<=o then i[e]=i[n]L[e]=L[n]_[e]=_[n]-(n-e)T[e]=T[n]else i[e]=nil L[e]=nil _[e]=nil T[e]=nil end end n=n+1 e=e+1 end local e,n,l=1,1,#r while n<=l do if t[e]then e=e+1 end if e>n then if e<=l then r[n]=r[e]u[n]=u[e]else r[n]=nil u[n]=nil end end e=e+1 n=n+1 end end local function s(r)O=0 c={}E=I(N)S=I(o)if r["opt-entropy"]then x(r)end local e={}for n=1,#o do e[n]=o[n]end K.sort(e,function(n,e)return n.xcount>e.xcount end)local l,n,d={},1,false for o=1,#e do local e=e[o]if not e.isself then l[n]=e n=n+1 else d=true end end e=l local i=#e while i>0 do local a,l repeat a,l=y()until not w[a]c[#c+1]=a local n=i if l then local t=N[E[a].id].xref local a=#t for l=1,i do local l=e[l]local i,e=l.act,l.rem while e<0 do e=o[-e].rem end local o for n=1,a do local n=t[n]if n>=i and n<=e then o=true end end if o then l.skip=true n=n-1 end end end while n>0 do local l=1 while e[l].skip do l=l+1 end n=n-1 local t=e[l]l=l+1 t.newname=a t.skip=true t.done=true local i,r=t.first,t.last local c=t.xref if i and n>0 then local a=n while a>0 do while e[l].skip do l=l+1 end a=a-1 local e=e[l]l=l+1 local a,l=e.act,e.rem while l<0 do l=o[-l].rem end if not(rl)then if a>=t.act then for o=1,t.xcount do local o=c[o]if o>=a and o<=l then n=n-1 e.skip=true break end end else if e.last and e.last>=t.act then n=n-1 e.skip=true end end end if n==0 then break end end end end local l,n={},1 for o=1,i do local e=e[o]if not e.done then e.skip=false l[n]=e n=n+1 end end e=l i=#e end for e=1,#o do local e=o[e]local n=e.xref if e.newname then for l=1,e.xcount do local n=n[l]u[n]=e.newname end e.name,e.oldname=e.newname,e.name else e.oldname=e.name end end if d then c[#c+1]="self"end local e=I(o)R(E,S,e,r)end function optimize(n,t,l,e)r,u=t,l i,L,_=e.toklist,e.seminfolist,e.xreflist N,o,T=e.globalinfo,e.localinfo,e.statinfo if n["opt-locals"]then s(n)end if n["opt-experimental"]then f()end end end b.equiv=function()module"equiv"local e=l.require"string"local d=l.loadstring local s=e.sub local c=e.match local i=e.dump local _=e.byte local f={TK_KEYWORD=true,TK_NAME=true,TK_NUMBER=true,TK_STRING=true,TK_LSTRING=true,TK_OP=true,TK_EOS=true,}local t,e,r function init(o,l,n)t=o e=l r=n end local function a(n)e.init(n)e.llex()local l,t=e.tok,e.seminfo local e,n={},{}for o=1,#l do local l=l[o]if f[l]then e[#e+1]=l n[#n+1]=t[o]end end return e,n end function source(n,f)local function s(e)local e=d("return "..e,"z")if e then return i(e)end end local function o(e)if t.DETAILS then l.print("SRCEQUIV: "..e)end r.SRC_EQUIV=true end local e,d=a(n)local l,r=a(f)local n=c(n,"^(#[^\r\n]*)")local a=c(f,"^(#[^\r\n]*)")if n or a then if not n or not a or n~=a then o("shbang lines different")end end if#e~=#l then o("count "..#e.." "..#l)return end for n=1,#e do local e,i=e[n],l[n]local a,l=d[n],r[n]if e~=i then o("type ["..n.."] "..e.." "..i)break end if e=="TK_KEYWORD"or e=="TK_NAME"or e=="TK_OP"then if e=="TK_NAME"and t["opt-locals"]then elseif a~=l then o("seminfo ["..n.."] "..e.." "..a.." "..l)break end elseif e=="TK_EOS"then else local t,i=s(a),s(l)if not t or not i or t~=i then o("seminfo ["..n.."] "..e.." "..a.." "..l)break end end end end function binary(a,o)local e=0 local N=1 local I=3 local v=4 local function e(e)if t.DETAILS then l.print("BINEQUIV: "..e)end r.BIN_EQUIV=true end local function l(e)local n=c(e,"^(#[^\r\n]*\r?\n?)")if n then e=s(e,#n+1)end return e end local n=d(l(a),"z")if not n then e("failed to compile original sources for binary chunk comparison")return end local l=d(l(o),"z")if not l then e("failed to compile compressed result for binary chunk comparison")end local t={i=1,dat=i(n)}t.len=#t.dat local c={i=1,dat=i(l)}c.len=#c.dat local K,d,u,m,T,o,h local function r(e,n)if e.i+n-1>e.len then return end return true end local function p(n,e)if not e then e=1 end n.i=n.i+e end local function a(n)local e=n.i if e>n.len then return end local l=s(n.dat,e,e)n.i=e+1 return _(l)end local function L(l)local n,e=0,1 if not r(l,d)then return end for o=1,d do n=n+e*a(l)e=e*256 end return n end local function O(n)local e=0 if not r(n,d)then return end for l=1,d do e=e*256+a(n)end return e end local function k(l)local n,e=0,1 if not r(l,u)then return end for o=1,u do n=n+e*a(l)e=e*256 end return n end local function g(n)local e=0 if not r(n,u)then return end for l=1,u do e=e*256+a(n)end return e end local function f(e,o)local n=e.i local l=n+o-1 if l>e.len then return end local l=s(e.dat,n,l)e.i=n+o return l end local function i(n)local e=h(n)if not e then return end if e==0 then return""end return f(n,e)end local function _(e,n)local e,n=a(e),a(n)if not e or not n or e~=n then return end return e end local function s(e,n)local e=_(e,n)if not e then return true end end local function b(e,n)local e,n=o(e),o(n)if not e or not n or e~=n then return end return e end local function E(l,n)if not i(l)or not i(n)then e("bad source name");return end if not o(l)or not o(n)then e("bad linedefined");return end if not o(l)or not o(n)then e("bad lastlinedefined");return end if not(r(l,4)and r(n,4))then e("prototype header broken")end if s(l,n)then e("bad nups");return end if s(l,n)then e("bad numparams");return end if s(l,n)then e("bad is_vararg");return end if s(l,n)then e("bad maxstacksize");return end local t=b(l,n)if not t then e("bad ncode");return end local a=f(l,t*m)local t=f(n,t*m)if not a or not t or a~=t then e("bad code block");return end local t=b(l,n)if not t then e("bad nconst");return end for o=1,t do local o=_(l,n)if not o then e("bad const type");return end if o==N then if s(l,n)then e("bad boolean value");return end elseif o==I then local l=f(l,T)local n=f(n,T)if not l or not n or l~=n then e("bad number value");return end elseif o==v then local l=i(l)local n=i(n)if not l or not n or l~=n then e("bad string value");return end end end local t=b(l,n)if not t then e("bad nproto");return end for o=1,t do if not E(l,n)then e("bad function prototype");return end end local a=o(l)if not a then e("bad sizelineinfo1");return end local t=o(n)if not t then e("bad sizelineinfo2");return end if not f(l,a*d)then e("bad lineinfo1");return end if not f(n,t*d)then e("bad lineinfo2");return end local a=o(l)if not a then e("bad sizelocvars1");return end local t=o(n)if not t then e("bad sizelocvars2");return end for n=1,a do if not i(l)or not o(l)or not o(l)then e("bad locvars1");return end end for l=1,t do if not i(n)or not o(n)or not o(n)then e("bad locvars2");return end end local t=o(l)if not t then e("bad sizeupvalues1");return end local o=o(n)if not o then e("bad sizeupvalues2");return end for n=1,t do if not i(l)then e("bad upvalues1");return end end for l=1,o do if not i(n)then e("bad upvalues2");return end end return true end if not(r(t,12)and r(c,12))then e("header broken")end p(t,6)K=a(t)d=a(t)u=a(t)m=a(t)T=a(t)p(t)p(c,12)if K==1 then o=L h=k else o=O h=g end E(t,c)if t.i~=t.len+1 then e("inconsistent binary chunk1");return elseif c.i~=c.len+1 then e("inconsistent binary chunk2");return end end end b["plugin/html"]=function()module"plugin/html"local n=l.require"string"local u=l.require"table"local s=l.require"io"local f=".html"local h={["&"]="&",["<"]="<",[">"]=">",["'"]="'",['"']=""",}local m=[[ %s
]]local T=[[
]]local p=[[ BODY { background: white; color: navy; } pre.code { color: black; } span.comment { color: #00a000; } span.string { color: #009090; } span.keyword { color: black; font-weight: bold; } span.number { color: #993399; } span.operator { } span.name { } span.global { color: #ff0000; font-weight: bold; } span.local { color: #0000ff; font-weight: bold; } ]]local a local e,o local t,d,r local function i(...)if a.QUIET then return end l.print(...)end function init(i,t,r)a=i e=t local t,r=n.find(e,"%.[^%.%\\%/]*$")local i,c=e,""if t and t>1 then i=n.sub(e,1,t-1)c=n.sub(e,t,r)end o=i..f if a.OUTPUT_FILE then o=a.OUTPUT_FILE end if e==o then l.error("output filename identical to input filename")end end function post_load(n)i([[ HTML plugin module for LuaSrcDiet ]])i("Exporting: "..e.." -> "..o.."\n")end function post_lex(e,n,l)t,d,r=e,n,l end local function r(l)local e=1 while e<=#l do local o=n.sub(l,e,e)local t=h[o]if t then o=t l=n.sub(l,1,e-1)..o..n.sub(l,e+1)end e=e+#o end return l end local function h(n,o)local e=s.open(n,"wb")if not e then l.error('cannot open "'..n..'" for writing')end local o=e:write(o)if not o then l.error('cannot write to "'..n..'"')end e:close()end function post_parse(f,s)local c={}local function i(e)c[#c+1]=e end local function l(e,n)i(''..n..'')end for e=1,#f do local e=f[e]local e=e.xref for n=1,#e do local e=e[n]t[e]="TK_GLOBAL"end end for e=1,#s do local e=s[e]local e=e.xref for n=1,#e do local e=e[n]t[e]="TK_LOCAL"end end i(n.format(m,r(e),p))for e=1,#t do local e,n=t[e],d[e]if e=="TK_KEYWORD"then l("keyword",n)elseif e=="TK_STRING"or e=="TK_LSTRING"then l("string",r(n))elseif e=="TK_COMMENT"or e=="TK_LCOMMENT"then l("comment",r(n))elseif e=="TK_GLOBAL"then l("global",n)elseif e=="TK_LOCAL"then l("local",n)elseif e=="TK_NAME"then l("name",n)elseif e=="TK_NUMBER"then l("number",n)elseif e=="TK_OP"then l("operator",r(n))elseif e~="TK_EOS"then i(n)end end i(T)h(o,u.concat(c))a.EXIT=true end end b["plugin/sloc"]=function()module"plugin/sloc"local a=l.require"string"local e=l.require"table"local o local r function init(n,e,l)o=n o.QUIET=true r=e end local function i(o)local l={}local n,t=1,#o while n<=t do local e,i,c,r=a.find(o,"([\r\n])([\r\n]?)",n)if not e then e=t+1 end l[#l+1]=a.sub(o,n,e-1)n=e+1 if ee and c~=r then n=n+1 end end return l end function post_lex(n,c,d)local e,t=0,0 local function a(n)if n>e then t=t+1;e=n end end for e=1,#n do local n,l,e=n[e],c[e],d[e]if n=="TK_KEYWORD"or n=="TK_NAME"or n=="TK_NUMBER"or n=="TK_OP"then a(e)elseif n=="TK_STRING"then local n=i(l)e=e-#n+1 for n=1,#n do a(e);e=e+1 end elseif n=="TK_LSTRING"then local n=i(l)e=e-#n+1 for l=1,#n do if n[l]~=""then a(e)end e=e+1 end end end l.print(r..": "..t)o.EXIT=true end end local o=k"llex"local s=k"lparser"local g=k"optlex"local v=k"optparser"local O=k"equiv"local l local b=[[ LuaSrcDiet: Puts your Lua 5.1 source code on a diet Version 0.12.1 (20120407) Copyright (c) 2012 Kein-Hong Man The COPYRIGHT file describes the conditions under which this software may be distributed. ]]local h=[[ usage: LuaSrcDiet [options] [filenames] example: >LuaSrcDiet myscript.lua -o myscript_.lua options: -v, --version prints version information -h, --help prints usage information -o specify file name to write output -s suffix for output files (default '_') --keep keep block comment with inside --plugin run in plugin/ directory - stop handling arguments (optimization levels) --none all optimizations off (normalizes EOLs only) --basic lexer-based optimizations only --maximum maximize reduction of source (informational) --quiet process files quietly --read-only read file and print token stats only --dump-lexer dump raw tokens from lexer to stdout --dump-parser dump variable tracking tables from parser --details extra info (strings, numbers, locals) features (to disable, insert 'no' prefix like --noopt-comments): %s default settings: %s]]local _=[[ --opt-comments,'remove comments and block comments' --opt-whitespace,'remove whitespace excluding EOLs' --opt-emptylines,'remove empty lines' --opt-eols,'all above, plus remove unnecessary EOLs' --opt-strings,'optimize strings and long strings' --opt-numbers,'optimize numbers' --opt-locals,'optimize local variable names' --opt-entropy,'tries to reduce symbol entropy of locals' --opt-srcequiv,'insist on source (lexer stream) equivalence' --opt-binequiv,'insist on binary chunk equivalence' --opt-experimental,'apply experimental optimizations' ]]local N=[[ --opt-comments --opt-whitespace --opt-emptylines --opt-numbers --opt-locals --opt-srcequiv --opt-binequiv ]]local R=[[ --opt-comments --opt-whitespace --opt-emptylines --noopt-eols --noopt-strings --noopt-numbers --noopt-locals --noopt-entropy --opt-srcequiv --opt-binequiv ]]local S=[[ --opt-comments --opt-whitespace --opt-emptylines --opt-eols --opt-strings --opt-numbers --opt-locals --opt-entropy --opt-srcequiv --opt-binequiv ]]local x=[[ --noopt-comments --noopt-whitespace --noopt-emptylines --noopt-eols --noopt-strings --noopt-numbers --noopt-locals --noopt-entropy --opt-srcequiv --opt-binequiv ]]local r="_"local w="plugin/"local function t(e)m("LuaSrcDiet (error): "..e);os.exit(1)end if not X(_VERSION,"5.1",1,1)then t("requires Lua 5.1 to run")end local a=""do local t=24 local n={}for l,o in Q(_,"%s*([^,]+),'([^']+)'")do local e=" "..l e=e..i.rep(" ",t-#e)..o.."\n"a=a..e n[l]=true n["--no"..p(l,3)]=true end _=n end h=i.format(h,a,N)if z then local e="\nembedded plugins:\n"for n=1,#z do local n=z[n]e=e.." "..Z[n].."\n"end h=h..e end local I=r local e={}local r,a local function T(n)for n in Q(n,"(%-%-%S+)")do if p(n,3,4)=="no"and _["--"..p(n,5)]then e[p(n,5)]=false else e[p(n,3)]=true end end end local d={"TK_KEYWORD","TK_NAME","TK_NUMBER","TK_STRING","TK_LSTRING","TK_OP","TK_EOS","TK_COMMENT","TK_LCOMMENT","TK_EOL","TK_SPACE",}local u=7 local f={["\n"]="LF",["\r"]="CR",["\n\r"]="LFCR",["\r\n"]="CRLF",}local function c(e)local n=io.open(e,"rb")if not n then t('cannot open "'..e..'" for reading')end local l=n:read("*a")if not l then t('cannot read from "'..e..'"')end n:close()return l end local function A(n,l)local e=io.open(n,"wb")if not e then t('cannot open "'..n..'" for writing')end local l=e:write(l)if not l then t('cannot write to "'..n..'"')end e:close()end local function L()r,a={},{}for e=1,#d do local e=d[e]r[e],a[e]=0,0 end end local function K(e,n)r[e]=r[e]+1 a[e]=a[e]+#n end local function E()local function t(e,n)if e==0 then return 0 end return n/e end local o={}local e,n=0,0 for l=1,u do local l=d[l]e=e+r[l];n=n+a[l]end r.TOTAL_TOK,a.TOTAL_TOK=e,n o.TOTAL_TOK=t(e,n)e,n=0,0 for l=1,#d do local l=d[l]e=e+r[l];n=n+a[l]o[l]=t(r[l],a[l])end r.TOTAL_ALL,a.TOTAL_ALL=e,n o.TOTAL_ALL=t(e,n)return o end local function M(e)local e=c(e)o.init(e)o.llex()local e,l=o.tok,o.seminfo for n=1,#e do local n,e=e[n],l[n]if n=="TK_OP"and i.byte(e)<32 then e="("..i.byte(e)..")"elseif n=="TK_EOL"then e=f[e]else e="'"..e.."'"end m(n.." "..e)end end local function C(e)local n=m local e=c(e)o.init(e)o.llex()local e,o,l=o.tok,o.seminfo,o.tokln s.init(e,o,l)local e=s.parser()local l,t=e.globalinfo,e.localinfo local o=i.rep("-",72)n("*** Local/Global Variable Tracker Tables ***")n(o.."\n GLOBALS\n"..o)for e=1,#l do local l=l[e]local e="("..e..") '"..l.name.."' -> "local l=l.xref for o=1,#l do e=e..l[o].." "end n(e)end n(o.."\n LOCALS (decl=declared act=activated rem=removed)\n"..o)for e=1,#t do local l=t[e]local e="("..e..") '"..l.name.."' decl:"..l.decl.." act:"..l.act.." rem:"..l.rem if l.isself then e=e.." isself"end e=e.." -> "local l=l.xref for o=1,#l do e=e..l[o].." "end n(e)end n(o.."\n")end local function P(l)local e=m local n=c(l)o.init(n)o.llex()local n,o=o.tok,o.seminfo e(b)e("Statistics for: "..l.."\n")L()for e=1,#n do local e,n=n[e],o[e]K(e,n)end local n=E()local l=i.format local function c(e)return r[e],a[e],n[e]end local t,o="%-16s%8s%8s%10s","%-16s%8d%8d%10.2f"local n=i.rep("-",42)e(l(t,"Lexical","Input","Input","Input"))e(l(t,"Elements","Count","Bytes","Average"))e(n)for t=1,#d do local t=d[t]e(l(o,t,c(t)))if t=="TK_EOS"then e(n)end end e(n)e(l(o,"Total Elements",c("TOTAL_ALL")))e(n)e(l(o,"Total Tokens",c("TOTAL_TOK")))e(n.."\n")end local function y(p,T)local function n(...)if e.QUIET then return end _G.print(...)end if l and l.init then e.EXIT=false l.init(e,p,T)if e.EXIT then return end end n(b)local u=c(p)if l and l.post_load then u=l.post_load(u)or u if e.EXIT then return end end o.init(u)o.llex()local c,f,h=o.tok,o.seminfo,o.tokln if l and l.post_lex then l.post_lex(c,f,h)if e.EXIT then return end end L()for e=1,#c do local n,e=c[e],f[e]K(n,e)end local _=E()local b,m=r,a v.print=n s.init(c,f,h)local s=s.parser()if l and l.post_parse then l.post_parse(s.globalinfo,s.localinfo)if e.EXIT then return end end v.optimize(e,c,f,s)if l and l.post_optparse then l.post_optparse()if e.EXIT then return end end local s=g.warn g.print=n c,f,h=g.optimize(e,c,f,h)if l and l.post_optlex then l.post_optlex(c,f,h)if e.EXIT then return end end local l=ee.concat(f)if i.find(l,"\r\n",1,1)or i.find(l,"\n\r",1,1)then s.MIXEDEOL=true end O.init(e,o,s)O.source(u,l)O.binary(u,l)local h="before and after lexer streams are NOT equivalent!"local u="before and after binary chunks are NOT equivalent!"if s.SRC_EQUIV then if e["opt-srcequiv"]then t(h)end else n("*** SRCEQUIV: token streams are sort of equivalent")if e["opt-locals"]then n("(but no identifier comparisons since --opt-locals enabled)")end n()end if s.BIN_EQUIV then if e["opt-binequiv"]then t(u)end else n("*** BINEQUIV: binary chunks are sort of equivalent")n()end A(T,l)L()for e=1,#c do local e,n=c[e],f[e]K(e,n)end local o=E()n("Statistics for: "..p.." -> "..T.."\n")local l=i.format local function c(e)return b[e],m[e],_[e],r[e],a[e],o[e]end local o,t="%-16s%8s%8s%10s%8s%8s%10s","%-16s%8d%8d%10.2f%8d%8d%10.2f"local e=i.rep("-",68)n("*** lexer-based optimizations summary ***\n"..e)n(l(o,"Lexical","Input","Input","Input","Output","Output","Output"))n(l(o,"Elements","Count","Bytes","Average","Count","Bytes","Average"))n(e)for o=1,#d do local o=d[o]n(l(t,o,c(o)))if o=="TK_EOS"then n(e)end end n(e)n(l(t,"Total Elements",c("TOTAL_ALL")))n(e)n(l(t,"Total Tokens",c("TOTAL_TOK")))n(e)if s.LSTRING then n("* WARNING: "..s.LSTRING)elseif s.MIXEDEOL then n("* WARNING: ".."output still contains some CRLF or LFCR line endings")elseif s.SRC_EQUIV then n("* WARNING: "..h)elseif s.BIN_EQUIV then n("* WARNING: "..u)end n()end local c={...}local r={}T(N)local function f(a)for n=1,#a do local n=a[n]local l local o,c=i.find(n,"%.[^%.%\\%/]*$")local r,i=n,""if o and o>1 then r=p(n,1,o-1)i=p(n,o,c)end l=r..I..i if#a==1 and e.OUTPUT_FILE then l=e.OUTPUT_FILE end if n==l then t("output filename identical to input filename")end if e.DUMP_LEXER then M(n)elseif e.DUMP_PARSER then C(n)elseif e.READ_ONLY then P(n)else y(n,l)end end end local function d()local n,o=#c,1 if n==0 then e.HELP=true end while o<=n do local n,a=c[o],c[o+1]local i=X(n,"^%-%-?")if i=="-"then if n=="-h"then e.HELP=true;break elseif n=="-v"then e.VERSION=true;break elseif n=="-s"then if not a then t("-s option needs suffix specification")end I=a o=o+1 elseif n=="-o"then if not a then t("-o option needs a file name")end e.OUTPUT_FILE=a o=o+1 elseif n=="-"then break else t("unrecognized option "..n)end elseif i=="--"then if n=="--help"then e.HELP=true;break elseif n=="--version"then e.VERSION=true;break elseif n=="--keep"then if not a then t("--keep option needs a string to match for")end e.KEEP=a o=o+1 elseif n=="--plugin"then if not a then t("--plugin option needs a module name")end if e.PLUGIN then t("only one plugin can be specified")end e.PLUGIN=a l=k(w..a)o=o+1 elseif n=="--quiet"then e.QUIET=true elseif n=="--read-only"then e.READ_ONLY=true elseif n=="--basic"then T(R)elseif n=="--maximum"then T(S)elseif n=="--none"then T(x)elseif n=="--dump-lexer"then e.DUMP_LEXER=true elseif n=="--dump-parser"then e.DUMP_PARSER=true elseif n=="--details"then e.DETAILS=true elseif _[n]then T(n)else t("unrecognized option "..n)end else r[#r+1]=n end o=o+1 end if e.HELP then m(b..h);return true elseif e.VERSION then m(b);return true end if#r>0 then if#r>1 and e.OUTPUT_FILE then t("with -o, only one source file can be specified")end f(r)return true else t("nothing to do!")end end if not d()then t("Please run with option -h or --help for usage information")end