1#!/usr/bin/env lua5.3
2
3
4-- special marks:
5-- \1 - paragraph (empty line)
6-- \4 - remove spaces around it
7-- \3 - ref (followed by label|)
8
9---------------------------------------------------------------
10header = [[
11<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
12<html>
13
14<head>
15<title>Lua 5.4 Reference Manual</title>
16<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
17<link rel="stylesheet" href="lua.css">
18<link rel="stylesheet" href="manual.css">
19</head>
20
21<body bgcolor="#FFFFFF">
22
23<hr>
24<h1>
25<a href="http://www.lua.org/home.html"><img src="logo.gif" alt="[Lua logo]" border="0"></a>
26Lua 5.4 Reference Manual
27</h1>
28
29by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes
30<p>
31<small>
32<a href="http://www.lua.org/copyright.html">Copyright</a>
33© 2024 Lua.org, PUC-Rio. All rights reserved.
34</small>
35<hr>
36
37<!-- ====================================================================== -->
38<p>
39
40]]
41
42footer = "\n\n</body></html>\n\n"
43
44local seefmt = '(see %s)'
45
46if arg[1] == 'port' then
47 seefmt = '(ver %s)'
48 header = string.gsub(header, "by (.-)\n",
49 "%1\n<p>Tradução: Sérgio Queiroz de Medeiros", 1)
50 header = string.gsub(header, "Lua (%d+.%d+) Reference Manual",
51 "Manual de Referência de Lua %1")
52 header = string.gsub(header, "All rights reserved",
53 "Todos os direitos reservados")
54end
55
56
57---------------------------------------------------------------
58
59local function compose (f,g)
60 assert(f and g)
61 return function (s) return g(f(s)) end
62end
63
64local function concat (f, g)
65 assert(f and g)
66 return function (s) return f(s) .. g(s) end
67end
68
69
70local Tag = {}
71
72
73setmetatable(Tag, {
74 __index = function (t, tag)
75 local v = function (n, att)
76 local e = ""
77 if type(att) == "table" then
78 for k,v in pairs(att) do e = string.format('%s %s="%s"', e, k, v) end
79 end
80 if n then
81 return string.format("<%s%s>%s</%s>", tag, e, n, tag)
82 else
83 return string.format("<%s%s>", tag, e)
84 end
85 end
86 t[tag] = v
87 return v
88 end
89})
90
91
92
93---------------------------------------------------------------
94local labels = {}
95
96
97local function anchor (text, label, link, textlink)
98 if labels[label] then
99 error("label " .. label .. " already defined")
100 end
101 labels[label] = {text = textlink, link = link}
102 return Tag.a(text, {name=link})
103end
104
105local function makeref (label)
106 assert(not string.find(label, "|"))
107 return string.format("\3%s\3", label)
108end
109
110local function ref (label)
111 local l = labels[label]
112 if not l then
113 io.stderr:write("label ", label, " undefined\n")
114 return "@@@@@@@"
115 else
116 return Tag.a(l.text, {href="#"..l.link})
117 end
118end
119
120---------------------------------------------------------------
121local function nopara (t)
122 t = string.gsub(t, "\1", "\n\n")
123 t = string.gsub(t, "<p>%s*</p>", "")
124 return t
125end
126
127local function fixpara (t)
128 t = string.gsub(t, "\1", "\n</p>\n\n<p>\n")
129 t = string.gsub(t, "<p>%s*</p>", "")
130 return t
131end
132
133local function antipara (t)
134 return "</p>\n" .. t .. "<p>"
135end
136
137
138Tag.pre = compose(Tag.pre, antipara)
139Tag.ul = compose(Tag.ul, antipara)
140
141---------------------------------------------------------------
142local Gfoots = 0
143local footnotes = {}
144
145local line = Tag.hr(nil)
146
147local function dischargefoots ()
148 if #footnotes == 0 then return "" end
149 local fn = table.concat(footnotes)
150 footnotes = {}
151 return line .. Tag.h3"footnotes:" .. fn .. line
152end
153
154
155local Glists = 0
156local listings = {}
157
158local function dischargelist ()
159 if #listings == 0 then return "" end
160 local l = listings
161 listings = {}
162 return line .. table.concat(l, line..line) .. line
163end
164
165---------------------------------------------------------------
166local counters = {
167h1 = {val = 1},
168h2 = {father = "h1", val = 1},
169h3 = {father = "h2", val = 1},
170listing = {father = "h1", val = 1},
171}
172
173local function inccounter (count)
174 counters[count].val = counters[count].val + 1
175 for c, v in pairs(counters) do
176 if v.father == count then v.val = 1 end
177 end
178end
179
180local function getcounter (count)
181 local c = counters[count]
182 if c.father then
183 return getcounter(c.father) .. "." .. c.val
184 else
185 return c.val .. ""
186 end
187end
188---------------------------------------------------------------
189
190
191local function fixed (x)
192 return function () return x end
193end
194
195local function id (x) return x end
196
197
198local function prepos (x, y)
199 assert(x and y)
200 return function (s) return string.format("%s%s%s", x, s, y) end
201end
202
203
204local rw = Tag.b
205
206
207
208
209local function LuaName (name)
210 return Tag.code(name)
211end
212
213
214local function getparam (s)
215 local i, e = string.find(s, "^[^%s@|]+|")
216 if not i then return nil, s
217 else return string.sub(s, i, e - 1), string.sub(s, e + 1)
218 end
219end
220
221
222local function gettitle (h)
223 local title, p = assert(string.match(h, "<title>(.-)</title>()"))
224 return title, string.sub(h, p)
225end
226
227local function getparamtitle (what, h, nonum)
228 local label, title, c, count
229 label, h = getparam(h)
230 title, h = gettitle(h)
231 if not nonum then
232 count = getcounter(what)
233 inccounter(what)
234 c = string.format("%s – ", count)
235 else
236 c = ""
237 end
238 label = label or count
239 if label then
240 title = anchor(title, label, count, "§"..count)
241 end
242 title = string.format("%s%s", c, title)
243 return title, h
244end
245
246local function section (what, nonum)
247 return function (h)
248 local title
249 title, h = getparamtitle(what, h, nonum)
250 local fn = what == "h1" and dischargefoots() or ""
251 h = fixpara(Tag.p(h))
252 return "</p>\n" .. Tag[what](title) .. h .. fn ..
253 dischargelist() .. "<p>"
254 end
255end
256
257
258local function verbatim (s)
259 s = nopara(s)
260 s = string.gsub(s, "\n", "\n ")
261 s = string.gsub(s, "\n%s*$", "\n")
262 return Tag.pre(s)
263end
264
265
266local function verb (s)
267 return Tag.code(s)
268end
269
270
271local function lua2link (e)
272 return string.find(e, "luaL?_") and e or "pdf-"..e
273end
274
275
276local verbfixed = verb
277
278
279local Tex = {
280
281ANSI = function (func)
282 return "ISO C function " .. Tag.code(func)
283 end,
284At = fixed"@",
285B = Tag.b,
286bigskip = fixed"",
287bignum = id,
288C = fixed"",
289Ci = prepos("<!-- ", " -->"),
290CId = function (func)
291 return "C function " .. Tag.code(func)
292 end,
293chapter = section"h1",
294Char = compose(verbfixed, prepos("'", "'")),
295Cdots = fixed"···",
296Close = fixed"}",
297col = Tag.td,
298defid = function (name)
299 local l = lua2link(name)
300 local c = Tag.code(name)
301 return anchor(c, l, l, c)
302 end,
303def = Tag.em,
304description = compose(nopara, Tag.ul),
305Em = fixed("\4" .. "—" .. "\4"),
306emph = Tag.em,
307emphx = Tag.em, -- emphasis plus index (if there was an index)
308En = fixed("–"),
309format = fixed"",
310["false"] = fixed(Tag.b"false"),
311id = Tag.code,
312idx = Tag.code,
313index = fixed"",
314Lidx = fixed"", -- Tag.code,
315ldots = fixed"...",
316x = id,
317itemize = compose(nopara, Tag.ul),
318leq = fixed"≤",
319Lid = function (s)
320 return makeref(lua2link(s))
321 end,
322M = Tag.em,
323N = function (s) return (string.gsub(s, " ", " ")) end,
324NE = id, -- tag"foreignphrase",
325num = id,
326["nil"] = fixed(Tag.b"nil"),
327fail = fixed(Tag.b"fail"),
328Open = fixed"{",
329part = section("h1", true),
330Pat = compose(verbfixed, prepos("'", "'")),
331preface = section("h1", true),
332psect = section("h2", true),
333Q = prepos('"', '"'),
334refchp = makeref,
335refcode = makeref,
336refsec = makeref,
337
338pi = fixed"π",
339rep = Tag.em, -- compose(prepos("<", ">"), Tag.em),
340Rw = rw,
341rw = rw,
342sb = Tag.sub,
343sp = Tag.sup,
344St = compose(verbfixed, prepos('"', '"')),
345sect1 = section"h1",
346sect2 = section"h2",
347sect3 = section"h3",
348sect4 = section("h4", true),
349simplesect = id,
350Tab2 = function (s) return Tag.table(s, {border=1}) end,
351row = Tag.tr,
352title = Tag.title,
353todo = Tag.todo,
354["true"] = fixed(Tag.b"true"),
355T = verb,
356
357item = function (s)
358 local t, p = string.match(s, "^([^\n|]+)|()")
359 if t then
360 s = string.sub(s, p)
361 s = Tag.b(t..": ") .. s
362 end
363 return Tag.li(fixpara(s))
364 end,
365
366verbatim = verbatim,
367
368manual = id,
369
370
371-- for the manual
372
373link =function (s)
374 local l, t = getparam(s)
375 assert(l)
376 return string.format("%s (%s)", t, makeref(l))
377end,
378
379see = function (s) return string.format(seefmt, makeref(s)) end,
380See = makeref,
381seeC = function (s)
382 return string.format(seefmt, makeref(s))
383 end,
384
385seeF = function (s)
386 return string.format(seefmt, makeref(lua2link(s)))
387 end,
388
389APIEntry = function (e)
390 local h, name
391 h, e = string.match(e, "^%s*(.-)%s*|(.*)$")
392 name = string.match(h, "(luaL?_[%w_]+)%)? +%(") or
393 string.match(h, "luaL?_[%w_]+")
394 local a = anchor(Tag.code(name), name, name, Tag.code(name))
395 local apiicmd, ne = string.match(e, "^(.-</span>)(.*)")
396--io.stderr:write(e)
397 if not apiicmd then
398 return antipara(Tag.hr() .. Tag.h3(a)) .. Tag.pre(h) .. e
399 else
400 return antipara(Tag.hr() .. Tag.h3(a)) .. apiicmd .. Tag.pre(h) .. ne
401 end
402end,
403
404LibEntry = function (e)
405 local h, name
406 h, e = string.match(e, "^(.-)|(.*)$")
407 name = string.gsub(h, " (.+", "")
408 local l = lua2link(name)
409 local a = anchor(Tag.code(h), l, l, Tag.code(name))
410 return Tag.hr() .. Tag.h3(a) .. e
411end,
412
413Produc = compose(nopara, Tag.pre),
414producname = prepos("\t", " ::= "),
415Or = fixed" | ",
416VerBar = fixed"|", -- vertical bar
417OrNL = fixed" | \4",
418bnfNter = prepos("", ""),
419bnfopt = prepos("[", "]"),
420bnfrep = prepos("{", "}"),
421bnfter = compose(Tag.b, prepos("‘", "’")),
422producbody = function (s)
423 s = string.gsub(s, "%s+", " ")
424 s = string.gsub(s, "\4", "\n\t\t")
425 return s
426 end,
427
428apii = function (s)
429 local pop,push,err = string.match(s, "^(.-),(.-),(.*)$")
430 if pop ~= "?" and string.find(pop, "%W") then
431 pop = "(" .. pop .. ")"
432 end
433 if push ~= "?" and string.find(push, "%W") then
434 push = "(" .. push .. ")"
435 end
436 err = (err == "-") and "–" or Tag.em(err)
437 return Tag.span(
438 string.format("[-%s, +%s, %s]", pop, push, err),
439 {class="apii"}
440 )
441 end,
442}
443
444local others = prepos("?? "," ??")
445
446local function trata (t)
447 t = string.gsub(t, "@(%w+)(%b{})", function (w, f)
448 f = trata(string.sub(f, 2, -2))
449 if type(Tex[w]) ~= "function" then
450 io.stderr:write(w .. "\n")
451 return others(f)
452 else
453 return Tex[w](f, w)
454 end
455 end)
456 return t
457end
458
459
460---------------------------------------------------------------------
461---------------------------------------------------------------------
462
463-- read whole book
464t = io.read"*a"
465
466t = string.gsub(t, "[<>&\128-\255]",
467 {["<"] = "<",
468 [">"] = ">",
469 ["&"] = "&",
470 ["\170"] = "ª",
471 ["\186"] = "º",
472 ["\192"] = "À",
473 ["\193"] = "Á",
474 ["\194"] = "Â",
475 ["\195"] = "Ã",
476 ["\199"] = "Ç",
477 ["\201"] = "É",
478 ["\202"] = "Ê",
479 ["\205"] = "Í",
480 ["\211"] = "Ó",
481 ["\212"] = "Ô",
482 ["\218"] = "Ú",
483 ["\224"] = "à",
484 ["\225"] = "á",
485 ["\226"] = "â",
486 ["\227"] = "ã",
487 ["\231"] = "ç",
488 ["\233"] = "é",
489 ["\234"] = "ê",
490 ["\237"] = "í",
491 ["\243"] = "ó",
492 ["\244"] = "ô",
493 ["\245"] = "õ",
494 ["\250"] = "ú",
495 ["\252"] = "ü"
496 })
497
498t = string.gsub(t, "\n\n+", "\1")
499
500
501
502-- complete macros with no arguments
503t = string.gsub(t, "(@%w+)([^{%w])", "%1{}%2")
504
505t = trata(t)
506
507-- correct references
508t = string.gsub(t, "\3(.-)\3", ref)
509
510-- remove extra space (??)
511t = string.gsub(t, "%s*\4%s*", "")
512
513t = nopara(t)
514
515-- HTML 3.2 does not need </p> (but complains when it is in wrong places :)
516t = string.gsub(t, "</p>", "")
517
518io.write(header, t, footer)
519