#!/usr/local/bin/sbasic -q
#
# This program is distributed under the terms of the GPL v2.0 or later
# Download the GNU Public License (GPL) from www.gnu.org
#
# $Id: texi2html.bas,v 1.3 2005-06-15 01:39:20 zeeb90au Exp $
# text2html.bas Copyright (c) Chris Warren-Smith July 2004
# Version 1.0
#
######################################################################
local g_fontSize
local g_excludeChapters
local g_title
local g_fileName
local g_index
map_tbl = [&
"command", "CODE";&
"var", "SPAN";&
"strong", "B";&
"uref", "U";&
"samp", "SAMP";&
"code", "CODE";&
"dfn", "I"]
map_cont = 0
map_rpl = ""
map_len = (len(map_tbl)/2)-1
map_skip = 0
g_fontSize = 2
func toString(ar, index)
local s, arLen, i
arLen = len(ar)-1
if (index <= arLen) then
s = ar(index)
fi
for i = index+1 to arLen
s = s + " " + ar(i)
next i
toString = s
end
func replaceAll(s, find, repl)
local i, s_len, s_end, f_len
i = 1
s_len = len(s)
f_len = len(find)
while i < s_len
i = instr(i, s, find)
if (i = 0) then
exit loop
fi
if (i+f_len < len(s)) then
s_end = mid(s, i+f_len)
else
s_end = ""
fi
s = left(s, i-1) + repl + s_end
i++
wend
replaceAll = s
end
func doReplaceMap(s, i_beg, byref i_end, level)
local i_at, i, offs, s_blk, s_cmd, s_beg, s_end, s_out, s_mod, out_len
s_out = s
i_at = 0
i = i_beg
s_mod = 0
while i < len(s)
ch = mid(s, i+1, 1)
if (ch = "@") then
i_at = i
elseif (ch = "{") then
## offset position of i_at in s for position in s_out
offs = len(s_out)-len(s)
s_beg = mid(s_out, i_beg+1, i_at-i_beg+offs)
s_cmd = mid(s, i_at+2, i-i_at-1)
s_blk = doReplaceMap(s, i+1, i_end, level+1)
if (i_end < len(s)) then
s_end = mid(s, i_end+1)
else
s_end = ""
fi
i = i_end
map_rpl = ""
for m = 0 to map_len
if (map_tbl(m, 0) = s_cmd) then
map_rpl = map_tbl(m, 1)
exit for
fi
next m
if (len(map_rpl) > 0) then
if (map_cont) then
s_out = s_beg+"<"+map_rpl+">"+s_blk+s_end
else
s_out = s_beg+"<"+map_rpl+">"+s_blk+"</"+map_rpl+">"+s_end
fi
else
s_out = s_beg+s_blk+s_end
fi
s_mod = 1
i_beg = 0
elseif (ch = "}") then
i_end = i+1
if (s_mod) then
out_len = instr(s_out, "}")-1
else
out_len = i-i_beg
fi
if (mid(s, i, 1) = "@") then
out_len--
fi
map_cont = 0
if (level > 0) then
doReplaceMap = mid(s_out, i_beg+1, out_len)
exit func
else
## continued from previous line
s_beg = left(s, i)
if (i_end = len(s)) then
s_end = ""
else
s_end = mid(s, i_end+1)
fi
s_out = s_beg+"</"+map_rpl+">"+s_end
fi
fi
i++
wend
map_cont = 1
i_end = i
doReplaceMap = mid(s_out, i_beg+1)
end
func replaceMap(s)
local i_end, i
i_end = 0
i = 0
if (instr(s, "@verbatim") != 0) then
map_skip = 1
elseif (instr(s, "@end verbatim") != 0) then
map_skip = 0
fi
if (map_skip = 0 && instr(s, "{") != 0) then
replaceMap = doReplaceMap(s, i, i_end, 0)
else
replaceMap = s
fi
end
func isExcludeChapter(chapter)
local c
for c in g_excludeChapters
if (instr(chapter, c) = 1) then
isExcludeChapter = 1
exit func
fi
next
isExcludeChapter = 0
end
func makeHTM(s)
local t
t = squeeze(s)
t = replaceAll(t, "&", "&")
t = replaceAll(t, "<", "<")
t = replaceAll(t, ">", ">")
makeHTM = t
end
sub addLineEnding(byref out, ending)
local s,t
s = out(len(out)-2)
if (len(s) > 0) then
t = right(s, 4)
if (t = "<hr>" || t = "<br>" || t = "</p>") then
exit sub
fi
fi
out << ending
end
sub writeHeader(byref buf, byref chapters, chapterId)
local t, nav, title, index
nav = "<title>"+g_title+"</title>"
index = 0
for chapter in chapters
if (isExcludeChapter(chapter) = 0) then
if (index = chapterId) then
' current section
title = "<b>" + chapter + "</b>"
else
title = chapter
fi
nav += "<a href=" + index + ".html>" + title + "</a> | "
fi
index++
next
if chapterId = -1 then
nav += "<a href=index.html><b>Index</b></a> | "
else
nav += "<a href=index.html>Index</a> | "
fi
nav += "<hr>"
buf << nav
end
sub readHeader(byref buffer, byref i)
local bufferLen
bufferLen = len(buffer)-1
for i =0 to bufferLen
split buffer(i), " ", v() use trim(x)
if (len(v) > 0)
if (v(0) = "@node") then
i++
exit sub
elseif (v(0) = "@c") then
# comment
elseif (v(0) = "@settitle") then
g_title = toString(v,1)
elseif (v(0) = "@setfilename") then
g_fileName = toString(v,1)
elseif (v(0) = "@set") then
s = v(1) + "=" + toString(v, 2)
env(s)
fi
fi
next i
end
func readChapterTitles(byref buffer, byref chapters, byref i)
local bufferLen
bufferLen = len(buffer)-1
while (i < bufferLen)
s = buffer(i)
if (instr(s, "@node") = 1) then
i++
exit loop
elseif (instr(s, "@chapter") = 1 || &
instr(s, "@top") = 1 || &
instr(s, "@appendix") = 1) then
chapters << rightof(s, " ")
elseif (instr(s, "@bye") = 1) then
readChapterTitles = -1
exit func
fi
i++
wend
readChapterTitles = i
end
sub readSectionTitles(byref buffer, i, byref sections)
bufferLen = len(buffer)-1
while (i < bufferLen)
s = buffer(i)
if (instr(s, "@section") = 1) then
sections << replaceMap(rightof(s, " "))
elseif (instr(s, "@node") = 1 || &
instr(s, "@chapter") = 1 || &
instr(s, "@bye") = 1) then
exit sub
fi
i++
wend
end
func createIndexNodes(byref defs, byref filename)
local deffn
for deffn in defs
node = [deffn, filename]
g_index << node
next deffn
end
func readNextSection(byref buffer, byref i, byref out, byref title, byref filename)
local bufferLen, s, inTable, inItem, s_line, defs
inTable = 0
inItem = 0
bufferLen = len(buffer)-1
while (i < bufferLen)
s = buffer(i)
s = replaceMap(s)
if (instr(s, "@node") = 1 || &
instr(s, "@bye") = 1) then
readNextSection = -1
addLineEnding out, "</p>"
createIndexNodes defs, filename
exit func
elseif (instr(s, "@section") = 1) then
# end of this section -- another section follows
title = rightof(s, " ")
i++
exit loop
elseif (instr(s, "@subs") = 1) then
#subsection or subsubsection
title = rightof(s, " ")
readNextSection = i
createIndexNodes defs, filename
exit func
fi
if (instr(s, "@c") = 1) then
# comment
elseif (instr(s, "@menu") = 1) then
out << "<br>"
i++
while (i < bufferLen)
s = buffer(i)
if (instr(s, "@end") = 1) then
exit loop
else
#menu not supported
#out << s +"<br>"
fi
i++
wend
elseif (instr(s, "@itemize") = 1 || &
instr(s, "@enumerate") = 1) then
out << "<ul>"
elseif (instr(s, "@item") = 1) then
inItem = 1
if (inTable = 1) then
s_line = rightof(s, "@item")
if (len(squeeze(leftof(s_line, "@tab"))) > 0) then
out << "<tr>"
out << "<td>" + makeHTM(leftof(s_line, "@tab")) + "</td>"
out << "<td>" + makeHTM(rightof(s_line, "@tab")) + "</td>"
out << "</tr>"
fi
else
out << "<li>" + rightof(s, " ")
fi
elseif (instr(s, "@end itemize") = 1 || &
instr(s, "@end enumerate") = 1) then
out << "</ul>"
elseif (instr(s, "@verbatim") = 1 || &
instr(s, "@example") = 1) then
out << "<pre>"
elseif (instr(s, "@end verbatim") = 1 || &
instr(s, "@end example") = 1) then
out << "</pre>"
elseif (instr(s, "@deffn") = 1) then
split s, " ", v() use trim(x)
addLineEnding out, "<br>"
# create a link to this definition from the index
out << "<a name='" + lower(v(2)) + "'>"
defs << lower(v(2))
out << "<u>" + v(1) + "</u>: "
out << "<b>" + v(2) + "</b> "
out << "<i>" + toString(v, 3)+ "</i> "
elseif (instr(s, "@end deffn") = 1) then
#####out << "<br>"
elseif (instr(s, "@table") = 1) then
out << "<ul>"
elseif (instr(s, "@end table") = 1) then
out << "</ul>"
elseif (instr(s, "@multitable") = 1) then
out << "<table>"
inTable = 1
elseif (instr(s, "@end multitable") = 1) then
out << "</table>"
inTable = 0
inItem = 0
elseif (instr(s, "@tab") = 1) then
out << " "
elseif (instr(s, "@") = 1) then
# un-supported tag
else
out << s
fi
i++
wend
#out << "</p>"
createIndexNodes defs, filename
readNextSection = i
end
func skipChapter(byref buffer, byref i)
local s
# skip past initial @chapter
i+=2
while (i < bufferLen)
s = buffer(i)
if (instr(s, "@bye") = 1) then
exit loop
elseif (instr(s, "@node") = 1) then
skipChapter = i
exit func
fi
i++
wend
skipChapter = -1
end
func processChapter(byref buffer, byref i, byref chapters, byref chapterId)
local s, sections, out, index, result, bufferLen, fname, title, nav
local sectionTitle, sstitle, ssout, ssindex, sstitle
# skip past initial @chapter
i+=2
# create the section index page
writeHeader out, chapters, chapterId
readSectionTitles buffer, i, sections
# read the chapter preface
fname = chapterId+".html"
result = readNextSection(buffer, i, out, title, fname)
addLineEnding out, "<br>"
index = 0
for section in sections
out << "<br><a href="+chapterId+"_"+index+".html>"+section+"</a>"
index++
next
tsave fname, out
index = 0
while (result != -1)
out = 0
writeHeader out, chapters, chapterId
out << "<b>"+title+"</b><br><br>"
sectionTitle = title
fname = chapterId+"_"+index+".html"
result = readNextSection(buffer, i, out, title, fname)
ssindex = 0
while (result != -1 && instr(buffer(i), "@subs") = 1)
ssout = 0
ssindex ++
sstitle = rightof(buffer(i), " ")
fname = chapterId+"_"+index+"_"+ssindex+".html"
out << "<p><a href="+fname+">"+sstitle+"</a>"
i++
writeHeader ssout, chapters, chapterId
ssout << "<b>"+sectionTitle+" > "+sstitle+"</b><br><br>"
result = readNextSection(buffer, i, ssout, title, fname)
ssout << "<hr><a href="+chapterId+"_"+index+".html>[Up]</a>"
tsave fname, ssout
wend
# section navigation
nav = "<hr>"
if (index > 0) then
nav += "<a href="+chapterId+"_"
nav += (index-1)
nav += ".html>[Prev]</a> "
else
nav += "[Prev] "
fi
if (index+1 < len(sections)) then
nav += "<a href="+chapterId+"_"
nav += (index+1)
nav += ".html>[Next]</a>"
else
nav += "[Next]"
fi
out << nav
tsave chapterId+"_"+index+".html", out
index++
wend
if (i >= bufferLen || instr(buffer(i), "@bye") = 1) then
processChapter = -1
else
processChapter = i
fi
end
func sortIndex(x,y)
if x(0) = y(0)
sortIndex = 0
elseif x(0) > y(0)
sortIndex = 1
else
sortIndex = -1
endif
end
sub execute(inputFile)
local i, ibegin, result, chapters, buffer, index, bufferLen, out
tload inputFile, buffer
bufferLen = len(buffer)-1
readHeader buffer, ibegin
result = 0
i = ibegin
while result != -1
result = readChapterTitles(buffer, chapters, i)
wend
index = 0
result = 0
i = ibegin
while result != -1
if (isExcludeChapter(chapters(index)) = 1) then
result = skipChapter(buffer, i)
else
result = processChapter(buffer, i, chapters, index)
fi
index++
wend
# create index.html
writeHeader out, chapters, -1
sort g_index use sortIndex(x,y)
letter = "A"
out << "<table><tr><td><b>A</b></td></tr>"
for index in g_index
nextLetter = upper(mid(index(0), 1,1))
if (nextLetter != letter) then
out << "<tr><td><br><b>"+nextLetter+"</b></td></tr>"
letter = nextLetter
fi
out << "<tr>"
out << "<td><a href="+index(1)+"#"+index(0)+">"+index(0)+"</a></td>"
out << "</tr>"
next index
out << "</table>"
tsave "index.html", out
# save context help lookup file
out = 0
for index in g_index
out << index(0)+":"+index(1)+"#"+index(0)
next index
tsave "help.idx", out
# these are also available
# ? title
# ? env("SUBTITLE")
end
if (len(command$) = 0) then
? "Usage: texi2html file.texi"
else
split command, " ", args() use trim(x)
fileIndex = 0
argLen = len(args)-1
for i = 0 to argLen
if (args(i) = "/x") then
i++
if (i < len(args)) then
g_excludeChapters << replaceAll(args(i), "_", " ")
fi
fi
next i
execute args(argLen)
fi