Lua 5.1.4: pretty.lua
L0001 L0002 L0003 L0004 L0005 L0006 L0007 L0008
L0009 require 'pl'
L0010
L0011 local url_shortcuts = {
L0012 manl = 'doc/manual.html#pdf-',
L0013 manc = 'doc/manual.html#',
L0014 wiki = 'http://lua-users.org/wiki/'
L0015 }
L0016
L0017 function read_annotations(file)
L0018 file = file or 'annotations.txt'
L0019 local anot = {}
L0020 local f = io.open(file)
L0021 local line = f:read();
L0022 while line do
L0023 local file,sym = line:match('#%s+([^:]+):(.*)')
L0024 if not anot[file] then anot[file] = {} end
L0025 line = f:read()
L0026 local body = List()
L0027 while line and not line:match '^#' do
L0028 body:append(line)
L0029 line = f:read()
L0030 end
L0031 body:remove(#body)
L0032 body = body:join '\n'
L0033 if #sym == 0 then
L0034 anot[file]["#file"] = body
L0035 else
L0036 anot[file][sym] = body
L0037 end
L0038 end
L0039 f:close()
L0040 return anot
L0041 end
L0042
L0043 local append = table.insert
L0044
L0045 function readtags(file)
L0046 file = file or 'tags'
L0047 local f = io.open(file)
L0048 local symbols = {}
L0049
L0050 L0051 local line = f:read()
L0052 while line:find '^!' do
L0053 line = f:read()
L0054 end
L0055
L0056 local k = 1
L0057 for line in f:lines() do
L0058 local sym,file,lno,tp,rest = line:match('([%w_]+)\t(%S+)\t(%S+)\t(%a)(.*)')
L0059 lno = lno:match '(%d+);"'
L0060 if lno then lno = tonumber(lno) end
L0061 L0062 if not symbols[sym] then symbols[sym] = {} end
L0063 append(symbols[sym],{name=sym,file=file,lno=lno,tp=tp, ts=k })
L0064 k = k + 1
L0065 end
L0066
L0067 f:close()
L0068
L0069 return symbols
L0070 end
L0071
L0072 function get_file_refs(syms,file)
L0073 L0074 local file_refs = {}
L0075 for name,entries in pairs(syms) do
L0076 for _,entry in ipairs(entries) do
L0077 if entry.file == file then
L0078 file_refs[name] = entry
L0079 end
L0080 end
L0081 end
L0082 return file_refs
L0083 end
L0084
L0085 function find_refs(syms,fname)
L0086 local res = List()
L0087 for name,entries in pairs(syms) do for _,entry in ipairs(entries) do
L0088 if entry.refs then
L0089 for rname,e in pairs(entry.refs) do
L0090 if rname == fname then res:append(entry) end
L0091 end
L0092 end
L0093 end end
L0094 return res
L0095 end
L0096
L0097
L0098 local header = [[
L0099 <html>
L0100 <head>
L0101 <link rel='stylesheet' type='text/css' href='style.css'></link>
L0102 <body>
L0103 ]]
L0104
L0105 local footer = [[
L0106 <hr/>
L0107 Generated by <a href="pretty.lua.html">pretty.lua</html>
L0108 </body></html>
L0109 ]]
L0110
L0111 local syms = readtags()
L0112 local anot = read_annotations()
L0113
L0114 function do_refs(file)
L0115 local file_refs = get_file_refs(syms,file)
L0116 print('refs',file)
L0117 local res = List()
L0118 res:append(header)
L0119 res:append (('<h1>Lua 5.1.4: %s references</h1>\n<hr/>\n'):format(file))
L0120 L0121 for name,entry in pairs(file_refs) do
L0122 local refs = find_refs(syms,name)
L0123 if refs and #refs > 0 then
L0124 res:append(('<a name="%s"/><h3>%s</h3>\n<ul>'):format(name,name))
L0125 for _,ref in ipairs(refs) do
L0126 res:append(('<li><a href="%s.html#%s">%s</a> in %s</li>\n'):format(
L0127 ref.file,ref.name,ref.name,ref.file) )
L0128 end
L0129 res:append '</ul>\n'
L0130 end
L0131 end
L0132 res:append(footer)
L0133 utils.writefile(file..'.ref.html',res:join '')
L0134 end
L0135
L0136 local lbrack,rbrack = '\001','\002'
L0137 local escaped_chars = {
L0138 ['&'] = '&',
L0139 ['<'] = '<',
L0140 ['>'] = '>',
L0141 [lbrack] = '<',
L0142 [rbrack] = '>',
L0143 }
L0144 local escape_pat = '[&<>'..lbrack..rbrack..']'
L0145
L0146 local function escape(str)
L0147 str = str:gsub('<%a+:[^>]->',function(ref)
L0148 local url
L0149 ref = ref:sub(2,-2)
L0150 local proto,rest = ref:match('^(%a+):(.+)')
L0151 if proto ~= 'http' then
L0152 local base_url = url_shortcuts[proto]
L0153 assert(base_url,"unknown url shortcut "..proto)
L0154 url = base_url .. rest
L0155 else
L0156 url = ref
L0157 end
L0158 return ('%sa href="%s"%s%s%s/a%s'):format(lbrack,url,rbrack,ref,lbrack,rbrack)
L0159 end)
L0160 return (str:gsub(escape_pat,escaped_chars))
L0161 end
L0162
L0163 local function span(t,val)
L0164 return ('<span class="%s">%s</span>'):format(t,val)
L0165 end
L0166
L0167 local function link(file,ref,text)
L0168 text = text or ref
L0169 return ('<a class="L" href="%s.html#%s">%s</a>'):format(file,ref,text)
L0170 end
L0171
L0172 local function anchor(name)
L0173 return ('<a name="%s"/a>'):format(name)
L0174 end
L0175
L0176 local function block(text)
L0177 return ('<div class="block">%s\n</div>'):format(escape(text))
L0178 end
L0179
L0180 local function add_ref(fun,sym)
L0181 if not fun then return end
L0182 if not fun.refs then fun.refs = {} end
L0183 fun.refs[sym.name] = sym
L0184 end
L0185
L0186 function prettify_c (file)
L0187 local code = List()
L0188 local f,err = io.open(file)
L0189 if not f then return nil,err end
L0190 local aa = anot[file]
L0191
L0192 print('reading',file, aa and 'annotated' or '')
L0193
L0194 L0195 L0196 local lno = 1
L0197 for line in f:lines() do
L0198 code:append(('L%04d %s\n'):format(lno,line))
L0199 lno = lno + 1
L0200 end
L0201 code = code:join ''
L0202
L0203 local res = List()
L0204 res:append(header)
L0205 res:append (('<h1>Lua 5.1.4: %s</h1>\n<hr/>\n'):format(file))
L0206 res:append '<pre>\n'
L0207
L0208 if aa and aa['#file'] then
L0209 res:append(block(aa['#file']))
L0210 end
L0211
L0212 local no_refs = path.extension(file) == '.lua'
L0213 local scanner = lexer.cpp
L0214 if no_refs then
L0215 scanner = lexer.lua
L0216 syms = {}
L0217 end
L0218
L0219 local spans = {keyword=true,number=true,string=true,comment=true,prepro=true}
L0220 local curr_fun
L0221 local dcl
L0222
L0223 for t,val in scanner(code,{},{}) do
L0224 val = escape(val)
L0225 if t == 'iden' then
L0226 L0227 local ll = val:match('^L(%d%d%d%d)')
L0228 if ll then
L0229 lno = tonumber(ll)
L0230 L0231 if dcl then
L0232 if aa and aa[dcl] then
L0233 res:append(block(aa[dcl]))
L0234 end
L0235 dcl = nil
L0236 end
L0237 else
L0238 local sym = syms[val]
L0239 if sym then
L0240 local e = sym[1]
L0241 if e.file == file and e.lno == lno then
L0242 L0243 curr_fun = e
L0244 res:append (anchor(val))
L0245 val = link(file..'.ref',val)
L0246 dcl = e.name
L0247 elseif e.tp ~= 'm' then L0248 val = link(e.file,val)
L0249 add_ref(curr_fun,e)
L0250 end
L0251 end
L0252 end
L0253 res:append(val)
L0254 elseif spans[t] then
L0255 if t == 'prepro' then
L0256 local mname = val:match('#%s*define%s+([%w_]+)')
L0257 if mname then
L0258 res:append(anchor(mname))
L0259 dcl = mname
L0260 end
L0261 local file = val:match('#%s*include "([^"]+)"')
L0262 if file then
L0263 val = link(file,'',val)
L0264 end
L0265 end
L0266 res:append(span(t,val))
L0267 else
L0268 res:append(val)
L0269 end
L0270 end
L0271
L0272 res:append '</pre>\n'
L0273 res:append(footer)
L0274 utils.writefile(file..'.html',res:join '')
L0275 end
L0276
L0277 if arg[1] then
L0278 prettify_c(arg[1])
L0279 if path.extension(arg[1]) == '.c' then
L0280 do_refs(arg[1])
L0281 end
L0282 else
L0283 local function getfiles(mask)
L0284 return dir.getfiles('.',mask):map(path.basename)
L0285 end
L0286 local c_files = getfiles '*.c'
L0287 local h_files = getfiles '*.h'
L0288 c_files:foreach(prettify_c)
L0289 h_files:foreach(prettify_c)
L0290 L0291 c_files:foreach(do_refs)
L0292 h_files:foreach(do_refs)
L0293 end
Generated by pretty.lua