implement Man2html; include "sys.m"; stderr: ref Sys->FD; sys: Sys; print, fprint, sprint: import sys; include "bufio.m"; include "draw.m"; include "daytime.m"; dt: Daytime; include "string.m"; str: String; Man2html: module{ init: fn(ctxt: ref Draw->Context, args: list of string);}; Runeself: con 16r80;false, true: con iota; Troffspec: adt { name: string; value: string;}; tspec := array [] of { Troffspec ("ff", "ff"), ("fi", "fi"), ("fl", "fl"), ("Fi", "ffi"), ("ru", "_"), ("em", "­"), ("14", "¼"), ("12", "½"), ("co", "©"), ("de", "°"), ("dg", "¡"), ("fm", "´"), ("rg", "®"),# ("bu", "*"), ("bu", "•"), ("sq", "¤"), ("hy", "-"), ("pl", "+"), ("mi", "-"), ("mu", "×"), ("di", "÷"), ("eq", "="), ("==", "=="), (">=", ">="), ("<=", "<="), ("!=", "!="), ("+-", "±"), ("no", "¬"), ("sl", "/"), ("ap", "&"), ("~=", "~="), ("pt", "oc"), ("gr", "GRAD"), ("->", "->"), ("<-", "<-"), ("ua", "^"), ("da", "v"), ("is", "Integral"), ("pd", "DIV"), ("if", "oo"), ("sr", "-/"), ("sb", "(~"), ("sp", "~)"), ("cu", "U"), ("ca", "(^)"), ("ib", "(="), ("ip", "=)"), ("mo", "C"), ("es", "Ø"), ("aa", "´"), ("ga", "`"), ("ci", "O"), ("L1", "Lucent"), ("sc", "§"), ("dd", "++"), ("lh", "<="), ("rh", "=>"), ("lt", "("), ("rt", ")"), ("lc", "|"), ("rc", "|"), ("lb", "("), ("rb", ")"), ("lf", "|"), ("rf", "|"), ("lk", "|"), ("rk", "|"), ("bv", "|"), ("ts", "s"), ("br", "|"), ("or", "|"), ("ul", "_"), ("rn", " "), ("*p", "PI"), ("**", "*"),}; Entity: adt { name: string; value: int; }; Entities: array of Entity; Entities = array[] of { Entity( "¡", '¡' ), Entity( "¢", '¢' ), Entity( "£", '£' ), Entity( "¤", '¤' ), Entity( "¥", '¥' ), Entity( "¦", '¦' ), Entity( "§", '§' ), Entity( "¨", '¨' ), Entity( "©", '©' ), Entity( "ª", 'ª' ), Entity( "«", '«' ), Entity( "¬", '¬' ), Entity( "­", '' ), Entity( "®", '®' ), Entity( "¯", '¯' ), Entity( "°", '°' ), Entity( "±", '±' ), Entity( "²", '²' ), Entity( "³", '³' ), Entity( "´", '´' ), Entity( "µ", 'µ' ), Entity( "¶", '¶' ), Entity( "·", '·' ), Entity( "¸", '¸' ), Entity( "¹", '¹' ), Entity( "º", 'º' ), Entity( "»", '»' ), Entity( "¼", '¼' ), Entity( "½", '½' ), Entity( "¾", '¾' ), Entity( "¿", '¿' ), Entity( "À", 'À' ), Entity( "Á", 'Á' ), Entity( "Â", 'Â' ), Entity( "Ã", 'Ã' ), Entity( "Ä", 'Ä' ), Entity( "Å", 'Å' ), Entity( "Æ", 'Æ' ), Entity( "Ç", 'Ç' ), Entity( "È", 'È' ), Entity( "É", 'É' ), Entity( "Ê", 'Ê' ), Entity( "Ë", 'Ë' ), Entity( "Ì", 'Ì' ), Entity( "Í", 'Í' ), Entity( "Î", 'Î' ), Entity( "Ï", 'Ï' ), Entity( "Ð", 'Ð' ), Entity( "Ñ", 'Ñ' ), Entity( "Ò", 'Ò' ), Entity( "Ó", 'Ó' ), Entity( "Ô", 'Ô' ), Entity( "Õ", 'Õ' ), Entity( "Ö", 'Ö' ), Entity( "&215;", '×' ), Entity( "Ø", 'Ø' ), Entity( "Ù", 'Ù' ), Entity( "Ú", 'Ú' ), Entity( "Û", 'Û' ), Entity( "Ü", 'Ü' ), Entity( "Ý", 'Ý' ), Entity( "Þ", 'Þ' ), Entity( "ß", 'ß' ), Entity( "à", 'à' ), Entity( "á", 'á' ), Entity( "â", 'â' ), Entity( "ã", 'ã' ), Entity( "ä", 'ä' ), Entity( "å", 'å' ), Entity( "æ", 'æ' ), Entity( "ç", 'ç' ), Entity( "è", 'è' ), Entity( "é", 'é' ), Entity( "ê", 'ê' ), Entity( "ë", 'ë' ), Entity( "ì", 'ì' ), Entity( "í", 'í' ), Entity( "î", 'î' ), Entity( "ï", 'ï' ), Entity( "ð", 'ð' ), Entity( "ñ", 'ñ' ), Entity( "ò", 'ò' ), Entity( "ó", 'ó' ), Entity( "ô", 'ô' ), Entity( "õ", 'õ' ), Entity( "ö", 'ö' ), Entity( "&247;", '÷' ), Entity( "ø", 'ø' ), Entity( "ù", 'ù' ), Entity( "ú", 'ú' ), Entity( "û", 'û' ), Entity( "ü", 'ü' ), Entity( "ý", 'ý' ), Entity( "þ", 'þ' ), Entity( "ÿ", 'ÿ' ), # ÿ Entity( "&#SPACE;", ' ' ), Entity( "&#RS;", '\n' ), Entity( "&#RE;", '\r' ), Entity( """, '"' ), Entity( "&", '&' ), Entity( "<", '<' ), Entity( ">", '>' ), Entity( "CAP-DELTA", 'Δ' ), Entity( "ALPHA", 'α' ), Entity( "BETA", 'β' ), Entity( "DELTA", 'δ' ), Entity( "EPSILON", 'ε' ), Entity( "THETA", 'θ' ), Entity( "MU", 'μ' ), Entity( "PI", 'π' ), Entity( "TAU", 'τ' ), Entity( "CHI", 'χ' ), Entity( "<-", '←' ), Entity( "^", '↑' ), Entity( "->", '→' ), Entity( "v", '↓' ), Entity( "!=", '≠' ), Entity( "<=", '≤' ), Entity( nil, 0 ),}; Hit: adt { glob: string; chap: string; mtype: string; page: string;}; Lnone, Lordered, Lunordered, Ldef, Lother: con iota; # list types Chaps: adt { name: string; primary: int;}; Types: adt { name: string; desc: string;}; # having two separate flags here allows for inclusion of old-style formatted pages# under a new-style three-level treeOldstyle: adt { names: int; # two-level directory tree? fmt: int; # old internal formats: e.g., "B" font means "L"; name in .TH in all caps}; Href: adt { title: string; chap: string; mtype: string; man: string;}; # per-thread global dataGlobal: adt { bufio: Bufio; bin: ref Bufio->Iobuf; bout: ref Bufio->Iobuf; topname: string; # name of the top level categories in the manual chaps: array of Chaps; # names of top-level partitions of this manual types: array of Types; # names of second-level partitions oldstyle: Oldstyle; mantitle: string; mandir: string; thisone: Hit; # man page we're displaying mtime: int; # last modification time of thisone href: Href; # hrefs of components of this man page hits: array of Hit; nhits: int; list_type: int; pm: string; # proprietary marking def_goobie: string; # deferred goobie sop: int; # output at start of paragraph? sol: int; # input at start of line? broken: int; # output at a break? fill: int; # in fill mode? pre: int; # in PRE block? example: int; # an example active? ipd: int; # emit inter-paragraph distance? indents: int; hangingdt: int; curfont: string; # current font prevfont: string; # previous font lastc: int; # previous char from input scanner def_sm: int; # amount of deferred "make smaller" request mk_href_chap: fn(g: self ref Global, chap: string); mk_href_man: fn(g: self ref Global, man: string, oldstyle: int); mk_href_mtype: fn(g: self ref Global, chap, mtype: string); dobreak: fn(g: self ref Global); print: fn(g: self ref Global, s: string); softbr: fn(g: self ref Global): string; softp: fn(g: self ref Global): string;}; usage(){ sys->fprint(stderr, "Usage: man2html file [section]\n"); raise "fail:usage";} init(nil: ref Draw->Context, args: list of string){ sys = load Sys Sys->PATH; stderr = sys->fildes(2); str = load String String->PATH; dt = load Daytime Daytime->PATH; g := Global_init(); if(args != nil) args = tl args; if(args == nil) usage(); page := hd args; args = tl args; section := "1"; if(args != nil) section = hd args; hit := Hit ("", "man", section, page); domanpage(g, hit); g.bufio->g.bout.flush();} # remove markup from a string# doesn't handle nested/quoted delimitersdemark(s: string): string{ t: string; clean := true; for (i := 0; i < len s; i++) { case s[i] { '<' => clean = false; '>' => clean = true; * => if (clean) t[len t] = s[i]; } } return t;} ## Convert an individual man page to HTML and output.#domanpage(g: ref Global, man: Hit){ file := man.page; g.bin = g.bufio->open(file, Bufio->OREAD); g.bout = g.bufio->fopen(sys->fildes(1), Bufio->OWRITE); if (g.bin == nil) { fprint(stderr, "Cannot open %s: %r\n", file); return; } (err, info) := sys->fstat(g.bin.fd); if (! err) { g.mtime = info.mtime; } g.thisone = man; while ((p := getnext(g)) != nil) { c := p[0]; if (c == '.' && g.sol) { if (g.pre) { g.print("</PRE>"); g.pre = false; } dogoobie(g, false); dohangingdt(g); } else if (g.def_goobie != nil || g.def_sm != 0) { g.bufio->g.bin.ungetc(); dogoobie(g, true); } else if (c == '\n') { g.print(p); dohangingdt(g); } else g.print(p); } if (g.pm != nil) { g.print("<BR><BR><BR><FONT SIZE=-2><CENTER>\n"); g.print(g.pm); g.print("<BR></CENTER></FONT>\n"); } closeall(g, 0); rev(g, g.bin);} dogoobie(g: ref Global, deferred: int){ # read line, translate special chars line: string; while ((token := getnext(g)) != "\n") { if (token == nil) return; line += token; } # parse into arguments argl, rargl: list of string; # create reversed version, then invert while ((line = str->drop(line, " \t")) != nil) if (line[0] == '"') { (token, line) = split(line[1:], '"'); rargl = token :: rargl; } else { (token, line) = str->splitl(line, " \t"); rargl = token :: rargl; } if (rargl == nil && !deferred) return; for ( ; rargl != nil; rargl = tl rargl) argl = hd rargl :: argl; def_sm := g.def_sm; if (deferred && def_sm > 0) { g.print(sprint("<FONT SIZE=-%d>", def_sm)); if (g.def_goobie == nil) argl = "dS" :: argl; # dS is our own local creation } subgoobie(g, argl); if (deferred && def_sm > 0) { g.def_sm = 0; g.print("</FONT>"); }} subgoobie(g: ref Global, argl: list of string){ if (g.def_goobie != nil) { argl = g.def_goobie :: argl; g.def_goobie = nil; if (tl argl == nil) return; } # the command part is at most two characters, but may be concatenated with the first arg cmd := hd argl; argl = tl argl; if (len cmd > 2) { cmd = cmd[0:2]; argl = cmd[2:] :: argl; } case cmd { "B" or "I" or "L" or "R" => font(g, cmd, argl); # "R" macro implicitly generated by deferred R* macros "BI" or "BL" or "BR" or "IB" or "IL" or "LB" or "LI" or "RB" or "RI" or "RL" => altfont(g, cmd[0:1], cmd[1:2], argl, true); "IR" or "LR" => anchor(g, cmd[0:1], cmd[1:2], argl); # includes man page refs ("IR" is old style, "LR" is new) "dS" => printargs(g, argl); g.print("\n"); "1C" or "2C" or "DT" or "TF" => # ignore these return; "P" or "PP" or "LP" => g_PP(g); "EE" => g_EE(g); "EX" => g_EX(g); "HP" => g_HP_TP(g, 1); "IP" => g_IP(g, argl); "PD" => g_PD(g, argl); "PM" => g_PM(g, argl); "RE" => g_RE(g);Lines 1–500 of 1328. Load more
implement Man2html; include "sys.m"; stderr: ref Sys->FD; sys: Sys; print, fprint, sprint: import sys; include "bufio.m"; include "draw.m"; include "daytime.m"; dt: Daytime; include "string.m"; str: String; Man2html: module { init: fn(ctxt: ref Draw->Context, args: list of string); }; Runeself: con 16r80; false, true: con iota; Troffspec: adt { name: string; value: string; }; tspec := array [] of { Troffspec ("ff", "ff"), ("fi", "fi"), ("fl", "fl"), ("Fi", "ffi"), ("ru", "_"), ("em", "­"), ("14", "¼"), ("12", "½"), ("co", "©"), ("de", "°"), ("dg", "¡"), ("fm", "´"), ("rg", "®"), # ("bu", "*"), ("bu", "•"), ("sq", "¤"), ("hy", "-"), ("pl", "+"), ("mi", "-"), ("mu", "×"), ("di", "÷"), ("eq", "="), ("==", "=="), (">=", ">="), ("<=", "<="), ("!=", "!="), ("+-", "±"), ("no", "¬"), ("sl", "/"), ("ap", "&"), ("~=", "~="), ("pt", "oc"), ("gr", "GRAD"), ("->", "->"), ("<-", "<-"), ("ua", "^"), ("da", "v"), ("is", "Integral"), ("pd", "DIV"), ("if", "oo"), ("sr", "-/"), ("sb", "(~"), ("sp", "~)"), ("cu", "U"), ("ca", "(^)"), ("ib", "(="), ("ip", "=)"), ("mo", "C"), ("es", "Ø"), ("aa", "´"), ("ga", "`"), ("ci", "O"), ("L1", "Lucent"), ("sc", "§"), ("dd", "++"), ("lh", "<="), ("rh", "=>"), ("lt", "("), ("rt", ")"), ("lc", "|"), ("rc", "|"), ("lb", "("), ("rb", ")"), ("lf", "|"), ("rf", "|"), ("lk", "|"), ("rk", "|"), ("bv", "|"), ("ts", "s"), ("br", "|"), ("or", "|"), ("ul", "_"), ("rn", " "), ("*p", "PI"), ("**", "*"), }; Entity: adt { name: string; value: int; }; Entities: array of Entity; Entities = array[] of { Entity( "¡", '¡' ), Entity( "¢", '¢' ), Entity( "£", '£' ), Entity( "¤", '¤' ), Entity( "¥", '¥' ), Entity( "¦", '¦' ), Entity( "§", '§' ), Entity( "¨", '¨' ), Entity( "©", '©' ), Entity( "ª", 'ª' ), Entity( "«", '«' ), Entity( "¬", '¬' ), Entity( "­", '' ), Entity( "®", '®' ), Entity( "¯", '¯' ), Entity( "°", '°' ), Entity( "±", '±' ), Entity( "²", '²' ), Entity( "³", '³' ), Entity( "´", '´' ), Entity( "µ", 'µ' ), Entity( "¶", '¶' ), Entity( "·", '·' ), Entity( "¸", '¸' ), Entity( "¹", '¹' ), Entity( "º", 'º' ), Entity( "»", '»' ), Entity( "¼", '¼' ), Entity( "½", '½' ), Entity( "¾", '¾' ), Entity( "¿", '¿' ), Entity( "À", 'À' ), Entity( "Á", 'Á' ), Entity( "Â", 'Â' ), Entity( "Ã", 'Ã' ), Entity( "Ä", 'Ä' ), Entity( "Å", 'Å' ), Entity( "Æ", 'Æ' ), Entity( "Ç", 'Ç' ), Entity( "È", 'È' ), Entity( "É", 'É' ), Entity( "Ê", 'Ê' ), Entity( "Ë", 'Ë' ), Entity( "Ì", 'Ì' ), Entity( "Í", 'Í' ), Entity( "Î", 'Î' ), Entity( "Ï", 'Ï' ), Entity( "Ð", 'Ð' ), Entity( "Ñ", 'Ñ' ), Entity( "Ò", 'Ò' ), Entity( "Ó", 'Ó' ), Entity( "Ô", 'Ô' ), Entity( "Õ", 'Õ' ), Entity( "Ö", 'Ö' ), Entity( "&215;", '×' ), Entity( "Ø", 'Ø' ), Entity( "Ù", 'Ù' ), Entity( "Ú", 'Ú' ), Entity( "Û", 'Û' ), Entity( "Ü", 'Ü' ), Entity( "Ý", 'Ý' ), Entity( "Þ", 'Þ' ), Entity( "ß", 'ß' ), Entity( "à", 'à' ), Entity( "á", 'á' ), Entity( "â", 'â' ), Entity( "ã", 'ã' ), Entity( "ä", 'ä' ), Entity( "å", 'å' ), Entity( "æ", 'æ' ), Entity( "ç", 'ç' ), Entity( "è", 'è' ), Entity( "é", 'é' ), Entity( "ê", 'ê' ), Entity( "ë", 'ë' ), Entity( "ì", 'ì' ), Entity( "í", 'í' ), Entity( "î", 'î' ), Entity( "ï", 'ï' ), Entity( "ð", 'ð' ), Entity( "ñ", 'ñ' ), Entity( "ò", 'ò' ), Entity( "ó", 'ó' ), Entity( "ô", 'ô' ), Entity( "õ", 'õ' ), Entity( "ö", 'ö' ), Entity( "&247;", '÷' ), Entity( "ø", 'ø' ), Entity( "ù", 'ù' ), Entity( "ú", 'ú' ), Entity( "û", 'û' ), Entity( "ü", 'ü' ), Entity( "ý", 'ý' ), Entity( "þ", 'þ' ), Entity( "ÿ", 'ÿ' ), # ÿ Entity( "&#SPACE;", ' ' ), Entity( "&#RS;", '\n' ), Entity( "&#RE;", '\r' ), Entity( """, '"' ), Entity( "&", '&' ), Entity( "<", '<' ), Entity( ">", '>' ), Entity( "CAP-DELTA", 'Δ' ), Entity( "ALPHA", 'α' ), Entity( "BETA", 'β' ), Entity( "DELTA", 'δ' ), Entity( "EPSILON", 'ε' ), Entity( "THETA", 'θ' ), Entity( "MU", 'μ' ), Entity( "PI", 'π' ), Entity( "TAU", 'τ' ), Entity( "CHI", 'χ' ), Entity( "<-", '←' ), Entity( "^", '↑' ), Entity( "->", '→' ), Entity( "v", '↓' ), Entity( "!=", '≠' ), Entity( "<=", '≤' ), Entity( nil, 0 ), }; Hit: adt { glob: string; chap: string; mtype: string; page: string; }; Lnone, Lordered, Lunordered, Ldef, Lother: con iota; # list types Chaps: adt { name: string; primary: int; }; Types: adt { name: string; desc: string; }; # having two separate flags here allows for inclusion of old-style formatted pages # under a new-style three-level tree Oldstyle: adt { names: int; # two-level directory tree? fmt: int; # old internal formats: e.g., "B" font means "L"; name in .TH in all caps }; Href: adt { title: string; chap: string; mtype: string; man: string; }; # per-thread global data Global: adt { bufio: Bufio; bin: ref Bufio->Iobuf; bout: ref Bufio->Iobuf; topname: string; # name of the top level categories in the manual chaps: array of Chaps; # names of top-level partitions of this manual types: array of Types; # names of second-level partitions oldstyle: Oldstyle; mantitle: string; mandir: string; thisone: Hit; # man page we're displaying mtime: int; # last modification time of thisone href: Href; # hrefs of components of this man page hits: array of Hit; nhits: int; list_type: int; pm: string; # proprietary marking def_goobie: string; # deferred goobie sop: int; # output at start of paragraph? sol: int; # input at start of line? broken: int; # output at a break? fill: int; # in fill mode? pre: int; # in PRE block? example: int; # an example active? ipd: int; # emit inter-paragraph distance? indents: int; hangingdt: int; curfont: string; # current font prevfont: string; # previous font lastc: int; # previous char from input scanner def_sm: int; # amount of deferred "make smaller" request mk_href_chap: fn(g: self ref Global, chap: string); mk_href_man: fn(g: self ref Global, man: string, oldstyle: int); mk_href_mtype: fn(g: self ref Global, chap, mtype: string); dobreak: fn(g: self ref Global); print: fn(g: self ref Global, s: string); softbr: fn(g: self ref Global): string; softp: fn(g: self ref Global): string; }; usage() { sys->fprint(stderr, "Usage: man2html file [section]\n"); raise "fail:usage"; } init(nil: ref Draw->Context, args: list of string) { sys = load Sys Sys->PATH; stderr = sys->fildes(2); str = load String String->PATH; dt = load Daytime Daytime->PATH; g := Global_init(); if(args != nil) args = tl args; if(args == nil) usage(); page := hd args; args = tl args; section := "1"; if(args != nil) section = hd args; hit := Hit ("", "man", section, page); domanpage(g, hit); g.bufio->g.bout.flush(); } # remove markup from a string # doesn't handle nested/quoted delimiters demark(s: string): string { t: string; clean := true; for (i := 0; i < len s; i++) { case s[i] { '<' => clean = false; '>' => clean = true; * => if (clean) t[len t] = s[i]; } } return t; } # # Convert an individual man page to HTML and output. # domanpage(g: ref Global, man: Hit) { file := man.page; g.bin = g.bufio->open(file, Bufio->OREAD); g.bout = g.bufio->fopen(sys->fildes(1), Bufio->OWRITE); if (g.bin == nil) { fprint(stderr, "Cannot open %s: %r\n", file); return; } (err, info) := sys->fstat(g.bin.fd); if (! err) { g.mtime = info.mtime; } g.thisone = man; while ((p := getnext(g)) != nil) { c := p[0]; if (c == '.' && g.sol) { if (g.pre) { g.print("</PRE>"); g.pre = false; } dogoobie(g, false); dohangingdt(g); } else if (g.def_goobie != nil || g.def_sm != 0) { g.bufio->g.bin.ungetc(); dogoobie(g, true); } else if (c == '\n') { g.print(p); dohangingdt(g); } else g.print(p); } if (g.pm != nil) { g.print("<BR><BR><BR><FONT SIZE=-2><CENTER>\n"); g.print(g.pm); g.print("<BR></CENTER></FONT>\n"); } closeall(g, 0); rev(g, g.bin); } dogoobie(g: ref Global, deferred: int) { # read line, translate special chars line: string; while ((token := getnext(g)) != "\n") { if (token == nil) return; line += token; } # parse into arguments argl, rargl: list of string; # create reversed version, then invert while ((line = str->drop(line, " \t")) != nil) if (line[0] == '"') { (token, line) = split(line[1:], '"'); rargl = token :: rargl; } else { (token, line) = str->splitl(line, " \t"); rargl = token :: rargl; } if (rargl == nil && !deferred) return; for ( ; rargl != nil; rargl = tl rargl) argl = hd rargl :: argl; def_sm := g.def_sm; if (deferred && def_sm > 0) { g.print(sprint("<FONT SIZE=-%d>", def_sm)); if (g.def_goobie == nil) argl = "dS" :: argl; # dS is our own local creation } subgoobie(g, argl); if (deferred && def_sm > 0) { g.def_sm = 0; g.print("</FONT>"); } } subgoobie(g: ref Global, argl: list of string) { if (g.def_goobie != nil) { argl = g.def_goobie :: argl; g.def_goobie = nil; if (tl argl == nil) return; } # the command part is at most two characters, but may be concatenated with the first arg cmd := hd argl; argl = tl argl; if (len cmd > 2) { cmd = cmd[0:2]; argl = cmd[2:] :: argl; } case cmd { "B" or "I" or "L" or "R" => font(g, cmd, argl); # "R" macro implicitly generated by deferred R* macros "BI" or "BL" or "BR" or "IB" or "IL" or "LB" or "LI" or "RB" or "RI" or "RL" => altfont(g, cmd[0:1], cmd[1:2], argl, true); "IR" or "LR" => anchor(g, cmd[0:1], cmd[1:2], argl); # includes man page refs ("IR" is old style, "LR" is new) "dS" => printargs(g, argl); g.print("\n"); "1C" or "2C" or "DT" or "TF" => # ignore these return; "P" or "PP" or "LP" => g_PP(g); "EE" => g_EE(g); "EX" => g_EX(g); "HP" => g_HP_TP(g, 1); "IP" => g_IP(g, argl); "PD" => g_PD(g, argl); "PM" => g_PM(g, argl); "RE" => g_RE(g);