#line 217 "l2h.nw" procedure star(cs) suspend cs | (cs || "*") end #line 596 "l2h.nw" procedure asciiCharCode(S) return emit_text(S, char(2(optwhite(), TeXnumber(), optwhite()))) end procedure TeXnumber() return integer( (="'", "8r" || tab(many(&digits))) | (="\"", "16r" || tab(many(&digits))) | tab(many(&digits))) end #line 671 "l2h.nw" procedure convert(S, optstring) static specials initial { #line 819 "l2h.nw" activetab := table(unknown_cs) activeclosure := table() #line 969 "l2h.nw" cstab := table(unknown_cs) csclosure := table() #line 987 "l2h.nw" unknown_set := set() #line 1015 "l2h.nw" every begintab | endtab := table(unknown_env) every begincl | endcl := table() #line 1028 "l2h.nw" unknown_envs := set() #line 1381 "l2h.nw" liststack := [] # write(&errout, "Initialized liststack") suspendstack := [] #line 1961 "l2h.nw" countertab := table() #line 1969 "l2h.nw" accent_name := table() accent_valid := table('') accent_name ["`"] := "grave" accent_valid["`"] := 'AEIOUaeiou' accent_name ["'"] := "acute" accent_valid["'"] := 'AEIOUYaeiouy' accent_name ["^"] := "circ" accent_valid["^"] := 'AEIOUaeiou' accent_name ["hat"] := "circ" accent_valid["hat"] := 'AEIOUaeiou' accent_name ["\""] := "uml" accent_valid["\""] := 'AEIOUaeiouy' accent_name ["~"] := "tilde" accent_valid["~"] := 'ANOano' accent_name ["="] := "bar" accent_name ["."] := "dot" accent_name ["u"] := "u" accent_name ["v"] := "v" accent_name ["H"] := "H" accent_name ["t"] := "t" accent_name ["c"] := "cedil" accent_valid["c"] := 'Cc' accent_name ["d"] := "underdot" accent_name ["b"] := "underbar" #line 2675 "l2h.nw" csfunctions := table() #line 675 "l2h.nw" #line 114 "l2h.nw" substitution(",", " ") substitution(" ", " ") substitution("\n", "\n") substitution("\t", " ") ignore("raggedright") ignore("@") ignore("/") # no italic correction substitution("", "\n") # \ treated as request for newline every c := !"$%#{}_" do substitution(c, c) substitution("&", "&") argblock("emph", "em") every argblock("footnote" | "footnotetext" | "thanks", " [", "] ") # put footnotes in bold brackets substitution("today", &date) #line 132 "l2h.nw" ignore("textrm") # html can't switch to default font! argblock("textit", "i") argblock("textbf", "b") argblock("textsl", "i") ignore("textsc") argblock("texttt", "tt") ignore("textsf") ignore("boldmath") # \boldmath could be done by introducing S.mathfont, but I don't want to! #line 142 "l2h.nw" ignore("mathrm") # html can't switch to default font! argblock("mathit", "i") argblock("mathbf", "b") argblock("mathtt", "tt") ignore("mathsf") argblock("mathcal", "i") every ignore("scriptstyle"|"displaystyle"|"scriptscriptstyle") every ignore("mathord"|"mathbin"|"mathrel") #line 152 "l2h.nw" every ignore("tiny" | "scriptsize" | "footnotesize" | "small" | "normalsize" | "large" | "Large" | "LARGE" | "huge" | "Huge") #line 160 "l2h.nw" every accent(key(accent_name)) every ignore("dag" | "ddag") substitution("S", "§") substitution("P", "¶") substitution("copyright", "©") substitution("pounds", "£") substitution("o", "ø") substitution("O", "Ø") substitution("aa", "å") substitution("AA", "Å") substitution("ae", "æ") substitution("AE", "&Aelig;") #line 175 "l2h.nw" argblockv("part", "h1", &null, "*[") argblockv("chapter", "h1", &null, "*[") argblockv("section", "h2", &null, "*[") argblockv("subsection", "h3", &null, "*[") argblockv("subsubsection", "h4", &null, "*[") argblockv("paragraph", "h5", &null, "*[") argblockv("subparagraph", "h6", &null, "*[") ignore("appendix") auxfile("tableofcontents", "toc", "

\n\n[Table of contents]\n\n

", "

Table of Contents

\n\n", "\n\n") cstab["tableofcontents"] := Ctableofcontents # override to call set_toclevel ignore("listoftables") ignore("listoffigures") ignore("addtocontents", "{{") ignoreenv("filecontents", "{") #line 198 "l2h.nw" cstab["("] := Cmath cstab[")"] := Cmath_end cstab["["] := Cdisplaymath cstab["]"] := Cdisplaymath_end ignoreenv("equation") every table_env(star("eqnarray"), 0, " ", "
", "
") # also lame substitution("frac", "frac") substitution("sqrt", "frac") every substitution("ldots" | "cdots" | "vdots", "...") ignore("left") ignore("right") ignore("overline") substitution(":", " ") substitution(";", " ") ignore("!") #line 223 "l2h.nw" substitution("Diamond", "<>") substitution("langle", "<") substitution("rangle", ">") substitution("le", "<=") substitution("ne", "!=") substitution("ge", ">=") substitution("times", "×") substitution("divide", "÷") substitution("bmod", "mod") # better hook in with math substitution("equiv", "===") every x := "arccos" | "arcsin" | "arctan" | "arg" | "cos" | "cosh" | "cot" | "coth" | "csc" | "deg" | "det" | "dim" | "exp" | "gcd" | "hom" | "lim" | "liminf" | "limsup" | "ln" | "log" | "max" | "min" | "sec" | "sin" | "sinh" | "sup" | "tan" | "tanh" do substitution(x, "" || x || "") substitution("liminf", "lim inf") substitution("limsup", "lim sup") every x := "alpha" | "beta" | "gamma" | "delta" | "epsilon" | "zeta" | "eta" | "theta" | "iota" | "kappa" | "lambda" | "nu" | "xi" | "pi" | "rho" | "sigma" | "tau" | "upsilon" | "phi" | "chi" | "psi" | "omega" | "in" do substitution(x, "" || x || "") substitution("mu", "µ") every x := "Gamma" | "Delta" | "Theta" | "Lambda" | "Xi" | "Pi" | "Sigma" | "Upsilon" | "Phi" | "Psi" | "Omega" do substitution(x, "" || x || "") #line 255 "l2h.nw" substitution("lfloor", "|_") substitution("rfloor", "_|") substitution("leq", "<=") substitution("geq", ">=") substitution("ll", "«") substitution("gg", "»") substitution("Rightarrow", "==>") substitution("rightarrow", "-->") substitution("approx", "~") #line 268 "l2h.nw" envblock("quote", "blockquote") envblock("quotation", "blockquote") envblock("center", "blockquote") envblock("flushleft", "blockquote") envblock("flushright", "blockquote") envblock("verse", "blockquote") verbatim("verbatim", escape_HTML_specials, "pre") cstab["verb"] := Cverb cstab["verb*"] := Cverb csclosure["verb*"] := 1 cstab["verbatiminput"] := Cverbatiminput csclosure["verbatiminput"] := verbatim_cl(escape_HTML_specials) #line 284 "l2h.nw" cstab["item"] := Citem csclosure["item"] := [item_cl("
  • ", "", "
  • ")] listenv("itemize", "ul") listenv("enumerate", "ol") listenv("description", "dl") #line 292 "l2h.nw" ignore("documentstyle", "[{") ignore("documentclass", "[{") ignore("usepackage", "[{") ignore("pagestyle", "{") ignore("thispagestyle", "{") ignore("pagenumbering", "{") ignore("newcounter", "{") ignore("global") ignore("etalchar") # used in the .bbl files: \newcommand{\etalchar}[1]{$^{#1}$} #line 307 "l2h.nw" argblockv("title", "h1") argblockv("author","address") argblockv("date", "b") substitution("maketitle", "") ignoreenv("titlepage") envblock("abstract", "

    Abstract

    ", "
    ") #line 322 "l2h.nw" cstab["label"] := Clabel cstab["ref"] := Cref cstab["pageref"] := Cref cstab["subpageref"] := Cref cstab["chunklabel"] := Clabel #line 332 "l2h.nw" ignore("bibliographystyle", "{") auxfile("bibliography", "bbl", "[BibTeX bibliography]", &null, &null, "{") envblock("thebibliography", "

    References

    ", "", "{") every cstab["cite" | "citeN" | "opencite" | "openciteN" | "citeyear"] := Ccite cstab["bibitem"] := Cbibitem ignore("newblock") ignore("nocite", "{") #line 343 "l2h.nw" every ignore("input" | "include" | "includeonly", "{") # filecontents not done yet #line 348 "l2h.nw" cstab["\\"] := Cbackback substitution("linebreak", "
    ") ignore("-") ignoreenv("sloppypar") ignore("sloppy") #line 357 "l2h.nw" substitution("pagebreak", "
    ") substitution("newpage", "
    ") substitution("clearpage", "
    ") ignore("enlargethispage", "*{") #line 364 "l2h.nw" ignore("mbox") ignore("makebox", "([[") # ( comes from picture area ignore("fbox") ignore("framebox", "[[") # could insert horizontal rules, but why? ignore("newsavebox", 1) ignore("sbox", 2) ignore("savebox", "{[[{") ignore("usebox", 1) envblock("minipage", "blockquote", &null, "[{") argblock("parbox", "blockquote", &null, "[{") #line 377 "l2h.nw" ignore("hspace", "*{") ignore("hfil") ignore("hfill") ignore("vspace", "*{") ignore("vfil") ignore("vfill") #line 386 "l2h.nw" ignore("newlength", "{") ignore("setlength", "{{") ignore("addtolength", "{{") #line 392 "l2h.nw" envblock("picture", "[picture]", "", "((") ignore("put", "({") ignore("multiput", "(({{") ignore("dashbox", "{([") ignore("line", "({") ignore("vector", "({") ignore("shortstack", "[") ignore("circle", "*{") ignore("oval", "([") ignore("frame") ignore("thinlines") ignore("thicklines") #line 408 "l2h.nw" every envblock(star("figure"), "
    ", "
    ", "[") every envblock(star("table"), "
    ", "
    ", "[") argblock("caption", "b") # captions in bold #line 415 "l2h.nw" envblock("tabbing", "blockquote") # \= is accent ignore(">") ignore("+") ignore("kill") #line 423 "l2h.nw" tabular("array", "[") tabular("tabular", "[") tabular("tabularx", "{[") tabular("tabular*", "{[") every cstab["multicolumn"|"multispan"] := Cmulticolumn cstab["span"] := Cspan cstab["noalign"] := Cnoalign cstab["hline"] := Chline cstab["toprule"] := Chline cstab["midrule"] := Chline cstab["bottomrule"] := Chline ignore("cline", "{") ignore("newcolumntype", "{{") #line 439 "l2h.nw" ignore("newcommand", "A[[{") ignore("renewcommand", "A[[{") ignore("providecommand", "A[[{") ignore("newenvironment", "{[{{") ignore("renewenvironment", "{[{{") ignore("newtheorem", "{{") #line 450 "l2h.nw" cstab["setcounter"] := Csetcounter ignore("addtocounter", "{{") #line 455 "l2h.nw" cstab["makeatletter"] := Cmakeatletter cstab["makeatother"] := Cmakeatother #line 460 "l2h.nw" every fontchange("tt" | "ttfamily", "tt") every fontchange("bf" | "bfseries", "b") every fontchange("it" | "itshape", "i") fontchange("sl", "i") fontchange("em", "em") ignore("rm") # html can't switch to default font! ignore("sf") ignore("sc") #line 470 "l2h.nw" ignore("rmfamily") ignore("normalfont") #line 473 "l2h.nw" ignoreenv("document") #line 475 "l2h.nw" substitution("LaTeX", "LaTeX") #line 477 "l2h.nw" ignore("numberline", "{") ignore("protect") ignore("onecolumn") ignore("twocolumn", "C") ignore("typeout", "[{") ignore("closedbib") #line 484 "l2h.nw" every ignore("leftmargini" | "leftmarginii" | "labelsep" | "fboxsep", "=") every ignore("tabcolsep", "=") every ignore("evensidemargin" | "marginparsep" | "marginparwidth" | "oddsidemargin" | "textheight" | "textwidth" | "topmargin", "=") #line 489 "l2h.nw" ignore("DeclareMathVersion", "{") ignore("mathversion", "{") ignore("setpapersize", "{") ignore("setmarginsrb", "{{{{{{{{") ignore("marginparwidth", "=") ignore("marginparsep", "=") #line 498 "l2h.nw" ignoreenv("multicols", "{C") cstab["citeN"] := Ccite ignore("afterpage", "{") every cstab["psfig"|"epsfig"] := Cepsfig cstab["includegraphics"] := Cincludegraphics ignore("newcolumntype", "{{") #line 507 "l2h.nw" cstab["kill"] := Ckill #line 511 "l2h.nw" activesubst("~", " ") argblock("centerline", "
    ", "
    ") substitution("cr", "
    ") substitution("hrule", "
    ") substitution("vrule", "|") substitution("hrulefill", "------") ignore("hyphenation", "{") ignore("hbox") ignore("rlap") ignore("llap") ignore("vbox") ignore("vtop") ignore("hidewidth") ignore("message", "{") ignore("relax") ignore("null") ignore("offinterlineskip") ignore("omit") ignore("newdimen", "{") ignore("nobreak") #line 532 "l2h.nw" cstab["par"] := implicit_paragraph cstab["smallskip"] := implicit_paragraph cstab["medskip"] := implicit_paragraph cstab["bigskip"] := implicit_paragraph cstab["vskip"] := implicit_paragraph csclosure["vskip"] := "=" #line 544 "l2h.nw" every ignore("begingroup" | "endgroup" | "bgroup" | "egroup") #line 546 "l2h.nw" cstab["newif"] := Cnewif cstab["iffalse"] := Ciffalse cstab["iftrue"] := Ciftrue cstab["ifhtml"] := Ciftrue # false in LaTeX, but true when converting! cstab["else"] := Celse cstab["fi"] := Cfi cstab["ifx"] := cstab["if"] := cstab["ifnum"] := Ciffalse #line 556 "l2h.nw" ignore("let", "A=") every ignore("hfuzz" | "parindent" | "parskip" | "baselineskip", "=") every ignore("hbadness" | "hsize" | "vsize" | "overfullrule" | "tabskip", "=") every ignore("extrarowheight" | "codemargin", "=") every ignore("looseness", "=") substitution("hskip", " ", "=") ignore("setbox", "{=") every ignore("box" | "unhbox" | "unvbox", "{") #line 565 "l2h.nw" ignore("unskip") ignore("hss") ignore("phantom", "{") every ignore("kern" | "lower" | "spacefactor", "=") # a cheat, but works every ignore("clubpenalty" | "widowpenalty", "=") #line 578 "l2h.nw" every ignore("expandafter" | "indent" | "noindent" | "leavevmode" | "strut") ignore("def", 1) #line 581 "l2h.nw" substitution("TeX", "TeX") substitution("BibTeX", "BibTeX") substitution("MF", "METAFONT") #line 594 "l2h.nw" cstab["char"] := asciiCharCode #line 608 "l2h.nw" macro("nwanchorto", 2, "#2") macro("nwanchorname", 2, "#2") ignore("nwaddbox", "{") verbatim("latexonly", do_nothing) verbatim("rawhtml", emit_text) #line 617 "l2h.nw" substitution("quad", " ") #line 624 "l2h.nw" ignore("noweboptions", 1) #line 630 "l2h.nw" substitution("nowebindex", "") substitution("nowebchunks", "") ignore("nowebsize") #line 634 "l2h.nw" envblock("fields", "blockquote", &null, "[") # lame; could try to 1st col envblock("fields*", "blockquote", &null, "{") # lame; could try to 1st col ignore("citeauthoryear", "{{{") ignore("authoryear", "{{") substitution("bibrule", "--------") let("bibskip", "par") every cstab["anoncite"|"authorcite"] := Ccite #line 644 "l2h.nw" ignore("pssilent") ignore("psnoisy") #line 1012 "l2h.nw" cstab["begin"] := do_begin cstab["end"] := do_end #line 1385 "l2h.nw" cstab["suspend"] := Csuspend cstab["resume"] := Cresume #line 1603 "l2h.nw" cstab["uppercase"] := Cuppercase #line 1899 "l2h.nw" cstab["contentsline"] := Ccontentsline #line 676 "l2h.nw" #line 2677 "l2h.nw" csfunctions["argblock"] := argblock csfunctions["argblockv"] := argblockv csfunctions["envblock"] := envblock csfunctions["fontchange"] := fontchange csfunctions["ignore"] := ignore csfunctions["ignoreenv"] := ignoreenv csfunctions["let"] := let csfunctions["letenv"] := letenv csfunctions["listenv"] := listenv csfunctions["substitution"] := substitution csfunctions["activesubst"] := activesubst csfunctions["closure"] := let_closure csfunctions["let_closure"] := let_closure csfunctions["newcommand"] := l2h_macro csfunctions["macro"] := l2h_macro csfunctions["environment"] := l2h_environment csfunctions["tabular"] := tabular #line 677 "l2h.nw" specials := '\\{}<>-\'`"%$&~\n\0\1' } if \optstring then return optstring ? convert(S) else { #line 867 "l2h.nw" l := S.newtext S.newtext := [] while c := get(l) do c.proc!c.args #line 700 "l2h.nw" if S.mode == "V" & any(~'\\{}<>%\n\t ') then S.mode := "H" emit_text(S, tab(upto(specials) | 0)) while not pos(0) do if S.mode == "Q" then { # quoting emit_text(S, tab(upto('\1') | 0)) if ="\1" then { emit_text(S, "\1") S.mode := S.quotemode } } else { if any(S.activechars) then do_activechar(S, move(1)) else case move(1) of { "\\" : { #line 941 "l2h.nw" cs := if pos(0) then "" else if any(S.csletters) then tab(many(S.csletters)) else move(1) if /S.ignoring | cs == ("else"|"fi") | cstab[cs] === (Ciffalse|Ciftrue) then do_cs(S, cs) else &null # error("### Ignoring \\", cs) #line 714 "l2h.nw" } "{" : { #line 915 "l2h.nw" push(S.closes, []) # fresh set of closing tasks while c := get(S.open) do c.proc!c.args #line 715 "l2h.nw" } "}" : { #line 919 "l2h.nw" while c := get(S.closes[1]) do c.proc!c.args pop(S.closes) #line 716 "l2h.nw" } "%" : { #line 1066 "l2h.nw" parse_dynamic_add(S) delay_newtext(S) eat_comment(S) #line 717 "l2h.nw" } "\n" : { #line 1313 "l2h.nw" emit_text(S, "\n") if /S.ignoring then Cnewline(S) #line 718 "l2h.nw" } "$" : { #line 1301 "l2h.nw" if /S.ignoring then if ="$" then if S.mode == "M" then { Cdisplaymath_end(S); S.mode := "V" } else { Cdisplaymath(S); S.mode := "M" } else if S.mode == "M" then { Cmath_end(S); S.mode := "H" } else { Cmath(S); S.mode := "M" } #line 719 "l2h.nw" } "&" : ampersand(S) "\0" : {S.quotemode := S.mode; S.mode := "Q"; emit_text(S, "\0")} # remaining cases simply escape HTML specials "<" : emit_text(S, "<") ">" : emit_text(S, ">") "\"" : emit_text(S, """) "-" : { #line 735 "l2h.nw" if S.mode == "V" then S.mode := "H" if S.mode == "H" then if ="--" then emit_text(S, "—") else if ="-" then emit_text(S, "–") else emit_text(S, "-") else emit_text(S, "-") #line 726 "l2h.nw" } "`" : { #line 746 "l2h.nw" if S.mode == "V" then S.mode := "H" if \html_quotes & S.mode == "H" then if ="`" then emit_text(S, "“") else emit_text(S, "‘") else emit_text(S, "`") #line 727 "l2h.nw" } "'" : { #line 753 "l2h.nw" if S.mode == "V" then S.mode := "H" if \html_quotes & S.mode == "H" & ="'" then emit_text(S, "”") else emit_text(S, "'") #line 728 "l2h.nw" } } if S.mode == "V" & any(~'\\{}<>%\n\t ') then S.mode := "H" emit_text(S, tab(upto(specials++S.activechars) | 0)) } return 1(. S.the_text, S.the_text := "") # what's been converted #line 683 "l2h.nw" } end #line 744 "l2h.nw" global html_quotes # render quotes as HTML 4 entities #line 760 "l2h.nw" record state(mode, quotemode #line 788 "l2h.nw" , text, the_text #line 804 "l2h.nw" , ignoring #line 822 "l2h.nw" , activechars #line 844 "l2h.nw" , newtext #line 887 "l2h.nw" , delayed_newtext #line 897 "l2h.nw" , open, closes #line 949 "l2h.nw" , csletters #line 1082 "l2h.nw" , comment #line 1521 "l2h.nw" , ifstack #line 1628 "l2h.nw" , tables #line 760 "l2h.nw" ) # mode is Q, H, V, or M # quotemode is saved mode: H, V, or M #line 766 "l2h.nw" procedure converter(mode) /mode := "V" return state(mode, mode #line 790 "l2h.nw" , accumulate_text, "" #line 806 "l2h.nw" , &null #line 824 "l2h.nw" , '~' #line 846 "l2h.nw" , [] #line 889 "l2h.nw" , [] #line 899 "l2h.nw" , [], [] #line 951 "l2h.nw" , &letters #line 1084 "l2h.nw" , "" #line 1523 "l2h.nw" , [] #line 1630 "l2h.nw" , [] #line 768 "l2h.nw" ) end #line 774 "l2h.nw" procedure reset(S) #line 792 "l2h.nw" S.text := accumulate_text S.the_text := "" #line 808 "l2h.nw" S.ignoring := &null #line 826 "l2h.nw" S.activechars := '~' #line 848 "l2h.nw" S.newtext := [] #line 891 "l2h.nw" S.delayed_newtext := [] #line 901 "l2h.nw" every S.open | S.closes := [] #line 953 "l2h.nw" S.csletters := &letters #line 1086 "l2h.nw" S.comment := "" #line 1525 "l2h.nw" if *S.ifstack > 0 then S.ifstack := [] # keeps GC down #line 1632 "l2h.nw" S.tables := [] #line 776 "l2h.nw" return S end #line 783 "l2h.nw" procedure accumulate_text(S, text) S.the_text ||:= text return end #line 800 "l2h.nw" procedure emit_text(S, text) return if \S.ignoring then "" else S.text(S, text) end #line 813 "l2h.nw" global activetab, activeclosure procedure do_activechar(S, c) (activetab[c])(S, c, activeclosure[c]) return end #line 852 "l2h.nw" record closure(proc, args) #line 857 "l2h.nw" procedure before_next_newtext(S, proc, args) push(S.newtext, closure(proc, args)) end procedure after_next_newtext(S, proc, args) put(S.newtext, closure(proc, args)) end #line 876 "l2h.nw" procedure delay_newtext(S) push(S.delayed_newtext, S.newtext) S.newtext := [] return end procedure undelay_newtext(S) S.newtext := \pop(S.delayed_newtext) | {write(&errout, "This can't happen: no delayed_newtext"); &null[0]} end #line 903 "l2h.nw" procedure after_next_open(S, proc, args) return put(S.open, closure(proc, args)) end procedure before_next_close(S, proc, args) return push(S.closes[1], closure(proc, args)) # lost at top level end procedure after_next_close(S, proc, args) return put(S.closes[1], closure(proc, args)) # lost at top level end #line 960 "l2h.nw" global cstab, csclosure procedure do_cs(S, cs) tab(many(' \t')) # skip white space following CS if pos(0) | any('\n') then before_next_newtext(S, skipblanks, [S]) (cstab[cs])(S, cs, csclosure[cs]) return end #line 976 "l2h.nw" global show_unknowns procedure unknown_cs(S, cs, cl) # if S.text === ignore_text then return # a bit of a hack -- should no longer be needed if \show_unknowns then S.text(S, "\\" || cs || "") if not member(unknown_set, cs) then { write(\unknown_file, "Warning: unknown control sequence \\", cs) insert(unknown_set, cs) } return end #line 989 "l2h.nw" global cstab, csclosure, unknown_set #line 995 "l2h.nw" global begintab, endtab, begincl, endcl procedure do_begin(S, cs, cl) (="{", env := tab(upto('}')), ="}") | error("botched \\begin{...}") #line 915 "l2h.nw" push(S.closes, []) # fresh set of closing tasks while c := get(S.open) do c.proc!c.args #line 1000 "l2h.nw" (begintab[env])(S, env, begincl[env]) return end procedure do_end(S, cs, cl) (="{", env := tab(upto('}')), ="}") | error("botched \\end{...}") # write(&errout, "calling ", image(endtab[env]), " for \\end{", env, "}") (endtab[env])(S, env, endcl[env]) #line 919 "l2h.nw" while c := get(S.closes[1]) do c.proc!c.args pop(S.closes) #line 1009 "l2h.nw" return end #line 1018 "l2h.nw" procedure unknown_env(S, env, cl) ### if S.text === ignore_text then return # a bit of a hack # no longer needed if \show_unknowns then S.text(S, "{" || env || "}") if not member(unknown_envs, env) then { write(\unknown_file, "Warning: unknown environment {", env, "}") insert(unknown_envs, env) } return end #line 1030 "l2h.nw" global unknown_envs #line 1034 "l2h.nw" procedure warn_unknown(s, type, mark, rmark) if *s > 0 then { pushout("Unknown " || type || ": ") every pushout(((\mark | "")\1) || !sort(s) || ((\rmark | "")\1) || " ") pushout("\n") } end #line 1042 "l2h.nw" procedure pushout(s) static col initial col := 0 if find("\n", s) then s ? { pushout(tab(upto('\n'))) while ="\n" do {col := 0; write(&errout)} pushout(tab(0)) } else { col +:= *s if col >= 79 then {writes(&errout, "\n "); col := *s + 2} writes(&errout, s) } return end #line 1070 "l2h.nw" procedure eat_comment(S) S.comment ||:= tab(upto('\n') | 0) if pos(0) then before_next_newtext(S, eat_comment, [S]) else { undelay_newtext(S) Ccomment(S) S.comment := "" } return end #line 1106 "l2h.nw" record verbatim_cl(output, terminator, html, translate_blank) procedure verbatim(name, output, html) begintab[name] := Cverbatim begincl [name] := verbatim_cl(output, &null, html) return end procedure Cverbatim(S, cs, cl) if cl === begincl[cs] & /cl.terminator then cl := begincl[cs] := verbatim_cl(cl.output, "\\end{" || cs || "}", cl.html, cl.translate_blank) emit_text(S, tag(\cl.html)) delay_newtext(S) do_verbatim(S, cl) return end #line 1128 "l2h.nw" procedure do_verbatim(S, cl) if cl.output(S, tab(find(cl.terminator)), cl) then { =cl.terminator emit_text(S, endtag(\cl.html)) undelay_newtext(S) } else { cl.output(S, tab(0), cl) before_next_newtext(S, do_verbatim, [S, cl]) } return end #line 1142 "l2h.nw" procedure escape_HTML_specials(S, s, cl) s ? { while emit_text(S, tab(upto('&<>" '))) do case move(1) of { "\"" : emit_text(S, """) "&" : emit_text(S, "&") "<" : emit_text(S, "<") ">" : emit_text(S, ">") " " : emit_text(S, if \cl.translate_blank then "·" else " ") } emit_text(S, tab(0)) } return end #line 1160 "l2h.nw" procedure Cverb(S, cs, cl) Cverbatim(S, cs, verbatim_cl(escape_HTML_specials, move(1), "tt", cl)) return end #line 1166 "l2h.nw" procedure Cverbatiminput(S, cs, cl) local filename, f, line if ="{" & filename := tab(upto('}')) & ="}" then { f := \open(filename) | { emit_text(S, "Could not read file ") escape_HTML_specials(S, filename, cl) emit_text(S, "") return } emit_text(S, "\n
    \n")
        while line := read(f) do {
          escape_HTML_specials(S, line, cl)
          emit_text(S, "\n")
        }
        emit_text(S, "
    \n") close(f) } return end #line 1190 "l2h.nw" procedure csarg(S) return 2(="{", tab(bal('}', '{', '}')), ="}") | (optwhite(), if ="\\" then "\\" || (tab(many(S.csletters)) | move(1)) else move(1)) end #line 1225 "l2h.nw" procedure apply_args(S, p, as, args_wanted) delay_newtext(S) do_apply_args(S, closure(p, as), args_wanted, [], "", 0) return end procedure do_apply_args(S, cl, wanted_count, args_seen, current_arg, brace_depth) local open_comment # invariant : we have an open brace # pushtrace("APPLY") while *args_seen < wanted_count & not pos(0) do { while *args_seen < wanted_count & brace_depth = 0 & not pos(0) do { tab(many(' \t\n')) case c := move(1) of { "\\" : put(args_seen, "\\" || if pos(0) then "" else if any(S.csletters) then tab(many(S.csletters)) else move(1)) "{" : { current_arg := "" ; brace_depth := 1 } "}" : { error("Insufficient arguments to macro ", macro.name) } "%" : if tab(upto('\n')) then ="\n" else open_comment := tab(0) default : put(args_seen, c) } } while brace_depth > 0 & not pos(0) do { current_arg ||:= tab(upto('\\{}%') | 0) case move(1) of { "%" : if tab(upto('\n')) then ="\n" else open_comment := tab(0) "\\" : current_arg ||:= "\\" || if pos(0) then "" else if any(S.csletters) then tab(many(S.csletters)) else move(1) "{" : { current_arg ||:= "{" ; brace_depth +:= 1 } "}" : { brace_depth -:= 1 if brace_depth > 0 then current_arg ||:= "}" else { put(args_seen, current_arg) current_arg := "" } } } } } if *args_seen = wanted_count then { undelay_newtext(S) cl.proc ! (cl.args ||| args_seen) } else if \open_comment then { delay_newtext(S) before_next_newtext(S, skip_comment_and_continue, [S, closure(do_apply_args, [S, cl, wanted_count, args_seen, current_arg, brace_depth])]) } else before_next_newtext(S, do_apply_args, [S, cl, wanted_count, args_seen, current_arg, brace_depth]) # poptrace() return end #line 1284 "l2h.nw" procedure skip_comment_and_continue(S, cl) tab(upto('\n') | 0) if pos(0) then before_next_newtext(S, skip_comment_and_continue, [S, cl]) else { ="\n" undelay_newtext(S) # > } return end #line 1316 "l2h.nw" procedure Cnewline(S) tab(many(' \t')) if match("\n") then implicit_paragraph(S) if pos(0) then before_next_newtext(S, Cnewline, [S]) end #line 1325 "l2h.nw" procedure skipblanks(S) tab(many(' \t')) if ="\n" then Cnewline(S) else if pos(0) then before_next_newtext(S, skipblanks, [S]) end #line 1334 "l2h.nw" procedure implicit_paragraph(S, cs, cl) if S.mode ~== "V" then { S.mode := "V" Cparagraph(S) } cs_ignore(S, cs, \cl) end #line 1347 "l2h.nw" procedure stop_skipping(S) while S.newtext[1].proc === (Cnewline|skipblanks) do pop(S.newtext) end #line 1357 "l2h.nw" record item_cl(before, after, ifnone) procedure Citem(S, cs, cl) if pos(0) then after_next_newtext(S, Citem, [S, cs, cl]) else if ="[" then { delay_newtext(S) with_upto_bracket(S, "", convert_bracketed, cl) } else { skipblanks(S) emit_text(S, cl[1].ifnone) \liststack[1] := \liststack[1] + 1 } end #line 1372 "l2h.nw" procedure convert_bracketed(S, contents, cl) emit_text(S, cl[1].before || convert(converter("H"), "{" || contents || "}") || cl[1].after) optwhite() end #line 1379 "l2h.nw" global liststack, suspendstack #line 1388 "l2h.nw" procedure listenv(env, html) begintab[env] := Clist begincl[env] := html endtab[env] := Clist_end endcl[env] := html end procedure push_item_closure(cs) push(csclosure["item"], if cs == "description" then item_cl("
    ", "
    ", "
    ") else item_cl("
  • ", "--", "
  • ")) end procedure Clist(S, cs, cl) push(liststack, 1) push_item_closure(cs) emit_text(S, tag(cl)) end procedure Cresume(S, cs, cl) local n, env (="{", env := tab(upto('}')), ="}") | error("botched \\resume{...}") n := pop(suspendstack) | error("\\resume not balanced by corresponding \\suspend") push(liststack, n) push_item_closure(env) if env == "enumerate" then emit_text(S, tag(begincl[env] || " start=\"" || n || "\"")) else emit_text(S, tag(begincl[env])) end procedure Clist_end(S, cs, cl) emit_text(S, endtag(cl)) pop(csclosure["item"]) pop(liststack) end procedure Csuspend(S, cs, cl) local env (="{", env := tab(upto('}')), ="}") | error("botched \\suspend{...}") emit_text(S, endtag(endcl[env])) pop(csclosure["item"]) push(suspendstack, pop(liststack)) end #line 1437 "l2h.nw" global labels_seen procedure Clabel(S, cs, cl) initial /labels_seen := set() insert(labels_seen, l := csarg(S)) | fail emit_text(S, "[*]") end procedure Cref(S, cs, cl) local prefix, prefix_tag initial /labels_seen := set() prefix_tag := (\cl)[1] | "" prefix := (\cl)[2] | "" l := prefix || csarg(S) | fail emit_text(S, prefix_tag || "[" || (if member(labels_seen, l) then "<-" else "->") || "]") end #line 1463 "l2h.nw" procedure Ccite(S, cs, cl, bracketed_text) if ="[" then { delay_newtext(S) with_upto_bracket(S, "", do_cite, cl) } else do_cite(S, &null, cl) end procedure do_cite(S, commentary, cl) local key if \commentary then optwhite() if pos(0) then before_next_newtext(S, do_cite, [S, commentary, cl]) else { key := csarg(S) \commentary := convert(converter("H"), "{" || \commentary || "}") emit_text(S, "[cite ") key ? { while k := tab(upto(",")) & ="," do emit_text(S, "" || k || ", ") if k := tab(0) then emit_text(S, "" || k || "") } emit_text(S, ", " || \commentary || "") emit_text(S, "]") } end #line 1491 "l2h.nw" procedure Cbibitem(S, cs, cl) local label, key static counter initial counter := 0 if ="[" then { delay_newtext(S) with_upto_bracket(S, "", finish_bibitem, []) } else { label := "[" || (counter +:= 1) || "]" apply_args(S, do_bibitem_key, [S, label], 1) } end procedure do_bibitem_key(S, label, key) return emit_text(S, "" || label || " ") end procedure finish_bibitem(S, contents, args) local key, label optwhite() label := convert(converter("H"), "{" || contents || "}") key := apply_args(S, do_bibitem_key, [S, label], 1) end #line 1529 "l2h.nw" record ifrec(on_else, on_fi) #line 1538 "l2h.nw" procedure Ciffalse(S, cs, cl) #error("### \\", cs, " -> false (S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)}, ")") push(S.ifstack, ifrec(S.ignoring, S.ignoring)) S.ignoring := 1 end procedure Ciftrue(S, cs, cl) #error("### \\", cs, " -> true (S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)}, ")") push(S.ifstack, ifrec(1, S.ignoring)) end procedure Celse(S, cs, cl) S.ignoring := S.ifstack[1].on_else #error("### \\else -> S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)}) end procedure Cfi(S, cs, cl) S.ignoring := S.ifstack[1].on_fi #error("### \\fi -> S.ignoring === ", image(S.ignoring) ? {="procedure "; tab(0)}) pop(S.ifstack) end #line 1563 "l2h.nw" procedure Cnewif(S, cs, cl) local newif, newcs tab(many(' \t\n')) if pos(0) then after_next_newtext(S, Cnewif, [S, cs, cl]) else { newif := csarg(S) newif ? if ="\\if" & newcs := tab(many(S.csletters)) & pos(0) then { #line 1580 "l2h.nw" cstab[newcs || "false"] := Csetif cstab[newcs || "true"] := Csetif cstab["if" || newcs] := Ciffalse #line 1573 "l2h.nw" } else error("\\newif argument botch: " || newif) } end #line 1584 "l2h.nw" procedure Csetif(S, cs, cl) local base, tag if cs ? (base := tab(find("true"|"false")), tag := =("true"|"false"), pos(0)) then { cstab["if" || base] := if tag == "true" then Ciftrue else Ciffalse } else { error("This can't happen --- setif botch (not urgent)") } end #line 1598 "l2h.nw" procedure Cuppercase(S, cs, cl) l := map(csarg(S), &lcase, &ucase) | fail emit_text(S, l) end #line 1613 "l2h.nw" record table_info(index, # number of this cell in the row alignment, # the alignment of this cell width, # how many columns this cell will span alignments, # default alignments for this table brace_depth, # size of S.closes after start of cell cell_text) # value of S.text to use to scan this cell #line 1637 "l2h.nw" procedure start_table_cell(S, text) local this, attributes text ? { tab(many(' \t\n')) if pos(0) then return } # write(&errout, "starting cell with ", image(text)) this := S.tables[1] | fatal("starting cell with no current table") S.text := this.cell_text if /(\this).brace_depth then write(&errout, "starting table cell, ", image(this), " has null brace depth") # use this to start the current cell if this.index = 1 then emit_text(S, "") attributes := \this.alignment | aligneq("top") if this.width > 1 then attributes ||:= " colspan=" || this.width emit_text(S, "") # now update state for the next cell this.index +:= this.width # advance to next cell this.alignment := this.alignments[this.index] | &null this.width := 1 # can't set cell_text until we hit & #line 915 "l2h.nw" push(S.closes, []) # fresh set of closing tasks while c := get(S.open) do c.proc!c.args #line 1663 "l2h.nw" emit_text(S, text) return end #line 1670 "l2h.nw" procedure ampersand(S) local this this := S.tables[1] #line 919 "l2h.nw" while c := get(S.closes[1]) do c.proc!c.args pop(S.closes) #line 1674 "l2h.nw" if /this then emit_text(S, " --- ") else { emit_text(S, "") # be sure cell gets started, even if empty emit_text(S, "") if S.text ~=== start_table_cell then this.cell_text := S.text S.text := start_table_cell this.brace_depth := *S.closes + 1 # will open at start of cell #write(&errout, "set brace depth for ", image(this)) } tab(many(' \t\n')) ## write(&errout, " past &, text = ", image(S.text), ", next = ", ## image(&subject[&pos:0])) return end #line 1699 "l2h.nw" procedure Cbackback(S, cs, cl) local this this := S.tables[1] cs_ignore(S, cs, "[", Cbackback_continue, [S, this]) end procedure Cbackback_continue(S, this) #if /(\this).brace_depth then write(&errout, image(this), " has null brace depth") if /this | *S.closes > this.brace_depth then { # ordinary \\ S.text(S, "
    ") } else { # row terminator ## write(&errout, "ending row with ", image(&subject[&pos:0])) emit_text(S, "") # be sure cell gets started, even if empty #line 919 "l2h.nw" while c := get(S.closes[1]) do c.proc!c.args pop(S.closes) #line 1713 "l2h.nw" emit_text(S, "\n") tab(many(' \t\n')) if S.text ~=== start_table_cell then this.cell_text := S.text this.index := 1 this.alignment := this.alignments[this.index] | &null this.width := 1 S.text := start_table_cell this.brace_depth := *S.closes + 1 # about to open } end #line 1727 "l2h.nw" procedure Chline(S, cs, cl) if \S.tables[1] then return else emit_text(S, "
    ") return end #line 1737 "l2h.nw" procedure Ctabular_end(S, cs, cl) local this if S.text ~=== start_table_cell | S.tables[1].index > 1 then {# row in progress emit_text(S, "") # be sure cell gets started, even if empty #line 919 "l2h.nw" while c := get(S.closes[1]) do c.proc!c.args pop(S.closes) #line 1742 "l2h.nw" emit_text(S, "") } if S.text === start_table_cell then # abort it S.text := S.tables[1].cell_text emit_text(S, "") xxx := pop(S.tables) #write(&errout, "popped ", image(xxx)) return end #line 1754 "l2h.nw" procedure Ctabular(S, cs, cl) cs_ignore(S, cs, cl, Ctabular_continue, [S]) return end procedure Ctabular_continue(S) a := csarg() # alignment #write(&errout, "Alignment ", a) emit_text(S, if upto('|', a) then "" else "
    ") emit_text(S, "") a := alignments(a) emit_text(S, "") push(S.tables, table_info(1, a[1] | "l", 1, a, *S.closes+1, S.text)) #write(&errout, "pushed ", image(S.tables[1])) S.text := start_table_cell optwhite() return end #line 1777 "l2h.nw" procedure tabular(env, ignore) begintab[env] := Ctabular begincl[env] := ignore endtab[env] := Ctabular_end endcl[env] := ignore end #line 1786 "l2h.nw" procedure aligneq(a) return " align=\"" || a || "\"" end procedure valigneq(a) return " valign=\"" || a || "\"" end procedure alignments(s) a := [] s ? { while not pos(0) do case move(1) of { "l" | "X" | "Y" | "p" : { put(a, aligneq("left") || valigneq("top")); skip_bracket() } "c" : put(a, aligneq("center")) "r" : put(a, aligneq("right")) "m" : { put(a, aligneq("left") || valigneq("center")); skip_bracket() } "b" : { put(a, aligneq("left") || valigneq("bottom")); skip_bracket() } "@" | "<" | ">" | "!" : skip_bracket() "|" : &null default : &null # unrecognized... } } return a end #line 1813 "l2h.nw" procedure skip_bracket() if ="{" then { n := 1 while n > 0 & not pos(0) do { tab(upto('{}\\') | 0) case move(1) of { "{" : n +:= 1 "}" : n -:= 1 "\\" : move(1) } } } return end #line 1831 "l2h.nw" procedure Cmulticolumn(S, cs, cl) local this this := S.tables[1] n := integer(csarg()) | error("\\multicolumn or \\multispan not followed by integer") if cs == "multicolumn" then a := alignments(csarg()) # write(&errout, "\\", cs, " n = ", n, ", a = ", (\a)[1] | "???", # ", text = ", image(S.text)) if /this then return # \multicolumn without table? this.width := n this.alignment := (\a)[1] return end procedure Cspan(S, cs, cl) (\S.tables[1]).width +:= 1 return end #line 1850 "l2h.nw" procedure Cnoalign(S, cs, cl) apply_args(S, finish_noalign, [S], 1) return end procedure finish_noalign(S, arg) return if \S.ignoring then "" else accumulate_text(S, "
    " || convert(converter("V"), "{" || arg || "}") || "
    ") end #line 1862 "l2h.nw" procedure auxfile(cs, ext, placeholder, header, trailer, ignore) cstab[cs] := Cauxfile csclosure[cs] := aux_cl(ext, placeholder, header, trailer, \ignore | "") end #line 1869 "l2h.nw" record aux_cl(ext, placeholder, header, trailer, ignore) procedure Cauxfile(S, cs, cl) local auxfile, T if auxfile := open(basename(\curfile) || "." || cl.ext) then { T := converter("V") Cmakeatletter(T) S.text(S, \cl.header) while line := read(auxfile) do S.text(S, convert(T, line || "\n")) close(auxfile) S.text(S, \cl.trailer) } else { S.text(S, \cl.placeholder) } cs_ignore(S, cs, cl.ignore) if \auxfile then return end #line 1888 "l2h.nw" procedure basename(name) reverse(name) ? { tab(upto('.')) & ="." return reverse(tab(0)) } end #line 1901 "l2h.nw" procedure Ctableofcontents(S, cs, cl) S.mode := "V" Cauxfile(S, cs, cl) set_toclevel(S) end #line 1910 "l2h.nw" procedure set_toclevel(S, l) static toclevel, initiallevel if /initiallevel := \l then S.text(S, "
      ") if /l := \initiallevel then S.text(S, "
    ") if /l then return # never set a level /toclevel := l while toclevel < l do { S.text(S, "
      ") toclevel +:= 1 } while toclevel > l do { S.text(S, "
    ") toclevel -:= 1 } return end #line 1931 "l2h.nw" procedure Ccontentsline(S, cs, cl) local type, level static leveltab initial { #line 1945 "l2h.nw" l := ["part", "chapter", "section", "subsection", "subsubsection", "paragraph", "subparagraph"] leveltab := table() every i := 1 to *l do leveltab[l[i]] := i - 2 # making section level 1 #line 1934 "l2h.nw" } l := \leveltab[csarg()] | fail if l > \countertab["tocdepth"] then cs_ignore(S, cs, "{{") # skip this one else { set_toclevel(S, l) S.text(S, "
  • ") after_next_open(S, after_next_close, [S, cs_ignore, [S, cs, "{"]]) } end #line 1953 "l2h.nw" global countertab procedure Csetcounter(S, cs, cl) local counter (counter := csarg(), countertab[counter] := integer(csarg())) | cs_ignore(S, cs, "{{") end #line 1967 "l2h.nw" global accent_name, accent_valid #line 1998 "l2h.nw" procedure accent(cs) cstab[cs] := Caccent end procedure Caccent(S, cs, cl) static warned initial warned := table() arg := csarg(S) | return if arg == "\\i" then arg := "i" if arg == "\\j" then arg := "j" if *arg = 1 & any(accent_valid[cs], arg) then S.text(S, "&" || arg || accent_name[cs] || ";") else { #line 2016 "l2h.nw" /warned[cs] := set() if not member(warned[cs], arg) then { write(&errout, "Warning: Can't handle \\", cs, " with arg `", arg, "'") insert(warned[cs], arg) } #line 2012 "l2h.nw" S.text(S, arg) } end #line 2026 "l2h.nw" procedure fontchange(tex, html) cstab[tex] := Cfontchange csclosure[tex] := html end #line 2031 "l2h.nw" procedure Cfontchange(S, tex, html) S.text(S, tag(html)) before_next_close(S, emit_text, [S, endtag(html)]) end #line 2051 "l2h.nw" procedure ignore(cs, template) /template := "" cstab[cs] := cs_ignore csclosure[cs] := template end procedure ignoreenv(env, template) /template := "" begintab[env] := cs_ignore begincl[env] := template endtab[env] := do_nothing end #line 2070 "l2h.nw" procedure cs_ignore(S, cs, template, proc, args) local saved_ignore saved_ignore := S.ignoring S.ignoring := 1 if type(template) == "integer" then template := repl("{", template) return do_ignore(S, template, saved_ignore, proc, args) end #line 2084 "l2h.nw" procedure do_ignore(S, template, saved_ignore, proc, args) if *template > 0 then if optwhite() & pos(0) then after_next_newtext(S, do_ignore, [S, template, saved_ignore, proc, args]) else case template[1] of { "{" : { S.ignoring := 1 after_next_open(S, ignore_til_close, [S, template[2:0], saved_ignore, proc, args]) } "A" : { csarg(S) # had better be in one input do_ignore(S, template[2:0], saved_ignore, proc, args) } "[" : if optwhite() & ="[" then { delay_newtext(S) with_upto_bracket(S, "", ignore_bracket_plus, [S, template[2:0], saved_ignore, proc, args]) } else do_ignore(S, template[2:0], saved_ignore, proc, args) "C" : # a total cheat, means ``copy optional arg'' if optwhite() & ="[" then { S.ignoring := &null delay_newtext(S) with_upto_bracket(S, "", copy_bracket_plus, [S, template[2:0], saved_ignore, proc, args]) } else do_ignore(S, template[2:0], saved_ignore, proc, args) "=" : { delay_newtext(S) eat_assignment(S, do_ignore, [S, template[2:0], saved_ignore, proc,args]) } "*" : { (="*", optwhite()) do_ignore(S, template[2:0], saved_ignore, proc, args) } "(" : { (="(", tab(upto(')')), =")", optwhite()) do_ignore(S, template[2:0], saved_ignore, proc, args) } } else { S.ignoring := saved_ignore (\proc)!(\args) } end procedure ignore_til_close(S, template, saved_ignore, proc, args) before_next_close(S, do_ignore, [S, template, saved_ignore, proc, args]) end #line 2133 "l2h.nw" procedure do_nothing(S, cs, cl) return end #line 2144 "l2h.nw" procedure with_upto_bracket(S, bracketed_text, proc, args) bracketed_text ||:= tab(upto(']') | 0) if pos(0) then before_next_newtext(S, with_upto_bracket, [S, bracketed_text, proc, args]) else { ="]" undelay_newtext(S) (\proc)(S, bracketed_text, args) } return end #line 2158 "l2h.nw" procedure ignore_bracket_plus(S, contents, args) # contents are ignored do_ignore!args end #line 2164 "l2h.nw" procedure copy_bracket_plus(S, contents, args) local should_ignore should_ignore := args[3] | fail # saved_ignore arg to do_ignore if /should_ignore then S.text(S, convert(converter("H"), "{" || contents || "}")) do_ignore!args end #line 2177 "l2h.nw" procedure eat_assignment(S, proc, args) static decimal_chars, hex_chars, oct_chars initial { decimal_chars := &digits ++ '.,+-' hex_chars := &digits ++ 'abcdefABCDEF' oct_chars := '0124567' } optwhite() ="=" # so what if we swallow multiple = signs optwhite() if pos(0) then { before_next_newtext(S, eat_assignment, [S, proc, args]) return } else if glue() then { # finished } else if any(decimal_chars) then { tab(many(decimal_chars)) optwhite() if ="\\" then tab(many(S.csletters)) | move(1) # else assume assignment of the form \hangafter=2 } else if ="\"" then { tab(many(hex_chars)) & optwhite() } else if ="\'" then { tab(many(oct_chars)) & optwhite() } else if =("\\"|"`\\") then tab(many(S.csletters)) | move(1) undelay_newtext(S) (\proc)!args end #line 2207 "l2h.nw" procedure dimen() static decimal_chars initial decimal_chars := &digits ++ '.,' suspend (optwhite(), if any('+-') then (move(1), optwhite()) else "", tab(many(decimal_chars)), optwhite(), (="true", optwhite()) | &null, =("em"|"ex"|"pt"|"pc"|"in"|"bp"|"cm"|"mm"|"dd"|"cc"|"sp"|"mu")) end #line 2217 "l2h.nw" procedure glue() suspend (dimen(), (optwhite(), ="plus", dimen()) | "", (optwhite(), ="minus", dimen()) | "") end #line 2231 "l2h.nw" procedure substitution(tex, html, ignore_template) # ignore mode for now cstab[tex] := Cemit_ig csclosure[tex] := emit_ig_cl(html, \ignore_template | "") end #line 2239 "l2h.nw" record emit_ig_cl(html, template) procedure Cemit_ig(S, cs, cl) emit_text(S, cl.html) if *cl.template > 0 then cs_ignore(S, cs, cl.template) end #line 2249 "l2h.nw" procedure activesubst(char, html, ignore_template) local S # ignore mode for now activetab[char] := Cemit_ig activeclosure[char] := emit_ig_cl(html, \ignore_template | "") S := \dynamic_add_hack | return if upto(S.activechars, char) then return # already active if S.activechars ++:= cset(char) then { before_next_close(S, delete_active_char, [S, char]) } else impossible("ugh") return end procedure delete_active_char(S, char) S.activechars --:= char return end #line 2282 "l2h.nw" procedure envblock(env, left, right, ignore_template) /ignore_template := "" begintab[env] := Cemit_ig begincl[env] := emit_ig_cl(if /right then tag(left) else left, ignore_template) endtab[env] := Cemit endcl[env] := if /right then endtag(left) else right end #line 2291 "l2h.nw" procedure Cemit(S, cs, cl) S.text(S, cl) end #line 2303 "l2h.nw" record blockpair(left, right, ignore) procedure argblock(tex, html, right, ignore) # called as is envblock /ignore := "" cstab[tex] := Cblock csclosure[tex] := if /right then blockpair (tag(html), endtag(html), ignore) else blockpair (html, right, ignore) end #line 2316 "l2h.nw" procedure argblockv(tex, html, right, ignore) argblock(tex, html, right, ignore) cstab[tex] := CblockV end #line 2321 "l2h.nw" procedure Cblock(S, cs, cl, done_ignoring) if /done_ignoring & *cl.ignore > 0 then { cs_ignore(S, cs, cl.ignore, Cblock, [S, cs, cl, 1]) } else if pos(0) then { after_next_newtext(S, do_cs, [S, cs, cl]) } else if match("{") then { S.text(S, cl.left) after_next_open(S, before_next_close, [S, emit_text, [S, cl.right]]) } else { # S.text(S, cl.left || csarg(S) || cl.right) apply_args(S, Cblock_continue, [S, cl], 1) } return end procedure Cblock_continue(S, cl, title) S.text (S, cl.left || title || cl.right) return end #line 2341 "l2h.nw" procedure CblockV(S, cs, cl) S.mode := "V" Cblock(S, cs, cl) return end #line 2353 "l2h.nw" record macro_defn(name, arg_count, body, mode) #line 2357 "l2h.nw" record raw_arg(number) record converted_arg(number, mode) #line 2361 "l2h.nw" procedure expand_macro(S, macro, args) every a := !macro.body do case type(a) of { "string" : emit_text(S, a) "raw_arg" : emit_text(S, args[a.number]) | impossible("missing arg") "converted_arg" : S.text(S, convert(S, "{" || args[a.number] || "}")) } # poptrace() return end #link pushtrace #line 2375 "l2h.nw" procedure do_macro(S, macro, args_seen, current_arg, brace_depth) # invariant : we have an open brace # write(&errout, "scanning args for macro ", macro.name) # write(&errout, "seen ", *args_seen, " want ", macro.arg_count) while *args_seen < macro.arg_count & not pos(0) do { while *args_seen < macro.arg_count & brace_depth = 0 & not pos(0) do { # write(&errout, "seen ", *args_seen, " want ", macro.arg_count, # " current ", image(current_arg), " braces ", brace_depth) tab(many(' \t\n')) case c := move(1) of { "\\" : put(args_seen, "\\" || if pos(0) then "" else if any(S.csletters) then tab(many(S.csletters)) else move(1)) "{" : { current_arg := "" ; brace_depth := 1 } "}" : { error("Insufficient arguments to macro ", macro.name) } default : put(args_seen, c) } } while brace_depth > 0 & not pos(0) do { # write(&errout, "seen ", *args_seen, " want ", macro.arg_count, # " current ", image(current_arg), " braces ", brace_depth) current_arg ||:= tab(upto('\\{}') | 0) case move(1) of { "\\" : current_arg ||:= "\\" || if pos(0) then "" else if any(S.csletters) then tab(many(S.csletters)) else move(1) "{" : { current_arg ||:= "{" ; brace_depth +:= 1 } "}" : { brace_depth -:= 1 if brace_depth > 0 then current_arg ||:= "}" else { put(args_seen, current_arg) current_arg := "" } } } } } # write(&errout, "seen ", *args_seen, " want ", macro.arg_count, # " current ", image(current_arg), " braces ", brace_depth) if *args_seen = macro.arg_count then { # write(&errout, "Arguments for macro ", macro.name, ":") # every write(&errout, "\t", image(!args_seen)) expand_macro(S, macro, args_seen) undelay_newtext(S) } else before_next_newtext(S, do_macro, [S, macro, args_seen, current_arg, brace_depth]) return end #line 2428 "l2h.nw" procedure Cmacro(S, cs, cl) # pushtrace("MACRO") delay_newtext(S) # apply_args(S, closure(expand_macro, [cl]), cl.arg_count) do_macro(S, cl, [], "", 0) return end #line 2439 "l2h.nw" procedure macro(name, arg_count, body, mode) m := macro_defn(name, arg_count, parse_body(body), mode) cstab[name] := Cmacro csclosure[name] := m return end procedure begin_macro(env, arg_count, body, mode) m := macro_defn(env, arg_count, parse_body(body), mode) begintab[env] := Cmacro begincl[env] := m return end procedure parse_body(body) b := [] body ? { put(b, tab(upto('#') | 0)) while ="#" do { put(b, ="#" | (="$", raw_arg(argnum())) | converted_arg(argnum())) | error("malformed macro arg #", tab(0)) put(b, tab(upto('#') | 0)) } } return b end procedure argnum() if any(&digits) then return integer(move(1)) else fail end #line 2472 "l2h.nw" procedure l2h_macro(name, count, body[]) count := integer(count) | return error("must give # of arguments to l2h macro ", name) s := "" every s ||:= " " || (1(b := !body, type(b) == "string")) s := s[2:0] # strip leading space if any return macro(name, count, s) end #line 2482 "l2h.nw" procedure l2h_environment(env, count, body[]) count := integer(count) | return error("must give # of arguments to l2h environment ", env) s := "" every s ||:= " " || (1(b := !body, type(b) == "string")) s := s[2:0] # strip leading space if any return begin_macro(env, count, s) end #line 2497 "l2h.nw" record table_closure(args, amp, open, close) procedure table_env(env, args, amp, open, close) begintab[env] := Ctable begincl[env] := table_closure(args, amp, if /close then tag(\open) | &null else open, if /close then endtag(\open) | &null else close) endtab[env] := Ctable_end endcl[env] := [] end #line 2508 "l2h.nw" procedure Ctable(S, env, cl) local amp ## amp := S.ampersand ## S.ampersand := cl.amp S.text(S, \cl.open) push(endcl[env], amp) cs_ignore(S, env, cl.args) end procedure Ctable_end(S, env, cl) # S.ampersand := pop(cl) S.text(S, \begincl[env].close) end #line 2524 "l2h.nw" procedure Cepsfig(S, cs, cl) apply_args(S, do_epsfig, [S], 1) end procedure do_epsfig(S, arg) local args args := [] arg ? while not pos(0) do { tab(many(' \t\n')) put(args, eqsplit(tab(upto(',') | 0))) } if a := !args & a.name == ("file"|"figure") then emit_text(S, "[PostScript figure " || a.value || "]") else emit_text(S, "[Ill-understood PostScript figure]") end record apair(name, value) procedure eqsplit(s) p := apair() s ? (p.name := tab(upto('=')), ="=", p.value := tab(0)) return p end #line 2552 "l2h.nw" procedure Cincludegraphics(S, cs, cl) local saved_ignore saved_ignore := S.ignoring S.ignoring := 1 do_ignore(S, "[", saved_ignore, apply_args, [S, do_includegraphics, [S], 1]) end procedure do_includegraphics(S, arg) local base, ext if arg ? (base := tab(find(ext := ".ps" | ".eps" | ".epsi")), =ext, pos(0)) then emit_text(S, "[PostScript figure " || arg || "]") else if arg ? (base := tab(find(ext := ".png" | ".gif" | ".jpg")), =ext, pos(0)) then emit_text(S, "") else emit_text(S, "[Ill-understood graphics]") end #line 2574 "l2h.nw" procedure let(lhs, rhs) cstab[lhs] := cstab[rhs] csclosure[lhs] := csclosure[rhs] end procedure let_closure(lhs, cl[]) csclosure[lhs] := if *cl = 1 then cl[1] else cl end procedure letenv(lhs, rhs) begintab[lhs] := begintab[rhs] endtab[lhs] := endtab[rhs] begincl[lhs] := begincl[rhs] endcl[lhs] := endcl[rhs] end #line 2595 "l2h.nw" procedure tag(html) return "<" || html || ">" end procedure endtag(html) return "" end #line 2605 "l2h.nw" procedure Ccomment(S) if *S.comment > 0 then { S.text(S, "") } S.comment := "" return end #line 2621 "l2h.nw" procedure Cparagraph(S) S.text(S, "

    ") end #line 2625 "l2h.nw" procedure Cmath(S) #line 915 "l2h.nw" push(S.closes, []) # fresh set of closing tasks while c := get(S.open) do c.proc!c.args #line 2627 "l2h.nw" S.text(S, "") end procedure Cmath_end(S) S.text(S, "") #line 919 "l2h.nw" while c := get(S.closes[1]) do c.proc!c.args pop(S.closes) #line 2633 "l2h.nw" end #line 2635 "l2h.nw" procedure Cdisplaymath(S) #line 915 "l2h.nw" push(S.closes, []) # fresh set of closing tasks while c := get(S.open) do c.proc!c.args #line 2637 "l2h.nw" S.text(S, "

    ") end procedure Cdisplaymath_end(S) S.text(S, "
    ") #line 919 "l2h.nw" while c := get(S.closes[1]) do c.proc!c.args pop(S.closes) #line 2643 "l2h.nw" end #line 2645 "l2h.nw" procedure Cmakeatletter(S) S.csletters ++:= '@' end procedure Cmakeatother(S) S.csletters --:= '@' end #line 2655 "l2h.nw" procedure Ckill(S, cs, cl) S.the_text := "" end #line 2673 "l2h.nw" global csfunctions #line 2700 "l2h.nw" global dynamic_add_hack procedure parse_dynamic_add(S) if (optwhite(), =("l2h"|"sl2h"), skipwhite(), p := tab(upto(' \t')), #line 2717 "l2h.nw" ((p := \csfunctions[p]) | { dynamic_warn(p); fail }) #line 2703 "l2h.nw" , skipwhite(), any(~'\n')) then { a := [] while (any(~'\n'), l := tab(upto(' \t\n') | 0)) do { put(a, if p === (l2h_macro|l2h_environment) then l else map(l, "#", " ")) skipwhite() } dynamic_add_hack := S p!a dynamic_add_hack := &null return } end #line 2720 "l2h.nw" procedure dynamic_warn(p) static badprocs initial badprocs := set() if not member(badprocs, p) then { write(&errout, "Warning: % l2h ", p, " not recognized -- ignored") insert(badprocs, p) } end #line 2732 "l2h.nw" procedure optwhite() suspend tab(many(' \t')) | "" end #line 2737 "l2h.nw" procedure skipwhite() suspend tab(many(' \t')) end #line 2829 "l2h.nw" global errstatus procedure error(args[]) errstatus := 1 return write!([&errout, (\curfile || ":") | "line ", curline, ": "] ||| args) end #line 2878 "l2h.nw" procedure fatal(L[]) write!(["@fatal l2h "] ||| L) write!([&errout, "noweb error in l2h: "] ||| L) exit(1) end #line 2885 "l2h.nw" procedure rcsinfo () return "$Id: l2h.nw,v 1.24 2008/10/06 01:03:05 nr Exp nr $" || "$Name: v2_12 $" end #line 2745 "l2h.nw" procedure main(args) local line errstatus := 0 every arg := !args do case arg of { "-show-unknowns" : show_unknowns := 1 "-html-quotes" : html_quotes := 1 default : fatal("unknown arg ", image(arg)) } while line := read() do apply(filter, line) warn_unknown(\unknown_set, "control sequences", "\\") warn_unknown(\unknown_envs, "environments", "{", "}") if errstatus > 0 then write("@fatal l2h Error occurred in l2h conversion") exit(errstatus) end procedure apply(pass, line) line ? (="@" & pass(tab(upto(' ')|0), if =" " then tab(0) else &null)) end #line 2771 "l2h.nw" global curfile, curline procedure filter(name, arg) static S, code initial S := converter("V") ### write(" mode ", S.mode) case name of { "begin" : { #line 2817 "l2h.nw" write("@", name, (" " || \arg) | "") #line 2778 "l2h.nw" ; if match("code ", arg) then code := 1} "end" : {if match("docs ", arg) then #line 2795 "l2h.nw" if S.mode ~== "V" then write("@text

    ") #line 2780 "l2h.nw" #line 2817 "l2h.nw" write("@", name, (" " || \arg) | "") #line 2780 "l2h.nw" ; code := &null; S.mode := "V"} "quote" : { outtext("\0" ? convert(S)) } "endquote" : { outtext("\1" ? convert(S)) } "file" : { #line 2817 "l2h.nw" write("@", name, (" " || \arg) | "") #line 2783 "l2h.nw" ; curfile := arg; curline := 1} "line" : { #line 2817 "l2h.nw" write("@", name, (" " || \arg) | "") #line 2784 "l2h.nw" ; curline := integer(arg)} "defn" : { write("@", name, " ", convert_use_or_def(arg)) } "use" : { write("@", name, " ", convert_use_or_def(arg)) } "text" : {if \code then #line 2817 "l2h.nw" write("@", name, (" " || \arg) | "") #line 2787 "l2h.nw" else outtext(arg ? convert(S)) } "nl" : {if \code then #line 2817 "l2h.nw" write("@", name, (" " || \arg) | "") #line 2788 "l2h.nw" else outtext("\n" ? convert(S)); curline +:= 1} "fatal" : { #line 2817 "l2h.nw" write("@", name, (" " || \arg) | "") #line 2789 "l2h.nw" ; exit(1)} default : { #line 2817 "l2h.nw" write("@", name, (" " || \arg) | "") #line 2790 "l2h.nw" } } return end #line 2799 "l2h.nw" procedure convert_use_or_def(s) r := "" s ? { while r ||:= quickconv(tab(find("[["))) do { (r ||:= ="[[") | fatal("impossible missing [[") (r ||:= tab(find("]]")) || tab(many(']'))) | fatal("impossible missing ]] in ", image(s)) } return r || quickconv(tab(0)) } end procedure quickconv(s) static C initial C := converter("H") return 1(("{" || s || "}" ? convert(C)), reset(C)) end #line 2819 "l2h.nw" procedure outtext(s) s ? while not pos(0) do if ="\n" then write("@nl") else if ="\0" then write("@quote") else if ="\1" then write("@endquote") else write("@text ", tab(upto('\n\0\1') | 0)) return end