implement Cook; include "sys.m"; sys: Sys; FD: import Sys; include "draw.m"; draw: Draw; include "bufio.m"; B: Bufio; Iobuf: import B; include "string.m"; S: String; splitl, splitr, splitstrl, drop, take, in, prefix, tolower : import S; include "brutus.m"; Size6, Size8, Size10, Size12, Size16, NSIZE, Roman, Italic, Bold, Type, NFONT, NFONTTAG, Example, Caption, List, Listelem, Label, Labelref, Exercise, Heading, Nofill, Author, Title, Index, Indextopic, DefFont, DefSize, TitleFont, TitleSize, HeadingFont, HeadingSize: import Brutus; # following are needed for types in brutusext.minclude "tk.m"; tk: Tk;include "tkclient.m"; include "brutusext.m"; SGML, Text, Par, Extension, Float, Special, Celem, FLatex, FLatexProc, FLatexBook, FLatexPart, FLatexSlides, FHtml: import Brutusext; include "strinttab.m"; T: StringIntTab; Cook: module{ init: fn(ctxt: ref Draw->Context, args: list of string);}; # keep this sorted by nametagstringtab := array[] of { T->StringInt ("Author", Author), ("Bold.10", Bold*NSIZE + Size10), ("Bold.12", Bold*NSIZE + Size12), ("Bold.16", Bold*NSIZE + Size16), ("Bold.6", Bold*NSIZE + Size6), ("Bold.8", Bold*NSIZE + Size8), ("Caption", Caption), ("Example", Example), ("Exercise", Exercise), ("Extension", Extension), ("Float", Float), ("Heading", Heading), ("Index", Index), ("Index-topic", Indextopic), ("Italic.10", Italic*NSIZE + Size10), ("Italic.12", Italic*NSIZE + Size12), ("Italic.16", Italic*NSIZE + Size16), ("Italic.6", Italic*NSIZE + Size6), ("Italic.8", Italic*NSIZE + Size8), ("Label", Label), ("Label-ref", Labelref), ("List", List), ("List-elem", Listelem), ("No-fill", Nofill), ("Par", Par), ("Roman.10", Roman*NSIZE + Size10), ("Roman.12", Roman*NSIZE + Size12), ("Roman.16", Roman*NSIZE + Size16), ("Roman.6", Roman*NSIZE + Size6), ("Roman.8", Roman*NSIZE + Size8), ("SGML", SGML), ("Title", Title), ("Type.10", Type*NSIZE + Size10), ("Type.12", Type*NSIZE + Size12), ("Type.16", Type*NSIZE + Size16), ("Type.6", Type*NSIZE + Size6), ("Type.8", Type*NSIZE + Size8),}; # This table must be sortedfmtstringtab := array[] of { T->StringInt ("html", FHtml), ("latex", FLatex), ("latexbook", FLatexBook), ("latexpart", FLatexPart), ("latexproc", FLatexProc), ("latexslides", FLatexSlides),}; Transtab: adt{ ch: int; trans: string;}; # Order doesn't matter for these table ltranstab := array[] of { Transtab ('$', "\\textdollar{}"), ('&', "\\&"), ('%', "\\%"), ('#', "\\#"), ('_', "\\textunderscore{}"), ('{', "\\{"), ('}', "\\}"), ('~', "\\textasciitilde{}"), ('^', "\\textasciicircum{}"), ('\\', "\\textbackslash{}"), ('+', "\\textplus{}"), ('=', "\\textequals{}"), ('|', "\\textbar{}"), ('<', "\\textless{}"), ('>', "\\textgreater{}"), (' ', "~"), ('-', "-"), # needs special case ligature treatment ('\t', " "), # needs special case treatment}; htranstab := array[] of { Transtab ('α', "α"), ('Æ', "Æ"), ('Á', "Á"), ('Â', "Â"), ('À', "À"), ('Å', "Å"), ('Ã', "Ã"), ('Ä', "Ä"), ('Ç', "Ç"), ('Ð', "Ð"), ('É', "É"), ('Ê', "Ê"), ('È', "È"), ('Ë', "Ë"), ('Í', "Í"), ('Î', "Î"), ('Ì', "Ì"), ('Ï', "Ï"), ('Ñ', "Ñ"), ('Ó', "Ó"), ('Ô', "Ô"), ('Ò', "Ò"), ('Ø', "Ø"), ('Õ', "Õ"), ('Ö', "Ö"), ('Þ', "Þ"), ('Ú', "Ú"), ('Û', "Û"), ('Ù', "Ù"), ('Ü', "Ü"), ('Ý', "Ý"), ('æ', "&aElig;"), ('á', "á"), ('â', "â"), ('à', "à"), ('α', "α"), ('&', "&"), ('å', "å"), ('ã', "ã"), ('ä', "ä"), ('β', "β"), ('ç', "ç"), ('⋯', "&cdots;"), ('χ', "χ"), ('©', "©"), ('⋱', "&ddots;"), ('δ', "δ"), ('é', "é"), ('ê', "ê"), ('è', "è"), ('—', "&emdash;"), (' ', " "), ('–', "&endash;"), ('ε', "ε"), ('η', "η"), ('ð', "ð"), ('ë', "ë"), ('γ', "γ"), ('>', ">"), ('í', "í"), ('î', "î"), ('ì', "ì"), ('ι', "ι"), ('ï', "ï"), ('κ', "κ"), ('λ', "λ"), ('…', "&ldots;"), ('<', "<"), ('μ', "μ"), (' ', " "), ('ñ', "ñ"), ('ν', "ν"), ('ó', "ó"), ('ô', "ô"), ('ò', "ò"), ('ω', "ω"), ('ο', "ο"), ('ø', "ø"), ('õ', "õ"), ('ö', "ö"), ('φ', "φ"), ('π', "π"), ('ψ', "ψ"), (' ', "&quad;"), ('"', """), ('®', "®"), ('ρ', "ρ"), ('', "­"), ('σ', "σ"), ('ß', "ß"), ('τ', "τ"), ('θ', "θ"), (' ', " "), ('þ', "þ"), ('™', "™"), ('ú', "ú"), ('û', "û"), ('ù', "ù"), ('υ', "υ"), ('ü', "ü"), ('∈', "ϵ"), ('ϕ', "ϕ"), ('ϖ', "ϖ"), ('ϱ', "ϱ"), ('⋮', "&vdots;"), ('ς', "&vsigma;"), ('ϑ', "&vtheta;"), ('ξ', "ξ"), ('ý', "ý"), ('ÿ', "ÿ"), ('ζ', "ζ"), ('−', "-"),}; # For speedy lookups of ascii char translation, use asciitrans.# It should be initialized by ascii elements from one of above tablesasciitrans := array[128] of string; stderr: ref FD;infilename := "";outfilename := "";linenum := 0;fin : ref Iobuf = nil;fout : ref Iobuf = nil;debug := 0;fmt := FLatex; init(nil: ref Draw->Context, argv: list of string){ sys = load Sys Sys->PATH; S = load String String->PATH; B = load Bufio Bufio->PATH; draw = load Draw Draw->PATH; tk = load Tk Tk->PATH; T = load StringIntTab StringIntTab->PATH; stderr = sys->fildes(2); for(argv = tl argv; argv != nil; ) { s := hd argv; tlargv := tl argv; case s { "-f" => if(tlargv == nil) usage(); fnd: int; (fnd, fmt) = T->lookup(fmtstringtab, hd(tlargv)); if(!fnd) { sys->fprint(stderr, "unknown format: %s\n", hd(tlargv)); exit; } argv = tlargv; "-o" => if(tlargv == nil) usage(); outfilename = hd(tlargv); argv = tlargv; "-d" => debug = 1; "-dd" => debug = 2; * => if(tlargv == nil) infilename = s; else usage(); } argv = tl argv; } if(infilename == "") { fin = B->fopen(sys->fildes(0), sys->OREAD); infilename = "<stdin>"; } else fin = B->open(infilename, sys->OREAD); if(fin == nil) { sys->fprint(stderr, "cook: error opening %s: %r\n", infilename); exit; } if(outfilename == "") { fout = B->fopen(sys->fildes(1), sys->OWRITE); outfilename = "<stdout>"; } else fout = B->create(outfilename, sys->OWRITE, 8r664); if(fout == nil) { sys->fprint(stderr, "cook: error creating %s: %r\n", outfilename); exit; } line0 := fin.gets('\n'); if(line0 != "<SGML>\n") { parse_err("not an SGML file\n"); exit; } linenum = 1; e := parse(SGML); findpars(e, 1, nil); e = delemptystrs(e); (e, nil) = canonfonts(e, DefFont*NSIZE+DefSize, DefFont*NSIZE+DefSize); mergeadjs(e); findfloats(e); cleanexts(e); cleanpars(e); if(debug) { fout.puts("After Initial transformations:\n"); printelem(e, "", 1); fout.flush(); } case fmt { FLatex or FLatexProc or FLatexBook or FLatexPart or FLatexSlides => latexconv(e); FHtml => htmlconv(e); } fin.close(); fout.close();} usage(){ sys->fprint(stderr, "Usage: cook [-f (latex|html)] [-o outfile] [infile]\n"); exit;} parse_err(msg: string){ sys->fprint(stderr, "%s:%d: %s\n", infilename, linenum, msg);} # Parse into elements.# Assumes tags are balanced.# String elements are split so that there is never an internal newline.parse(id: int) : ref Celem{ els : ref Celem = nil; elstail : ref Celem = nil; for(;;) { c := fin.getc(); if(c == Bufio->EOF) { if(id == SGML) break; else { parse_err(sys->sprint("EOF while parsing %s", tagname(id))); return nil; } } if(c == '<') { tag := ""; start := 1; i := 0; for(;;) { c = fin.getc(); if(c == Bufio->EOF) { parse_err("EOF in middle of tag"); return nil; } if(c == '\n') { linenum++; parse_err("newline in middle of tag"); break; } if(c == '>') break; if(i == 0 && c == '/') start = 0; else tag[i++] = c; } (fnd, tid) := T->lookup(tagstringtab, tag); if(!fnd) { if(prefix("Extension ", tag)) { el := ref Celem(Extension, tag[10:], nil, nil, nil, nil); if(els == nil) { els = el; elstail = el; } else { el.prev = elstail; elstail.next = el; elstail = el; } } else parse_err(sys->sprint("unknown tag <%s>\n", tag)); continue; } if(start) { el := parse(tid); if(el == nil) return nil; if(els == nil) { els = el; elstail = el; } else { el.prev = elstail; elstail.next = el; elstail = el; } } else { if(tid != id) { parse_err(sys->sprint("<%s> ended by </%s>", tagname(id), tag)); continue; } break; } } else { s := ""; i := 0; for(;;) { if(c == Bufio->EOF) break; if(c == '<') { fin.ungetc(); break; } if(c == ';' && i >=3 && s[i-1] == 't' && s[i-2] == 'l' && s[i-3] == '&') { i -= 2; s[i-1] = '<'; s = s[0:i]; } else s[i++] = c; if(c == '\n') { linenum++; break; } else c = fin.getc(); } if(s != "") { el := ref Celem(Text, s, nil, nil, nil, nil); if(els == nil) { els = el; elstail = el; } else { el.prev = elstail; elstail.next = el; elstail = el; } } } } ans := ref Celem(id, "", els, nil, nil, nil); if(els != nil) els.parent = ans; return ans;} # Modify tree e so that blank lines become Par elements.# Only do it if parize is set, and unset parize when descending into TExample's.# Pass in most recent TString or TPar element, and return updated most-recent-TString/TPar.# This function may set some TString strings to ""findpars(e: ref Celem, parize: int, prevspe: ref Celem) : ref Celem{ while(e != nil) { prevnl := 0; prevpar := 0; if(prevspe != nil) { if(prevspe.tag == Text && len prevspe.s != 0 && prevspe.s[(len prevspe.s)-1] == '\n') prevnl = 1; else if(prevspe.tag == Par) prevpar = 1; } if(e.tag == Text) { if(parize && (prevnl || prevpar) && e.s[0] == '\n') { if(prevnl) prevspe.s = prevspe.s[0 : (len prevspe.s)-1]; e.tag = Par; e.s = nil; } prevspe = e; }Lines 1–500 of 1924. Load more
implement Cook; include "sys.m"; sys: Sys; FD: import Sys; include "draw.m"; draw: Draw; include "bufio.m"; B: Bufio; Iobuf: import B; include "string.m"; S: String; splitl, splitr, splitstrl, drop, take, in, prefix, tolower : import S; include "brutus.m"; Size6, Size8, Size10, Size12, Size16, NSIZE, Roman, Italic, Bold, Type, NFONT, NFONTTAG, Example, Caption, List, Listelem, Label, Labelref, Exercise, Heading, Nofill, Author, Title, Index, Indextopic, DefFont, DefSize, TitleFont, TitleSize, HeadingFont, HeadingSize: import Brutus; # following are needed for types in brutusext.m include "tk.m"; tk: Tk; include "tkclient.m"; include "brutusext.m"; SGML, Text, Par, Extension, Float, Special, Celem, FLatex, FLatexProc, FLatexBook, FLatexPart, FLatexSlides, FHtml: import Brutusext; include "strinttab.m"; T: StringIntTab; Cook: module { init: fn(ctxt: ref Draw->Context, args: list of string); }; # keep this sorted by name tagstringtab := array[] of { T->StringInt ("Author", Author), ("Bold.10", Bold*NSIZE + Size10), ("Bold.12", Bold*NSIZE + Size12), ("Bold.16", Bold*NSIZE + Size16), ("Bold.6", Bold*NSIZE + Size6), ("Bold.8", Bold*NSIZE + Size8), ("Caption", Caption), ("Example", Example), ("Exercise", Exercise), ("Extension", Extension), ("Float", Float), ("Heading", Heading), ("Index", Index), ("Index-topic", Indextopic), ("Italic.10", Italic*NSIZE + Size10), ("Italic.12", Italic*NSIZE + Size12), ("Italic.16", Italic*NSIZE + Size16), ("Italic.6", Italic*NSIZE + Size6), ("Italic.8", Italic*NSIZE + Size8), ("Label", Label), ("Label-ref", Labelref), ("List", List), ("List-elem", Listelem), ("No-fill", Nofill), ("Par", Par), ("Roman.10", Roman*NSIZE + Size10), ("Roman.12", Roman*NSIZE + Size12), ("Roman.16", Roman*NSIZE + Size16), ("Roman.6", Roman*NSIZE + Size6), ("Roman.8", Roman*NSIZE + Size8), ("SGML", SGML), ("Title", Title), ("Type.10", Type*NSIZE + Size10), ("Type.12", Type*NSIZE + Size12), ("Type.16", Type*NSIZE + Size16), ("Type.6", Type*NSIZE + Size6), ("Type.8", Type*NSIZE + Size8), }; # This table must be sorted fmtstringtab := array[] of { T->StringInt ("html", FHtml), ("latex", FLatex), ("latexbook", FLatexBook), ("latexpart", FLatexPart), ("latexproc", FLatexProc), ("latexslides", FLatexSlides), }; Transtab: adt { ch: int; trans: string; }; # Order doesn't matter for these table ltranstab := array[] of { Transtab ('$', "\\textdollar{}"), ('&', "\\&"), ('%', "\\%"), ('#', "\\#"), ('_', "\\textunderscore{}"), ('{', "\\{"), ('}', "\\}"), ('~', "\\textasciitilde{}"), ('^', "\\textasciicircum{}"), ('\\', "\\textbackslash{}"), ('+', "\\textplus{}"), ('=', "\\textequals{}"), ('|', "\\textbar{}"), ('<', "\\textless{}"), ('>', "\\textgreater{}"), (' ', "~"), ('-', "-"), # needs special case ligature treatment ('\t', " "), # needs special case treatment }; htranstab := array[] of { Transtab ('α', "α"), ('Æ', "Æ"), ('Á', "Á"), ('Â', "Â"), ('À', "À"), ('Å', "Å"), ('Ã', "Ã"), ('Ä', "Ä"), ('Ç', "Ç"), ('Ð', "Ð"), ('É', "É"), ('Ê', "Ê"), ('È', "È"), ('Ë', "Ë"), ('Í', "Í"), ('Î', "Î"), ('Ì', "Ì"), ('Ï', "Ï"), ('Ñ', "Ñ"), ('Ó', "Ó"), ('Ô', "Ô"), ('Ò', "Ò"), ('Ø', "Ø"), ('Õ', "Õ"), ('Ö', "Ö"), ('Þ', "Þ"), ('Ú', "Ú"), ('Û', "Û"), ('Ù', "Ù"), ('Ü', "Ü"), ('Ý', "Ý"), ('æ', "&aElig;"), ('á', "á"), ('â', "â"), ('à', "à"), ('α', "α"), ('&', "&"), ('å', "å"), ('ã', "ã"), ('ä', "ä"), ('β', "β"), ('ç', "ç"), ('⋯', "&cdots;"), ('χ', "χ"), ('©', "©"), ('⋱', "&ddots;"), ('δ', "δ"), ('é', "é"), ('ê', "ê"), ('è', "è"), ('—', "&emdash;"), (' ', " "), ('–', "&endash;"), ('ε', "ε"), ('η', "η"), ('ð', "ð"), ('ë', "ë"), ('γ', "γ"), ('>', ">"), ('í', "í"), ('î', "î"), ('ì', "ì"), ('ι', "ι"), ('ï', "ï"), ('κ', "κ"), ('λ', "λ"), ('…', "&ldots;"), ('<', "<"), ('μ', "μ"), (' ', " "), ('ñ', "ñ"), ('ν', "ν"), ('ó', "ó"), ('ô', "ô"), ('ò', "ò"), ('ω', "ω"), ('ο', "ο"), ('ø', "ø"), ('õ', "õ"), ('ö', "ö"), ('φ', "φ"), ('π', "π"), ('ψ', "ψ"), (' ', "&quad;"), ('"', """), ('®', "®"), ('ρ', "ρ"), ('', "­"), ('σ', "σ"), ('ß', "ß"), ('τ', "τ"), ('θ', "θ"), (' ', " "), ('þ', "þ"), ('™', "™"), ('ú', "ú"), ('û', "û"), ('ù', "ù"), ('υ', "υ"), ('ü', "ü"), ('∈', "ϵ"), ('ϕ', "ϕ"), ('ϖ', "ϖ"), ('ϱ', "ϱ"), ('⋮', "&vdots;"), ('ς', "&vsigma;"), ('ϑ', "&vtheta;"), ('ξ', "ξ"), ('ý', "ý"), ('ÿ', "ÿ"), ('ζ', "ζ"), ('−', "-"), }; # For speedy lookups of ascii char translation, use asciitrans. # It should be initialized by ascii elements from one of above tables asciitrans := array[128] of string; stderr: ref FD; infilename := ""; outfilename := ""; linenum := 0; fin : ref Iobuf = nil; fout : ref Iobuf = nil; debug := 0; fmt := FLatex; init(nil: ref Draw->Context, argv: list of string) { sys = load Sys Sys->PATH; S = load String String->PATH; B = load Bufio Bufio->PATH; draw = load Draw Draw->PATH; tk = load Tk Tk->PATH; T = load StringIntTab StringIntTab->PATH; stderr = sys->fildes(2); for(argv = tl argv; argv != nil; ) { s := hd argv; tlargv := tl argv; case s { "-f" => if(tlargv == nil) usage(); fnd: int; (fnd, fmt) = T->lookup(fmtstringtab, hd(tlargv)); if(!fnd) { sys->fprint(stderr, "unknown format: %s\n", hd(tlargv)); exit; } argv = tlargv; "-o" => if(tlargv == nil) usage(); outfilename = hd(tlargv); argv = tlargv; "-d" => debug = 1; "-dd" => debug = 2; * => if(tlargv == nil) infilename = s; else usage(); } argv = tl argv; } if(infilename == "") { fin = B->fopen(sys->fildes(0), sys->OREAD); infilename = "<stdin>"; } else fin = B->open(infilename, sys->OREAD); if(fin == nil) { sys->fprint(stderr, "cook: error opening %s: %r\n", infilename); exit; } if(outfilename == "") { fout = B->fopen(sys->fildes(1), sys->OWRITE); outfilename = "<stdout>"; } else fout = B->create(outfilename, sys->OWRITE, 8r664); if(fout == nil) { sys->fprint(stderr, "cook: error creating %s: %r\n", outfilename); exit; } line0 := fin.gets('\n'); if(line0 != "<SGML>\n") { parse_err("not an SGML file\n"); exit; } linenum = 1; e := parse(SGML); findpars(e, 1, nil); e = delemptystrs(e); (e, nil) = canonfonts(e, DefFont*NSIZE+DefSize, DefFont*NSIZE+DefSize); mergeadjs(e); findfloats(e); cleanexts(e); cleanpars(e); if(debug) { fout.puts("After Initial transformations:\n"); printelem(e, "", 1); fout.flush(); } case fmt { FLatex or FLatexProc or FLatexBook or FLatexPart or FLatexSlides => latexconv(e); FHtml => htmlconv(e); } fin.close(); fout.close(); } usage() { sys->fprint(stderr, "Usage: cook [-f (latex|html)] [-o outfile] [infile]\n"); exit; } parse_err(msg: string) { sys->fprint(stderr, "%s:%d: %s\n", infilename, linenum, msg); } # Parse into elements. # Assumes tags are balanced. # String elements are split so that there is never an internal newline. parse(id: int) : ref Celem { els : ref Celem = nil; elstail : ref Celem = nil; for(;;) { c := fin.getc(); if(c == Bufio->EOF) { if(id == SGML) break; else { parse_err(sys->sprint("EOF while parsing %s", tagname(id))); return nil; } } if(c == '<') { tag := ""; start := 1; i := 0; for(;;) { c = fin.getc(); if(c == Bufio->EOF) { parse_err("EOF in middle of tag"); return nil; } if(c == '\n') { linenum++; parse_err("newline in middle of tag"); break; } if(c == '>') break; if(i == 0 && c == '/') start = 0; else tag[i++] = c; } (fnd, tid) := T->lookup(tagstringtab, tag); if(!fnd) { if(prefix("Extension ", tag)) { el := ref Celem(Extension, tag[10:], nil, nil, nil, nil); if(els == nil) { els = el; elstail = el; } else { el.prev = elstail; elstail.next = el; elstail = el; } } else parse_err(sys->sprint("unknown tag <%s>\n", tag)); continue; } if(start) { el := parse(tid); if(el == nil) return nil; if(els == nil) { els = el; elstail = el; } else { el.prev = elstail; elstail.next = el; elstail = el; } } else { if(tid != id) { parse_err(sys->sprint("<%s> ended by </%s>", tagname(id), tag)); continue; } break; } } else { s := ""; i := 0; for(;;) { if(c == Bufio->EOF) break; if(c == '<') { fin.ungetc(); break; } if(c == ';' && i >=3 && s[i-1] == 't' && s[i-2] == 'l' && s[i-3] == '&') { i -= 2; s[i-1] = '<'; s = s[0:i]; } else s[i++] = c; if(c == '\n') { linenum++; break; } else c = fin.getc(); } if(s != "") { el := ref Celem(Text, s, nil, nil, nil, nil); if(els == nil) { els = el; elstail = el; } else { el.prev = elstail; elstail.next = el; elstail = el; } } } } ans := ref Celem(id, "", els, nil, nil, nil); if(els != nil) els.parent = ans; return ans; } # Modify tree e so that blank lines become Par elements. # Only do it if parize is set, and unset parize when descending into TExample's. # Pass in most recent TString or TPar element, and return updated most-recent-TString/TPar. # This function may set some TString strings to "" findpars(e: ref Celem, parize: int, prevspe: ref Celem) : ref Celem { while(e != nil) { prevnl := 0; prevpar := 0; if(prevspe != nil) { if(prevspe.tag == Text && len prevspe.s != 0 && prevspe.s[(len prevspe.s)-1] == '\n') prevnl = 1; else if(prevspe.tag == Par) prevpar = 1; } if(e.tag == Text) { if(parize && (prevnl || prevpar) && e.s[0] == '\n') { if(prevnl) prevspe.s = prevspe.s[0 : (len prevspe.s)-1]; e.tag = Par; e.s = nil; } prevspe = e; }