10e96539fSCharles.Forsythimplement Man2html; 20e96539fSCharles.Forsyth 30e96539fSCharles.Forsythinclude "sys.m"; 40e96539fSCharles.Forsyth stderr: ref Sys->FD; 50e96539fSCharles.Forsyth sys: Sys; 60e96539fSCharles.Forsyth print, fprint, sprint: import sys; 70e96539fSCharles.Forsyth 80e96539fSCharles.Forsyth 90e96539fSCharles.Forsythinclude "bufio.m"; 100e96539fSCharles.Forsyth 110e96539fSCharles.Forsythinclude "draw.m"; 120e96539fSCharles.Forsyth 130e96539fSCharles.Forsythinclude "daytime.m"; 140e96539fSCharles.Forsyth dt: Daytime; 150e96539fSCharles.Forsyth 160e96539fSCharles.Forsythinclude "string.m"; 170e96539fSCharles.Forsyth str: String; 180e96539fSCharles.Forsyth 1930dcb98cSCharles.Forsythinclude "arg.m"; 2030dcb98cSCharles.Forsyth 210e96539fSCharles.ForsythMan2html: module 220e96539fSCharles.Forsyth{ 230e96539fSCharles.Forsyth init: fn(ctxt: ref Draw->Context, args: list of string); 240e96539fSCharles.Forsyth}; 250e96539fSCharles.Forsyth 260e96539fSCharles.ForsythRuneself: con 16r80; 270e96539fSCharles.Forsythfalse, true: con iota; 280e96539fSCharles.Forsyth 290e96539fSCharles.ForsythTroffspec: adt { 300e96539fSCharles.Forsyth name: string; 310e96539fSCharles.Forsyth value: string; 320e96539fSCharles.Forsyth}; 330e96539fSCharles.Forsyth 340e96539fSCharles.Forsythtspec := array [] of { Troffspec 350e96539fSCharles.Forsyth ("ff", "ff"), 360e96539fSCharles.Forsyth ("fi", "fi"), 370e96539fSCharles.Forsyth ("fl", "fl"), 380e96539fSCharles.Forsyth ("Fi", "ffi"), 390e96539fSCharles.Forsyth ("ru", "_"), 401bc0e0d5SCharles.Forsyth ("em", "—"), 410e96539fSCharles.Forsyth ("14", "¼"), 420e96539fSCharles.Forsyth ("12", "½"), 430e96539fSCharles.Forsyth ("co", "©"), 440e96539fSCharles.Forsyth ("de", "°"), 450e96539fSCharles.Forsyth ("dg", "¡"), 460e96539fSCharles.Forsyth ("fm", "´"), 470e96539fSCharles.Forsyth ("rg", "®"), 480e96539fSCharles.Forsyth# ("bu", "*"), 490e96539fSCharles.Forsyth ("bu", "•"), 500e96539fSCharles.Forsyth ("sq", "¤"), 510e96539fSCharles.Forsyth ("hy", "-"), 520e96539fSCharles.Forsyth ("pl", "+"), 530e96539fSCharles.Forsyth ("mi", "-"), 540e96539fSCharles.Forsyth ("mu", "×"), 550e96539fSCharles.Forsyth ("di", "÷"), 560e96539fSCharles.Forsyth ("eq", "="), 570e96539fSCharles.Forsyth ("==", "=="), 580e96539fSCharles.Forsyth (">=", ">="), 590e96539fSCharles.Forsyth ("<=", "<="), 600e96539fSCharles.Forsyth ("!=", "!="), 610e96539fSCharles.Forsyth ("+-", "±"), 620e96539fSCharles.Forsyth ("no", "¬"), 630e96539fSCharles.Forsyth ("sl", "/"), 640e96539fSCharles.Forsyth ("ap", "&"), 650e96539fSCharles.Forsyth ("~=", "~="), 660e96539fSCharles.Forsyth ("pt", "oc"), 670e96539fSCharles.Forsyth ("gr", "GRAD"), 680e96539fSCharles.Forsyth ("->", "->"), 690e96539fSCharles.Forsyth ("<-", "<-"), 700e96539fSCharles.Forsyth ("ua", "^"), 710e96539fSCharles.Forsyth ("da", "v"), 720e96539fSCharles.Forsyth ("is", "Integral"), 730e96539fSCharles.Forsyth ("pd", "DIV"), 740e96539fSCharles.Forsyth ("if", "oo"), 750e96539fSCharles.Forsyth ("sr", "-/"), 760e96539fSCharles.Forsyth ("sb", "(~"), 770e96539fSCharles.Forsyth ("sp", "~)"), 780e96539fSCharles.Forsyth ("cu", "U"), 790e96539fSCharles.Forsyth ("ca", "(^)"), 800e96539fSCharles.Forsyth ("ib", "(="), 810e96539fSCharles.Forsyth ("ip", "=)"), 820e96539fSCharles.Forsyth ("mo", "C"), 830e96539fSCharles.Forsyth ("es", "Ø"), 840e96539fSCharles.Forsyth ("aa", "´"), 850e96539fSCharles.Forsyth ("ga", "`"), 860e96539fSCharles.Forsyth ("ci", "O"), 870e96539fSCharles.Forsyth ("L1", "Lucent"), 880e96539fSCharles.Forsyth ("sc", "§"), 890e96539fSCharles.Forsyth ("dd", "++"), 900e96539fSCharles.Forsyth ("lh", "<="), 910e96539fSCharles.Forsyth ("rh", "=>"), 920e96539fSCharles.Forsyth ("lt", "("), 930e96539fSCharles.Forsyth ("rt", ")"), 940e96539fSCharles.Forsyth ("lc", "|"), 950e96539fSCharles.Forsyth ("rc", "|"), 960e96539fSCharles.Forsyth ("lb", "("), 970e96539fSCharles.Forsyth ("rb", ")"), 980e96539fSCharles.Forsyth ("lf", "|"), 990e96539fSCharles.Forsyth ("rf", "|"), 1000e96539fSCharles.Forsyth ("lk", "|"), 1010e96539fSCharles.Forsyth ("rk", "|"), 1020e96539fSCharles.Forsyth ("bv", "|"), 1030e96539fSCharles.Forsyth ("ts", "s"), 1040e96539fSCharles.Forsyth ("br", "|"), 1050e96539fSCharles.Forsyth ("or", "|"), 1060e96539fSCharles.Forsyth ("ul", "_"), 1070e96539fSCharles.Forsyth ("rn", " "), 1080e96539fSCharles.Forsyth ("*p", "PI"), 1090e96539fSCharles.Forsyth ("**", "*"), 1100e96539fSCharles.Forsyth}; 1110e96539fSCharles.Forsyth 1120e96539fSCharles.Forsyth Entity: adt { 1130e96539fSCharles.Forsyth name: string; 1140e96539fSCharles.Forsyth value: int; 1150e96539fSCharles.Forsyth }; 1160e96539fSCharles.Forsyth Entities: array of Entity; 1170e96539fSCharles.Forsyth 1180e96539fSCharles.ForsythEntities = array[] of { 1190e96539fSCharles.Forsyth Entity( "¡", '¡' ), 1200e96539fSCharles.Forsyth Entity( "¢", '¢' ), 1210e96539fSCharles.Forsyth Entity( "£", '£' ), 1220e96539fSCharles.Forsyth Entity( "¤", '¤' ), 1230e96539fSCharles.Forsyth Entity( "¥", '¥' ), 1240e96539fSCharles.Forsyth Entity( "¦", '¦' ), 1250e96539fSCharles.Forsyth Entity( "§", '§' ), 1260e96539fSCharles.Forsyth Entity( "¨", '¨' ), 1270e96539fSCharles.Forsyth Entity( "©", '©' ), 1280e96539fSCharles.Forsyth Entity( "ª", 'ª' ), 1290e96539fSCharles.Forsyth Entity( "«", '«' ), 1300e96539fSCharles.Forsyth Entity( "¬", '¬' ), 1310e96539fSCharles.Forsyth Entity( "­", '' ), 1320e96539fSCharles.Forsyth Entity( "®", '®' ), 1330e96539fSCharles.Forsyth Entity( "¯", '¯' ), 1340e96539fSCharles.Forsyth Entity( "°", '°' ), 1350e96539fSCharles.Forsyth Entity( "±", '±' ), 1360e96539fSCharles.Forsyth Entity( "²", '²' ), 1370e96539fSCharles.Forsyth Entity( "³", '³' ), 1380e96539fSCharles.Forsyth Entity( "´", '´' ), 1390e96539fSCharles.Forsyth Entity( "µ", 'µ' ), 1400e96539fSCharles.Forsyth Entity( "¶", '¶' ), 1410e96539fSCharles.Forsyth Entity( "·", '·' ), 1420e96539fSCharles.Forsyth Entity( "¸", '¸' ), 1430e96539fSCharles.Forsyth Entity( "¹", '¹' ), 1440e96539fSCharles.Forsyth Entity( "º", 'º' ), 1450e96539fSCharles.Forsyth Entity( "»", '»' ), 1460e96539fSCharles.Forsyth Entity( "¼", '¼' ), 1470e96539fSCharles.Forsyth Entity( "½", '½' ), 1480e96539fSCharles.Forsyth Entity( "¾", '¾' ), 1490e96539fSCharles.Forsyth Entity( "¿", '¿' ), 1500e96539fSCharles.Forsyth Entity( "À", 'À' ), 1510e96539fSCharles.Forsyth Entity( "Á", 'Á' ), 1520e96539fSCharles.Forsyth Entity( "Â", 'Â' ), 1530e96539fSCharles.Forsyth Entity( "Ã", 'Ã' ), 1540e96539fSCharles.Forsyth Entity( "Ä", 'Ä' ), 1550e96539fSCharles.Forsyth Entity( "Å", 'Å' ), 1560e96539fSCharles.Forsyth Entity( "Æ", 'Æ' ), 1570e96539fSCharles.Forsyth Entity( "Ç", 'Ç' ), 1580e96539fSCharles.Forsyth Entity( "È", 'È' ), 1590e96539fSCharles.Forsyth Entity( "É", 'É' ), 1600e96539fSCharles.Forsyth Entity( "Ê", 'Ê' ), 1610e96539fSCharles.Forsyth Entity( "Ë", 'Ë' ), 1620e96539fSCharles.Forsyth Entity( "Ì", 'Ì' ), 1630e96539fSCharles.Forsyth Entity( "Í", 'Í' ), 1640e96539fSCharles.Forsyth Entity( "Î", 'Î' ), 1650e96539fSCharles.Forsyth Entity( "Ï", 'Ï' ), 1660e96539fSCharles.Forsyth Entity( "Ð", 'Ð' ), 1670e96539fSCharles.Forsyth Entity( "Ñ", 'Ñ' ), 1680e96539fSCharles.Forsyth Entity( "Ò", 'Ò' ), 1690e96539fSCharles.Forsyth Entity( "Ó", 'Ó' ), 1700e96539fSCharles.Forsyth Entity( "Ô", 'Ô' ), 1710e96539fSCharles.Forsyth Entity( "Õ", 'Õ' ), 1720e96539fSCharles.Forsyth Entity( "Ö", 'Ö' ), 1730e96539fSCharles.Forsyth Entity( "&215;", '×' ), 1740e96539fSCharles.Forsyth Entity( "Ø", 'Ø' ), 1750e96539fSCharles.Forsyth Entity( "Ù", 'Ù' ), 1760e96539fSCharles.Forsyth Entity( "Ú", 'Ú' ), 1770e96539fSCharles.Forsyth Entity( "Û", 'Û' ), 1780e96539fSCharles.Forsyth Entity( "Ü", 'Ü' ), 1790e96539fSCharles.Forsyth Entity( "Ý", 'Ý' ), 1800e96539fSCharles.Forsyth Entity( "Þ", 'Þ' ), 1810e96539fSCharles.Forsyth Entity( "ß", 'ß' ), 1820e96539fSCharles.Forsyth Entity( "à", 'à' ), 1830e96539fSCharles.Forsyth Entity( "á", 'á' ), 1840e96539fSCharles.Forsyth Entity( "â", 'â' ), 1850e96539fSCharles.Forsyth Entity( "ã", 'ã' ), 1860e96539fSCharles.Forsyth Entity( "ä", 'ä' ), 1870e96539fSCharles.Forsyth Entity( "å", 'å' ), 1880e96539fSCharles.Forsyth Entity( "æ", 'æ' ), 1890e96539fSCharles.Forsyth Entity( "ç", 'ç' ), 1900e96539fSCharles.Forsyth Entity( "è", 'è' ), 1910e96539fSCharles.Forsyth Entity( "é", 'é' ), 1920e96539fSCharles.Forsyth Entity( "ê", 'ê' ), 1930e96539fSCharles.Forsyth Entity( "ë", 'ë' ), 1940e96539fSCharles.Forsyth Entity( "ì", 'ì' ), 1950e96539fSCharles.Forsyth Entity( "í", 'í' ), 1960e96539fSCharles.Forsyth Entity( "î", 'î' ), 1970e96539fSCharles.Forsyth Entity( "ï", 'ï' ), 1980e96539fSCharles.Forsyth Entity( "ð", 'ð' ), 1990e96539fSCharles.Forsyth Entity( "ñ", 'ñ' ), 2000e96539fSCharles.Forsyth Entity( "ò", 'ò' ), 2010e96539fSCharles.Forsyth Entity( "ó", 'ó' ), 2020e96539fSCharles.Forsyth Entity( "ô", 'ô' ), 2030e96539fSCharles.Forsyth Entity( "õ", 'õ' ), 2040e96539fSCharles.Forsyth Entity( "ö", 'ö' ), 2050e96539fSCharles.Forsyth Entity( "&247;", '÷' ), 2060e96539fSCharles.Forsyth Entity( "ø", 'ø' ), 2070e96539fSCharles.Forsyth Entity( "ù", 'ù' ), 2080e96539fSCharles.Forsyth Entity( "ú", 'ú' ), 2090e96539fSCharles.Forsyth Entity( "û", 'û' ), 2100e96539fSCharles.Forsyth Entity( "ü", 'ü' ), 2110e96539fSCharles.Forsyth Entity( "ý", 'ý' ), 2120e96539fSCharles.Forsyth Entity( "þ", 'þ' ), 2130e96539fSCharles.Forsyth Entity( "ÿ", 'ÿ' ), # ÿ 2140e96539fSCharles.Forsyth 2150e96539fSCharles.Forsyth Entity( "&#SPACE;", ' ' ), 2160e96539fSCharles.Forsyth Entity( "&#RS;", '\n' ), 2170e96539fSCharles.Forsyth Entity( "&#RE;", '\r' ), 2180e96539fSCharles.Forsyth Entity( """, '"' ), 2190e96539fSCharles.Forsyth Entity( "&", '&' ), 2200e96539fSCharles.Forsyth Entity( "<", '<' ), 2210e96539fSCharles.Forsyth Entity( ">", '>' ), 2220e96539fSCharles.Forsyth 2230e96539fSCharles.Forsyth Entity( "CAP-DELTA", 'Δ' ), 2240e96539fSCharles.Forsyth Entity( "ALPHA", 'α' ), 2250e96539fSCharles.Forsyth Entity( "BETA", 'β' ), 2260e96539fSCharles.Forsyth Entity( "DELTA", 'δ' ), 2270e96539fSCharles.Forsyth Entity( "EPSILON", 'ε' ), 2280e96539fSCharles.Forsyth Entity( "THETA", 'θ' ), 2290e96539fSCharles.Forsyth Entity( "MU", 'μ' ), 2300e96539fSCharles.Forsyth Entity( "PI", 'π' ), 2310e96539fSCharles.Forsyth Entity( "TAU", 'τ' ), 2320e96539fSCharles.Forsyth Entity( "CHI", 'χ' ), 2330e96539fSCharles.Forsyth 2340e96539fSCharles.Forsyth Entity( "<-", '←' ), 2350e96539fSCharles.Forsyth Entity( "^", '↑' ), 2360e96539fSCharles.Forsyth Entity( "->", '→' ), 2370e96539fSCharles.Forsyth Entity( "v", '↓' ), 2380e96539fSCharles.Forsyth Entity( "!=", '≠' ), 2390e96539fSCharles.Forsyth Entity( "<=", '≤' ), 2400e96539fSCharles.Forsyth Entity( nil, 0 ), 2410e96539fSCharles.Forsyth}; 2420e96539fSCharles.Forsyth 2430e96539fSCharles.Forsyth 2440e96539fSCharles.ForsythHit: adt { 2450e96539fSCharles.Forsyth glob: string; 2460e96539fSCharles.Forsyth chap: string; 2470e96539fSCharles.Forsyth mtype: string; 2480e96539fSCharles.Forsyth page: string; 2490e96539fSCharles.Forsyth}; 2500e96539fSCharles.Forsyth 2510e96539fSCharles.ForsythLnone, Lordered, Lunordered, Ldef, Lother: con iota; # list types 2520e96539fSCharles.Forsyth 2530e96539fSCharles.ForsythChaps: adt { 2540e96539fSCharles.Forsyth name: string; 2550e96539fSCharles.Forsyth primary: int; 2560e96539fSCharles.Forsyth}; 2570e96539fSCharles.Forsyth 2580e96539fSCharles.ForsythTypes: adt { 2590e96539fSCharles.Forsyth name: string; 2600e96539fSCharles.Forsyth desc: string; 2610e96539fSCharles.Forsyth}; 2620e96539fSCharles.Forsyth 2630e96539fSCharles.Forsyth 2640e96539fSCharles.Forsyth# having two separate flags here allows for inclusion of old-style formatted pages 2650e96539fSCharles.Forsyth# under a new-style three-level tree 2660e96539fSCharles.ForsythOldstyle: adt { 2670e96539fSCharles.Forsyth names: int; # two-level directory tree? 2680e96539fSCharles.Forsyth fmt: int; # old internal formats: e.g., "B" font means "L"; name in .TH in all caps 2690e96539fSCharles.Forsyth}; 2700e96539fSCharles.Forsyth 2710e96539fSCharles.ForsythHref: adt { 2720e96539fSCharles.Forsyth title: string; 2730e96539fSCharles.Forsyth chap: string; 2740e96539fSCharles.Forsyth mtype: string; 2750e96539fSCharles.Forsyth man: string; 2760e96539fSCharles.Forsyth}; 2770e96539fSCharles.Forsyth 2780e96539fSCharles.Forsyth# per-thread global data 2790e96539fSCharles.ForsythGlobal: adt { 2800e96539fSCharles.Forsyth bufio: Bufio; 2810e96539fSCharles.Forsyth bin: ref Bufio->Iobuf; 2820e96539fSCharles.Forsyth bout: ref Bufio->Iobuf; 2830e96539fSCharles.Forsyth topname: string; # name of the top level categories in the manual 2840e96539fSCharles.Forsyth chaps: array of Chaps; # names of top-level partitions of this manual 2850e96539fSCharles.Forsyth types: array of Types; # names of second-level partitions 2860e96539fSCharles.Forsyth oldstyle: Oldstyle; 2870e96539fSCharles.Forsyth mantitle: string; 2880e96539fSCharles.Forsyth mandir: string; 2890e96539fSCharles.Forsyth thisone: Hit; # man page we're displaying 2900e96539fSCharles.Forsyth mtime: int; # last modification time of thisone 2910e96539fSCharles.Forsyth href: Href; # hrefs of components of this man page 2920e96539fSCharles.Forsyth hits: array of Hit; 2930e96539fSCharles.Forsyth nhits: int; 2940e96539fSCharles.Forsyth list_type: int; 2950e96539fSCharles.Forsyth pm: string; # proprietary marking 2960e96539fSCharles.Forsyth def_goobie: string; # deferred goobie 2970e96539fSCharles.Forsyth sop: int; # output at start of paragraph? 2980e96539fSCharles.Forsyth sol: int; # input at start of line? 2990e96539fSCharles.Forsyth broken: int; # output at a break? 3000e96539fSCharles.Forsyth fill: int; # in fill mode? 3010e96539fSCharles.Forsyth pre: int; # in PRE block? 3020e96539fSCharles.Forsyth example: int; # an example active? 3030e96539fSCharles.Forsyth ipd: int; # emit inter-paragraph distance? 3040e96539fSCharles.Forsyth indents: int; 3050e96539fSCharles.Forsyth hangingdt: int; 3060e96539fSCharles.Forsyth curfont: string; # current font 3070e96539fSCharles.Forsyth prevfont: string; # previous font 3080e96539fSCharles.Forsyth lastc: int; # previous char from input scanner 3090e96539fSCharles.Forsyth def_sm: int; # amount of deferred "make smaller" request 3100e96539fSCharles.Forsyth 3110e96539fSCharles.Forsyth mk_href_chap: fn(g: self ref Global, chap: string); 3120e96539fSCharles.Forsyth mk_href_man: fn(g: self ref Global, man: string, oldstyle: int); 3130e96539fSCharles.Forsyth mk_href_mtype: fn(g: self ref Global, chap, mtype: string); 3140e96539fSCharles.Forsyth dobreak: fn(g: self ref Global); 3150e96539fSCharles.Forsyth print: fn(g: self ref Global, s: string); 3160e96539fSCharles.Forsyth softbr: fn(g: self ref Global): string; 3170e96539fSCharles.Forsyth softp: fn(g: self ref Global): string; 3180e96539fSCharles.Forsyth}; 3190e96539fSCharles.Forsyth 32030dcb98cSCharles.Forsythheader := "<HTML><HEAD>"; 321*7cdb1d14SCharles.Forsythinitial := ""; 32230dcb98cSCharles.Forsythtrailer := "</BODY></HTML>"; 3230e96539fSCharles.Forsyth 3240e96539fSCharles.Forsythusage() 3250e96539fSCharles.Forsyth{ 326*7cdb1d14SCharles.Forsyth sys->fprint(stderr, "Usage: man2html [-h header] [-i initialtext] [-t trailer] file [section]\n"); 3270e96539fSCharles.Forsyth raise "fail:usage"; 3280e96539fSCharles.Forsyth} 3290e96539fSCharles.Forsyth 3300e96539fSCharles.Forsyth 3310e96539fSCharles.Forsythinit(nil: ref Draw->Context, args: list of string) 3320e96539fSCharles.Forsyth{ 3330e96539fSCharles.Forsyth sys = load Sys Sys->PATH; 3340e96539fSCharles.Forsyth stderr = sys->fildes(2); 3350e96539fSCharles.Forsyth str = load String String->PATH; 3360e96539fSCharles.Forsyth dt = load Daytime Daytime->PATH; 33730dcb98cSCharles.Forsyth arg := load Arg Arg->PATH; 33830dcb98cSCharles.Forsyth arg->init(args); 33930dcb98cSCharles.Forsyth arg->setusage("man2html [-h header] [-t trailer] file [section]"); 34030dcb98cSCharles.Forsyth while((o := arg->opt()) != 0) 34130dcb98cSCharles.Forsyth case o { 34230dcb98cSCharles.Forsyth 'h' => header = arg->earg(); 34330dcb98cSCharles.Forsyth 't' => trailer = arg->earg(); 34430dcb98cSCharles.Forsyth * => arg->usage(); 34530dcb98cSCharles.Forsyth } 34630dcb98cSCharles.Forsyth args = arg->argv(); 3470e96539fSCharles.Forsyth if(args == nil) 34830dcb98cSCharles.Forsyth arg->usage(); 34930dcb98cSCharles.Forsyth arg = nil; 35030dcb98cSCharles.Forsyth g := Global_init(); 3510e96539fSCharles.Forsyth page := hd args; 3520e96539fSCharles.Forsyth args = tl args; 3530e96539fSCharles.Forsyth section := "1"; 3540e96539fSCharles.Forsyth if(args != nil) 3550e96539fSCharles.Forsyth section = hd args; 3560e96539fSCharles.Forsyth hit := Hit ("", "man", section, page); 3570e96539fSCharles.Forsyth domanpage(g, hit); 35830dcb98cSCharles.Forsyth g.print(trailer+"\n"); 3590e96539fSCharles.Forsyth g.bufio->g.bout.flush(); 3600e96539fSCharles.Forsyth} 3610e96539fSCharles.Forsyth 3620e96539fSCharles.Forsyth# remove markup from a string 3630e96539fSCharles.Forsyth# doesn't handle nested/quoted delimiters 3640e96539fSCharles.Forsythdemark(s: string): string 3650e96539fSCharles.Forsyth{ 3660e96539fSCharles.Forsyth t: string; 3670e96539fSCharles.Forsyth clean := true; 3680e96539fSCharles.Forsyth for (i := 0; i < len s; i++) { 3690e96539fSCharles.Forsyth case s[i] { 3700e96539fSCharles.Forsyth '<' => 3710e96539fSCharles.Forsyth clean = false; 3720e96539fSCharles.Forsyth '>' => 3730e96539fSCharles.Forsyth clean = true; 3740e96539fSCharles.Forsyth * => 3750e96539fSCharles.Forsyth if (clean) 3760e96539fSCharles.Forsyth t[len t] = s[i]; 3770e96539fSCharles.Forsyth } 3780e96539fSCharles.Forsyth } 3790e96539fSCharles.Forsyth return t; 3800e96539fSCharles.Forsyth} 3810e96539fSCharles.Forsyth 3820e96539fSCharles.Forsyth 3830e96539fSCharles.Forsyth# 3840e96539fSCharles.Forsyth# Convert an individual man page to HTML and output. 3850e96539fSCharles.Forsyth# 3860e96539fSCharles.Forsythdomanpage(g: ref Global, man: Hit) 3870e96539fSCharles.Forsyth{ 3880e96539fSCharles.Forsyth file := man.page; 3890e96539fSCharles.Forsyth g.bin = g.bufio->open(file, Bufio->OREAD); 3900e96539fSCharles.Forsyth g.bout = g.bufio->fopen(sys->fildes(1), Bufio->OWRITE); 3910e96539fSCharles.Forsyth if (g.bin == nil) { 3920e96539fSCharles.Forsyth fprint(stderr, "Cannot open %s: %r\n", file); 3930e96539fSCharles.Forsyth return; 3940e96539fSCharles.Forsyth } 3950e96539fSCharles.Forsyth (err, info) := sys->fstat(g.bin.fd); 3960e96539fSCharles.Forsyth if (! err) { 3970e96539fSCharles.Forsyth g.mtime = info.mtime; 3980e96539fSCharles.Forsyth } 3990e96539fSCharles.Forsyth g.thisone = man; 4000e96539fSCharles.Forsyth while ((p := getnext(g)) != nil) { 4010e96539fSCharles.Forsyth c := p[0]; 4020e96539fSCharles.Forsyth if (c == '.' && g.sol) { 4030e96539fSCharles.Forsyth if (g.pre) { 4040e96539fSCharles.Forsyth g.print("</PRE>"); 4050e96539fSCharles.Forsyth g.pre = false; 4060e96539fSCharles.Forsyth } 4070e96539fSCharles.Forsyth dogoobie(g, false); 4080e96539fSCharles.Forsyth dohangingdt(g); 4090e96539fSCharles.Forsyth } else if (g.def_goobie != nil || g.def_sm != 0) { 4100e96539fSCharles.Forsyth g.bufio->g.bin.ungetc(); 4110e96539fSCharles.Forsyth dogoobie(g, true); 4120e96539fSCharles.Forsyth } else if (c == '\n') { 4130e96539fSCharles.Forsyth g.print(p); 4140e96539fSCharles.Forsyth dohangingdt(g); 4150e96539fSCharles.Forsyth } else 4160e96539fSCharles.Forsyth g.print(p); 4170e96539fSCharles.Forsyth } 4180e96539fSCharles.Forsyth if (g.pm != nil) { 4190e96539fSCharles.Forsyth g.print("<BR><BR><BR><FONT SIZE=-2><CENTER>\n"); 4200e96539fSCharles.Forsyth g.print(g.pm); 4210e96539fSCharles.Forsyth g.print("<BR></CENTER></FONT>\n"); 4220e96539fSCharles.Forsyth } 4230e96539fSCharles.Forsyth closeall(g, 0); 4240e96539fSCharles.Forsyth rev(g, g.bin); 4250e96539fSCharles.Forsyth} 4260e96539fSCharles.Forsyth 4270e96539fSCharles.Forsythdogoobie(g: ref Global, deferred: int) 4280e96539fSCharles.Forsyth{ 4290e96539fSCharles.Forsyth # read line, translate special chars 43079aa5773SCharles.Forsyth line := getline(g); 43179aa5773SCharles.Forsyth if (line == nil || line == "\n") 4320e96539fSCharles.Forsyth return; 4330e96539fSCharles.Forsyth 4340e96539fSCharles.Forsyth # parse into arguments 43579aa5773SCharles.Forsyth token: string; 4360e96539fSCharles.Forsyth argl, rargl: list of string; # create reversed version, then invert 43779aa5773SCharles.Forsyth while ((line = str->drop(line, " \t\n")) != nil) 4380e96539fSCharles.Forsyth if (line[0] == '"') { 4390e96539fSCharles.Forsyth (token, line) = split(line[1:], '"'); 4400e96539fSCharles.Forsyth rargl = token :: rargl; 4410e96539fSCharles.Forsyth } else { 4420e96539fSCharles.Forsyth (token, line) = str->splitl(line, " \t"); 4430e96539fSCharles.Forsyth rargl = token :: rargl; 4440e96539fSCharles.Forsyth } 4450e96539fSCharles.Forsyth 4460e96539fSCharles.Forsyth if (rargl == nil && !deferred) 4470e96539fSCharles.Forsyth return; 4480e96539fSCharles.Forsyth for ( ; rargl != nil; rargl = tl rargl) 4490e96539fSCharles.Forsyth argl = hd rargl :: argl; 4500e96539fSCharles.Forsyth 4510e96539fSCharles.Forsyth def_sm := g.def_sm; 4520e96539fSCharles.Forsyth if (deferred && def_sm > 0) { 4530e96539fSCharles.Forsyth g.print(sprint("<FONT SIZE=-%d>", def_sm)); 4540e96539fSCharles.Forsyth if (g.def_goobie == nil) 4550e96539fSCharles.Forsyth argl = "dS" :: argl; # dS is our own local creation 4560e96539fSCharles.Forsyth } 4570e96539fSCharles.Forsyth 4580e96539fSCharles.Forsyth subgoobie(g, argl); 4590e96539fSCharles.Forsyth 4600e96539fSCharles.Forsyth if (deferred && def_sm > 0) { 4610e96539fSCharles.Forsyth g.def_sm = 0; 4620e96539fSCharles.Forsyth g.print("</FONT>"); 4630e96539fSCharles.Forsyth } 4640e96539fSCharles.Forsyth} 4650e96539fSCharles.Forsyth 4660e96539fSCharles.Forsythsubgoobie(g: ref Global, argl: list of string) 4670e96539fSCharles.Forsyth{ 4680e96539fSCharles.Forsyth if (g.def_goobie != nil) { 4690e96539fSCharles.Forsyth argl = g.def_goobie :: argl; 4700e96539fSCharles.Forsyth g.def_goobie = nil; 4710e96539fSCharles.Forsyth if (tl argl == nil) 4720e96539fSCharles.Forsyth return; 4730e96539fSCharles.Forsyth } 4740e96539fSCharles.Forsyth 4750e96539fSCharles.Forsyth # the command part is at most two characters, but may be concatenated with the first arg 4760e96539fSCharles.Forsyth cmd := hd argl; 4770e96539fSCharles.Forsyth argl = tl argl; 4780e96539fSCharles.Forsyth if (len cmd > 2) { 4790e96539fSCharles.Forsyth cmd = cmd[0:2]; 4800e96539fSCharles.Forsyth argl = cmd[2:] :: argl; 4810e96539fSCharles.Forsyth } 4820e96539fSCharles.Forsyth 4830e96539fSCharles.Forsyth case cmd { 4840e96539fSCharles.Forsyth 4850e96539fSCharles.Forsyth "B" or "I" or "L" or "R" => 4860e96539fSCharles.Forsyth font(g, cmd, argl); # "R" macro implicitly generated by deferred R* macros 4870e96539fSCharles.Forsyth 4880e96539fSCharles.Forsyth "BI" or "BL" or "BR" or 4890e96539fSCharles.Forsyth "IB" or "IL" or 4900e96539fSCharles.Forsyth "LB" or "LI" or 4910e96539fSCharles.Forsyth "RB" or "RI" or "RL" => 4920e96539fSCharles.Forsyth altfont(g, cmd[0:1], cmd[1:2], argl, true); 4930e96539fSCharles.Forsyth 4940e96539fSCharles.Forsyth "IR" or "LR" => 4950e96539fSCharles.Forsyth anchor(g, cmd[0:1], cmd[1:2], argl); # includes man page refs ("IR" is old style, "LR" is new) 4960e96539fSCharles.Forsyth 4970e96539fSCharles.Forsyth "dS" => 4980e96539fSCharles.Forsyth printargs(g, argl); 4990e96539fSCharles.Forsyth g.print("\n"); 5000e96539fSCharles.Forsyth 5010e96539fSCharles.Forsyth "1C" or "2C" or "DT" or "TF" => # ignore these 5020e96539fSCharles.Forsyth return; 5030e96539fSCharles.Forsyth 50479aa5773SCharles.Forsyth "ig" => 50579aa5773SCharles.Forsyth while ((line := getline(g)) != nil){ 50679aa5773SCharles.Forsyth if(len line > 1 && line[0:2] == "..") 50779aa5773SCharles.Forsyth break; 50879aa5773SCharles.Forsyth } 50979aa5773SCharles.Forsyth return; 51079aa5773SCharles.Forsyth 5110e96539fSCharles.Forsyth "P" or "PP" or "LP" => 5120e96539fSCharles.Forsyth g_PP(g); 5130e96539fSCharles.Forsyth 5140e96539fSCharles.Forsyth "EE" => g_EE(g); 5150e96539fSCharles.Forsyth "EX" => g_EX(g); 5160e96539fSCharles.Forsyth "HP" => g_HP_TP(g, 1); 5170e96539fSCharles.Forsyth "IP" => g_IP(g, argl); 5180e96539fSCharles.Forsyth "PD" => g_PD(g, argl); 5190e96539fSCharles.Forsyth "PM" => g_PM(g, argl); 5200e96539fSCharles.Forsyth "RE" => g_RE(g); 5210e96539fSCharles.Forsyth "RS" => g_RS(g); 5220e96539fSCharles.Forsyth "SH" => g_SH(g, argl); 5230e96539fSCharles.Forsyth "SM" => g_SM(g, argl); 5240e96539fSCharles.Forsyth "SS" => g_SS(g, argl); 5250e96539fSCharles.Forsyth "TH" => g_TH(g, argl); 5260e96539fSCharles.Forsyth "TP" => g_HP_TP(g, 3); 5270e96539fSCharles.Forsyth 5280e96539fSCharles.Forsyth "br" => g_br(g); 5290e96539fSCharles.Forsyth "sp" => g_sp(g, argl); 5300e96539fSCharles.Forsyth "ti" => g_br(g); 5310e96539fSCharles.Forsyth "nf" => g_nf(g); 5320e96539fSCharles.Forsyth "fi" => g_fi(g); 5330e96539fSCharles.Forsyth "ft" => g_ft(g, argl); 5340e96539fSCharles.Forsyth 5350e96539fSCharles.Forsyth * => return; # ignore unrecognized commands 5360e96539fSCharles.Forsyth } 5370e96539fSCharles.Forsyth 5380e96539fSCharles.Forsyth} 5390e96539fSCharles.Forsyth 5400e96539fSCharles.Forsythg_br(g: ref Global) 5410e96539fSCharles.Forsyth{ 5420e96539fSCharles.Forsyth if (g.hangingdt != 0) { 5430e96539fSCharles.Forsyth g.print("<DD>"); 5440e96539fSCharles.Forsyth g.hangingdt = 0; 5450e96539fSCharles.Forsyth } else if (g.fill && ! g.broken) 5460e96539fSCharles.Forsyth g.print("<BR>\n"); 5470e96539fSCharles.Forsyth g.broken = true; 5480e96539fSCharles.Forsyth} 5490e96539fSCharles.Forsyth 5500e96539fSCharles.Forsythg_EE(g: ref Global) 5510e96539fSCharles.Forsyth{ 5520e96539fSCharles.Forsyth g.print("</PRE>\n"); 5530e96539fSCharles.Forsyth g.fill = true; 5540e96539fSCharles.Forsyth g.broken = true; 5550e96539fSCharles.Forsyth g.example = false; 5560e96539fSCharles.Forsyth} 5570e96539fSCharles.Forsyth 5580e96539fSCharles.Forsythg_EX(g: ref Global) 5590e96539fSCharles.Forsyth{ 5600e96539fSCharles.Forsyth g.print("<PRE>"); 5610e96539fSCharles.Forsyth if (! g.broken) 5620e96539fSCharles.Forsyth g.print("\n"); 5630e96539fSCharles.Forsyth g.sop = true; 5640e96539fSCharles.Forsyth g.fill = false; 5650e96539fSCharles.Forsyth g.broken = true; 5660e96539fSCharles.Forsyth g.example = true; 5670e96539fSCharles.Forsyth} 5680e96539fSCharles.Forsyth 5690e96539fSCharles.Forsythg_fi(g: ref Global) 5700e96539fSCharles.Forsyth{ 5710e96539fSCharles.Forsyth if (g.fill) 5720e96539fSCharles.Forsyth return; 5730e96539fSCharles.Forsyth g.fill = true; 5740e96539fSCharles.Forsyth g.print("<P style=\"display: inline; white-space: normal\">\n"); 5750e96539fSCharles.Forsyth g.broken = true; 5760e96539fSCharles.Forsyth g.sop = true; 5770e96539fSCharles.Forsyth} 5780e96539fSCharles.Forsyth 5790e96539fSCharles.Forsythg_ft(g: ref Global, argl: list of string) 5800e96539fSCharles.Forsyth{ 5810e96539fSCharles.Forsyth font: string; 5820e96539fSCharles.Forsyth arg: string; 5830e96539fSCharles.Forsyth 5840e96539fSCharles.Forsyth if (argl == nil) 5850e96539fSCharles.Forsyth arg = "P"; 5860e96539fSCharles.Forsyth else 5870e96539fSCharles.Forsyth arg = hd argl; 5880e96539fSCharles.Forsyth 5890e96539fSCharles.Forsyth if (g.curfont != nil) 5900e96539fSCharles.Forsyth g.print(sprint("</%s>", g.curfont)); 5910e96539fSCharles.Forsyth 5920e96539fSCharles.Forsyth case arg { 5930e96539fSCharles.Forsyth "2" or "I" => 5940e96539fSCharles.Forsyth font = "I"; 5950e96539fSCharles.Forsyth "3" or "B" => 5960e96539fSCharles.Forsyth font = "B"; 5970e96539fSCharles.Forsyth "5" or "L" => 5980e96539fSCharles.Forsyth font = "TT"; 5990e96539fSCharles.Forsyth "P" => 6000e96539fSCharles.Forsyth font = g.prevfont; 6010e96539fSCharles.Forsyth * => 6020e96539fSCharles.Forsyth font = nil; 6030e96539fSCharles.Forsyth } 6040e96539fSCharles.Forsyth g.prevfont = g.curfont; 6050e96539fSCharles.Forsyth g.curfont = font; 6060e96539fSCharles.Forsyth if (g.curfont != nil) 6070e96539fSCharles.Forsyth if (g.fill) 6080e96539fSCharles.Forsyth g.print(sprint("<%s>", g.curfont)); 6090e96539fSCharles.Forsyth else 6100e96539fSCharles.Forsyth g.print(sprint("<%s style=\"white-space: pre\">", g.curfont)); 6110e96539fSCharles.Forsyth} 6120e96539fSCharles.Forsyth 6130e96539fSCharles.Forsyth# level == 1 is a .HP; level == 3 is a .TP 6140e96539fSCharles.Forsythg_HP_TP(g: ref Global, level: int) 6150e96539fSCharles.Forsyth{ 6160e96539fSCharles.Forsyth case g.list_type { 6170e96539fSCharles.Forsyth Ldef => 6180e96539fSCharles.Forsyth if (g.hangingdt != 0) 6190e96539fSCharles.Forsyth g.print("<DD>"); 6200e96539fSCharles.Forsyth g.print(g.softbr() + "<DT>"); 6210e96539fSCharles.Forsyth * => 6220e96539fSCharles.Forsyth closel(g); 6230e96539fSCharles.Forsyth g.list_type = Ldef; 6240e96539fSCharles.Forsyth g.print("<DL compact>\n" + g.softbr() + "<DT>"); 6250e96539fSCharles.Forsyth } 6260e96539fSCharles.Forsyth g.hangingdt = level; 6270e96539fSCharles.Forsyth g.broken = true; 6280e96539fSCharles.Forsyth} 6290e96539fSCharles.Forsyth 6300e96539fSCharles.Forsythg_IP(g: ref Global, argl: list of string) 6310e96539fSCharles.Forsyth{ 6320e96539fSCharles.Forsyth case g.list_type { 6330e96539fSCharles.Forsyth 6340e96539fSCharles.Forsyth Lordered or Lunordered or Lother => 6350e96539fSCharles.Forsyth ; # continue with an existing list 6360e96539fSCharles.Forsyth 6370e96539fSCharles.Forsyth * => 6380e96539fSCharles.Forsyth # figure out the type of a new list and start it 6390e96539fSCharles.Forsyth closel(g); 6400e96539fSCharles.Forsyth arg := ""; 6410e96539fSCharles.Forsyth if (argl != nil) 6420e96539fSCharles.Forsyth arg = hd argl; 6430e96539fSCharles.Forsyth case arg { 6440e96539fSCharles.Forsyth "1" or "i" or "I" or "a" or "A" => 6450e96539fSCharles.Forsyth g.list_type = Lordered; 6460e96539fSCharles.Forsyth g.print(sprint("<OL type=%s>\n", arg)); 6470e96539fSCharles.Forsyth "*" or "•" or "•" => 6480e96539fSCharles.Forsyth g.list_type = Lunordered; 6490e96539fSCharles.Forsyth g.print("<UL type=disc>\n"); 6500e96539fSCharles.Forsyth "○" or "○"=> 6510e96539fSCharles.Forsyth g.list_type = Lunordered; 6520e96539fSCharles.Forsyth g.print("<UL type=circle>\n"); 6530e96539fSCharles.Forsyth "□" or "□" => 6540e96539fSCharles.Forsyth g.list_type = Lunordered; 6550e96539fSCharles.Forsyth g.print("<UL type=square>\n"); 6560e96539fSCharles.Forsyth * => 6570e96539fSCharles.Forsyth g.list_type = Lother; 6580e96539fSCharles.Forsyth g.print("<DL compact>\n"); 6590e96539fSCharles.Forsyth } 6600e96539fSCharles.Forsyth } 6610e96539fSCharles.Forsyth 6620e96539fSCharles.Forsyth # actually do this list item 6630e96539fSCharles.Forsyth case g.list_type { 6640e96539fSCharles.Forsyth Lother => 6650e96539fSCharles.Forsyth g.print(g.softp()); # make sure there's space before each list item 6660e96539fSCharles.Forsyth if (argl != nil) { 6670e96539fSCharles.Forsyth g.print("<DT>"); 6680e96539fSCharles.Forsyth printargs(g, argl); 6690e96539fSCharles.Forsyth } 6700e96539fSCharles.Forsyth g.print("\n<DD>"); 6710e96539fSCharles.Forsyth 6720e96539fSCharles.Forsyth Lordered or Lunordered => 6730e96539fSCharles.Forsyth g.print(g.softp() + "<LI>"); 6740e96539fSCharles.Forsyth } 6750e96539fSCharles.Forsyth g.broken = true; 6760e96539fSCharles.Forsyth} 6770e96539fSCharles.Forsyth 6780e96539fSCharles.Forsythg_nf(g: ref Global) 6790e96539fSCharles.Forsyth{ 6800e96539fSCharles.Forsyth if (! g.fill) 6810e96539fSCharles.Forsyth return; 6820e96539fSCharles.Forsyth g.fill = false; 6830e96539fSCharles.Forsyth g.print("<PRE>\n"); 6840e96539fSCharles.Forsyth g.broken = true; 6850e96539fSCharles.Forsyth g.sop = true; 6860e96539fSCharles.Forsyth g.pre = true; 6870e96539fSCharles.Forsyth} 6880e96539fSCharles.Forsyth 6890e96539fSCharles.Forsythg_PD(g: ref Global, argl: list of string) 6900e96539fSCharles.Forsyth{ 6910e96539fSCharles.Forsyth if (len argl == 1 && hd argl == "0") 6920e96539fSCharles.Forsyth g.ipd = false; 6930e96539fSCharles.Forsyth else 6940e96539fSCharles.Forsyth g.ipd = true; 6950e96539fSCharles.Forsyth} 6960e96539fSCharles.Forsyth 6970e96539fSCharles.Forsythg_PM(g: ref Global, argl: list of string) 6980e96539fSCharles.Forsyth{ 6990e96539fSCharles.Forsyth code := "P"; 7000e96539fSCharles.Forsyth if (argl != nil) 7010e96539fSCharles.Forsyth code = hd argl; 7020e96539fSCharles.Forsyth case code { 7030e96539fSCharles.Forsyth * => # includes "1" and "P" 7040e96539fSCharles.Forsyth g.pm = "<B>Lucent Technologies - Proprietary</B>\n" + 7050e96539fSCharles.Forsyth "<BR>Use pursuant to Company Instructions.\n"; 7060e96539fSCharles.Forsyth "2" or "RS" => 7070e96539fSCharles.Forsyth g.pm = "<B>Lucent Technologies - Proprietary (Restricted)</B>\n" + 7080e96539fSCharles.Forsyth "<BR>Solely for authorized persons having a need to know\n" + 7090e96539fSCharles.Forsyth "<BR>pursuant to Company Instructions.\n"; 7100e96539fSCharles.Forsyth "3" or "RG" => 7110e96539fSCharles.Forsyth g.pm = "<B>Lucent Technologies - Proprietary (Registered)</B>\n" + 7120e96539fSCharles.Forsyth "<BR>Solely for authorized persons having a need to know\n" + 7130e96539fSCharles.Forsyth "<BR>and subject to cover sheet instructions.\n"; 7140e96539fSCharles.Forsyth "4" or "CP" => 7150e96539fSCharles.Forsyth g.pm = "SEE PROPRIETARY NOTICE ON COVER PAGE\n"; 7160e96539fSCharles.Forsyth "5" or "CR" => 7170e96539fSCharles.Forsyth g.pm = "Copyright xxxx Lucent Technologies\n" + # should fill in the year from the date register 7180e96539fSCharles.Forsyth "<BR>All Rights Reserved.\n"; 7190e96539fSCharles.Forsyth "6" or "UW" => 7200e96539fSCharles.Forsyth g.pm = "THIS DOCUMENT CONTAINS PROPRIETARY INFORMATION OF\n" + 7210e96539fSCharles.Forsyth "<BR>LUCENT TECHNOLOGIES INC. AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN\n" + 7220e96539fSCharles.Forsyth "<BR>ACCORDANCE WITH APPLICABLE AGREEMENTS.\n" + 7230e96539fSCharles.Forsyth "<BR>Unpublished & Not for Publication\n"; 7240e96539fSCharles.Forsyth } 7250e96539fSCharles.Forsyth} 7260e96539fSCharles.Forsyth 7270e96539fSCharles.Forsythg_PP(g: ref Global) 7280e96539fSCharles.Forsyth{ 7290e96539fSCharles.Forsyth closel(g); 7300e96539fSCharles.Forsyth reset_font(g); 7310e96539fSCharles.Forsyth p := g.softp(); 7320e96539fSCharles.Forsyth if (p != nil) 7330e96539fSCharles.Forsyth g.print(p); 7340e96539fSCharles.Forsyth g.sop = true; 7350e96539fSCharles.Forsyth g.broken = true; 7360e96539fSCharles.Forsyth} 7370e96539fSCharles.Forsyth 7380e96539fSCharles.Forsythg_RE(g: ref Global) 7390e96539fSCharles.Forsyth{ 7400e96539fSCharles.Forsyth g.print("</DL>\n"); 7410e96539fSCharles.Forsyth g.indents--; 7420e96539fSCharles.Forsyth g.broken = true; 7430e96539fSCharles.Forsyth} 7440e96539fSCharles.Forsyth 7450e96539fSCharles.Forsythg_RS(g: ref Global) 7460e96539fSCharles.Forsyth{ 7470e96539fSCharles.Forsyth g.print("<DL>\n<DT><DD>"); 7480e96539fSCharles.Forsyth g.indents++; 7490e96539fSCharles.Forsyth g.broken = true; 7500e96539fSCharles.Forsyth} 7510e96539fSCharles.Forsyth 7520e96539fSCharles.Forsythg_SH(g: ref Global, argl: list of string) 7530e96539fSCharles.Forsyth{ 7540e96539fSCharles.Forsyth closeall(g, 1); # .SH is top-level list item 7550e96539fSCharles.Forsyth if (g.example) 7560e96539fSCharles.Forsyth g_EE(g); 757*7cdb1d14SCharles.Forsyth g_fi(g); 7580e96539fSCharles.Forsyth if (g.fill && ! g.sop) 7590e96539fSCharles.Forsyth g.print("<P>"); 7600e96539fSCharles.Forsyth g.print("<DT><H4>"); 7610e96539fSCharles.Forsyth printargs(g, argl); 7620e96539fSCharles.Forsyth g.print("</H4>\n"); 7630e96539fSCharles.Forsyth g.print("<DD>\n"); 7640e96539fSCharles.Forsyth g.sop = true; 7650e96539fSCharles.Forsyth g.broken = true; 7660e96539fSCharles.Forsyth} 7670e96539fSCharles.Forsyth 7680e96539fSCharles.Forsythg_SM(g: ref Global, argl: list of string) 7690e96539fSCharles.Forsyth{ 7700e96539fSCharles.Forsyth g.def_sm++; # can't use def_goobie, lest we collide with a deferred font macro 7710e96539fSCharles.Forsyth if (argl == nil) 7720e96539fSCharles.Forsyth return; 7730e96539fSCharles.Forsyth g.print(sprint("<FONT SIZE=-%d>", g.def_sm)); 7740e96539fSCharles.Forsyth printargs(g, argl); 7750e96539fSCharles.Forsyth g.print("</FONT>\n"); 7760e96539fSCharles.Forsyth g.def_sm = 0; 7770e96539fSCharles.Forsyth} 7780e96539fSCharles.Forsyth 7790e96539fSCharles.Forsythg_sp(g: ref Global, argl: list of string) 7800e96539fSCharles.Forsyth{ 7810e96539fSCharles.Forsyth if (g.sop && g.fill) 7820e96539fSCharles.Forsyth return; 7830e96539fSCharles.Forsyth count := 1; 7840e96539fSCharles.Forsyth if (argl != nil) { 7850e96539fSCharles.Forsyth rcount := real hd argl; 7860e96539fSCharles.Forsyth count = int rcount; # may be 0 (e.g., ".sp .5") 7870e96539fSCharles.Forsyth if (count == 0 && rcount > 0.0) 7880e96539fSCharles.Forsyth count = 1; # force whitespace for fractional lines 7890e96539fSCharles.Forsyth } 7900e96539fSCharles.Forsyth g.dobreak(); 7910e96539fSCharles.Forsyth for (i := 0; i < count; i++) 7920e96539fSCharles.Forsyth g.print(" <BR>\n"); 7930e96539fSCharles.Forsyth g.broken = true; 7940e96539fSCharles.Forsyth g.sop = count > 0; 7950e96539fSCharles.Forsyth} 7960e96539fSCharles.Forsyth 7970e96539fSCharles.Forsythg_SS(g: ref Global, argl: list of string) 7980e96539fSCharles.Forsyth{ 7990e96539fSCharles.Forsyth closeall(g, 1); 8000e96539fSCharles.Forsyth g.indents++; 8010e96539fSCharles.Forsyth g.print(g.softp() + "<DL><DT><FONT SIZE=3><B>"); 8020e96539fSCharles.Forsyth printargs(g, argl); 8030e96539fSCharles.Forsyth g.print("</B></FONT>\n"); 8040e96539fSCharles.Forsyth g.print("<DD>\n"); 8050e96539fSCharles.Forsyth g.sop = true; 8060e96539fSCharles.Forsyth g.broken = true; 8070e96539fSCharles.Forsyth} 8080e96539fSCharles.Forsyth 8090e96539fSCharles.Forsythg_TH(g: ref Global, argl: list of string) 8100e96539fSCharles.Forsyth{ 8110e96539fSCharles.Forsyth if (g.oldstyle.names && len argl > 2) 8120e96539fSCharles.Forsyth argl = hd argl :: hd tl argl :: nil; # ignore extra .TH args on pages in oldstyle trees 8130e96539fSCharles.Forsyth case len argl { 8140e96539fSCharles.Forsyth 0 => 8150e96539fSCharles.Forsyth g.oldstyle.fmt = true; 8160e96539fSCharles.Forsyth title(g, sprint("%s", g.href.title), false); 8170e96539fSCharles.Forsyth 1 => 8180e96539fSCharles.Forsyth g.oldstyle.fmt = true; 8190e96539fSCharles.Forsyth title(g, sprint("%s", hd argl), false); # any pages use this form? 8200e96539fSCharles.Forsyth 2 => 8210e96539fSCharles.Forsyth g.oldstyle.fmt = true; 8220e96539fSCharles.Forsyth g.thisone.page = hd argl; 8230e96539fSCharles.Forsyth g.thisone.mtype = hd tl argl; 8240e96539fSCharles.Forsyth g.mk_href_man(hd argl, true); 8250e96539fSCharles.Forsyth g.mk_href_mtype(nil, hd tl argl); 8260e96539fSCharles.Forsyth title(g, sprint("%s(%s)", g.href.man, g.href.mtype), false); 8270e96539fSCharles.Forsyth * => 8280e96539fSCharles.Forsyth g.oldstyle.fmt = false; 8290e96539fSCharles.Forsyth chap := hd tl tl argl; 8300e96539fSCharles.Forsyth g.mk_href_chap(chap); 8310e96539fSCharles.Forsyth g.mk_href_man(hd argl, false); 8320e96539fSCharles.Forsyth g.mk_href_mtype(chap, hd tl argl); 8330e96539fSCharles.Forsyth title(g, sprint("%s/%s/%s(%s)", g.href.title, g.href.chap, g.href.man, g.href.mtype), false); 8340e96539fSCharles.Forsyth } 8350e96539fSCharles.Forsyth g.print("[<a href=\"../index.html\">manual index</a>]"); 8360e96539fSCharles.Forsyth g.print("[<a href=\"INDEX.html\">section index</a>]<p>"); 8370e96539fSCharles.Forsyth g.print("<DL>\n"); # whole man page is just one big list 8380e96539fSCharles.Forsyth g.indents = 1; 8390e96539fSCharles.Forsyth g.sop = true; 8400e96539fSCharles.Forsyth g.broken = true; 8410e96539fSCharles.Forsyth} 8420e96539fSCharles.Forsyth 8430e96539fSCharles.Forsythdohangingdt(g: ref Global) 8440e96539fSCharles.Forsyth{ 8450e96539fSCharles.Forsyth case g.hangingdt { 8460e96539fSCharles.Forsyth 3 => 8470e96539fSCharles.Forsyth g.hangingdt--; 8480e96539fSCharles.Forsyth 2 => 8490e96539fSCharles.Forsyth g.print("<DD>"); 8500e96539fSCharles.Forsyth g.hangingdt = 0; 8510e96539fSCharles.Forsyth g.broken = true; 8520e96539fSCharles.Forsyth } 8530e96539fSCharles.Forsyth} 8540e96539fSCharles.Forsyth 8550e96539fSCharles.Forsyth# close a list, if there's one active 8560e96539fSCharles.Forsythclosel(g: ref Global) 8570e96539fSCharles.Forsyth{ 8580e96539fSCharles.Forsyth case g.list_type { 8590e96539fSCharles.Forsyth Lordered => 8600e96539fSCharles.Forsyth g.print("</OL>\n"); 8610e96539fSCharles.Forsyth g.broken = true; 8620e96539fSCharles.Forsyth Lunordered => 8630e96539fSCharles.Forsyth g.print("</UL>\n"); 8640e96539fSCharles.Forsyth g.broken = true; 8650e96539fSCharles.Forsyth Lother or Ldef => 8660e96539fSCharles.Forsyth g.print("</DL>\n"); 8670e96539fSCharles.Forsyth g.broken = true; 8680e96539fSCharles.Forsyth } 8690e96539fSCharles.Forsyth g.list_type = Lnone; 8700e96539fSCharles.Forsyth} 8710e96539fSCharles.Forsyth 8720e96539fSCharles.Forsythcloseall(g: ref Global, level: int) 8730e96539fSCharles.Forsyth{ 8740e96539fSCharles.Forsyth closel(g); 8750e96539fSCharles.Forsyth reset_font(g); 8760e96539fSCharles.Forsyth while (g.indents > level) { 8770e96539fSCharles.Forsyth g.indents--; 8780e96539fSCharles.Forsyth g.print("</DL>\n"); 8790e96539fSCharles.Forsyth g.broken = true; 8800e96539fSCharles.Forsyth } 8810e96539fSCharles.Forsyth} 8820e96539fSCharles.Forsyth 8830e96539fSCharles.Forsyth# 8840e96539fSCharles.Forsyth# Show last revision date for a file. 8850e96539fSCharles.Forsyth# 8860e96539fSCharles.Forsythrev(g: ref Global, filebuf: ref Bufio->Iobuf) 8870e96539fSCharles.Forsyth{ 8880e96539fSCharles.Forsyth if (g.mtime == 0) { 8890e96539fSCharles.Forsyth (err, info) := sys->fstat(filebuf.fd); 8900e96539fSCharles.Forsyth if (! err) 8910e96539fSCharles.Forsyth g.mtime = info.mtime; 8920e96539fSCharles.Forsyth } 8930e96539fSCharles.Forsyth if (g.mtime != 0) { 8940e96539fSCharles.Forsyth g.print("<P><TABLE width=\"100%\" border=0 cellpadding=10 cellspacing=0 bgcolor=\"#E0E0E0\">\n"); 8950e96539fSCharles.Forsyth g.print("<TR>"); 8960e96539fSCharles.Forsyth g.print(sprint("<TD align=left><FONT SIZE=-1>")); 8970e96539fSCharles.Forsyth g.print(sprint("%s(%s)", g.thisone.page, g.thisone.mtype)); 8980e96539fSCharles.Forsyth g.print("</FONT></TD>\n"); 8990e96539fSCharles.Forsyth g.print(sprint("<TD align=right><FONT SIZE=-1><I>Rev: %s</I></FONT></TD></TR></TABLE>\n", 9000e96539fSCharles.Forsyth dt->text(dt->gmt(g.mtime)))); 9010e96539fSCharles.Forsyth } 9020e96539fSCharles.Forsyth} 9030e96539fSCharles.Forsyth 9040e96539fSCharles.Forsyth# 9050e96539fSCharles.Forsyth# Some font alternation macros are references to other man pages; 9060e96539fSCharles.Forsyth# detect them (second arg contains balanced parens) and make them into hot links. 9070e96539fSCharles.Forsyth# 9080e96539fSCharles.Forsythanchor(g: ref Global, f1, f2: string, argl: list of string) 9090e96539fSCharles.Forsyth{ 9100e96539fSCharles.Forsyth final := ""; 9110e96539fSCharles.Forsyth link := false; 9120e96539fSCharles.Forsyth if (len argl == 2) { 9130e96539fSCharles.Forsyth (s, e) := str->splitl(hd tl argl, ")"); 9140e96539fSCharles.Forsyth if (str->prefix("(", s) && e != nil) { 9150e96539fSCharles.Forsyth # emit href containing search for target first 9160e96539fSCharles.Forsyth # if numeric, do old style 9170e96539fSCharles.Forsyth link = true; 9180e96539fSCharles.Forsyth file := hd argl; 9190e96539fSCharles.Forsyth (chap, man) := split(httpunesc(file), '/'); 9200e96539fSCharles.Forsyth if (man == nil) { 9210e96539fSCharles.Forsyth # given no explicit chapter prefix, use current chapter 9220e96539fSCharles.Forsyth man = chap; 9230e96539fSCharles.Forsyth chap = g.thisone.chap; 9240e96539fSCharles.Forsyth } 9250e96539fSCharles.Forsyth mtype := s[1:]; 9260e96539fSCharles.Forsyth if (mtype == nil) 9270e96539fSCharles.Forsyth mtype = "-"; 9280e96539fSCharles.Forsyth (n, toks) := sys->tokenize(mtype, "."); # Fix section 10 9290e96539fSCharles.Forsyth if (n > 1) mtype = hd toks; 9300e96539fSCharles.Forsyth g.print(sprint("<A href=\"../%s/%s.html\">", mtype, fixlink(man))); 9310e96539fSCharles.Forsyth 9320e96539fSCharles.Forsyth # 9330e96539fSCharles.Forsyth # now generate the name the user sees, with terminal punctuation 9340e96539fSCharles.Forsyth # moved after the closing </A>. 9350e96539fSCharles.Forsyth # 9360e96539fSCharles.Forsyth if (len e > 1) 9370e96539fSCharles.Forsyth final = e[1:]; 9380e96539fSCharles.Forsyth argl = hd argl :: s + ")" :: nil; 9390e96539fSCharles.Forsyth } 9400e96539fSCharles.Forsyth } 9410e96539fSCharles.Forsyth altfont(g, f1, f2, argl, false); 9420e96539fSCharles.Forsyth if (link) { 9430e96539fSCharles.Forsyth g.print("</A>"); 9440e96539fSCharles.Forsyth font(g, f2, final :: nil); 9450e96539fSCharles.Forsyth } else 9460e96539fSCharles.Forsyth g.print("\n"); 9470e96539fSCharles.Forsyth} 9480e96539fSCharles.Forsyth 9490e96539fSCharles.Forsyth 9500e96539fSCharles.Forsyth# 9510e96539fSCharles.Forsyth# Fix up a link 9520e96539fSCharles.Forsyth# 9530e96539fSCharles.Forsyth 9540e96539fSCharles.Forsythfixlink(l: string): string 9550e96539fSCharles.Forsyth{ 9560e96539fSCharles.Forsyth ll := str->tolower(l); 9570e96539fSCharles.Forsyth if (ll == "copyright") ll = "1" + ll; 9580e96539fSCharles.Forsyth (a, b) := str->splitstrl(ll, "intro"); 9590e96539fSCharles.Forsyth if (len b == 5) ll = a + "0" + b; 9600e96539fSCharles.Forsyth return ll; 9610e96539fSCharles.Forsyth} 9620e96539fSCharles.Forsyth 9630e96539fSCharles.Forsyth 9640e96539fSCharles.Forsyth# 9650e96539fSCharles.Forsyth# output argl in font f 9660e96539fSCharles.Forsyth# 9670e96539fSCharles.Forsythfont(g: ref Global, f: string, argl: list of string) 9680e96539fSCharles.Forsyth{ 9690e96539fSCharles.Forsyth if (argl == nil) { 9700e96539fSCharles.Forsyth g.def_goobie = f; 9710e96539fSCharles.Forsyth return; 9720e96539fSCharles.Forsyth } 9730e96539fSCharles.Forsyth case f { 9740e96539fSCharles.Forsyth "L" => f = "TT"; 9750e96539fSCharles.Forsyth "R" => f = nil; 9760e96539fSCharles.Forsyth } 9770e96539fSCharles.Forsyth if (f != nil) # nil == default (typically Roman) 9780e96539fSCharles.Forsyth g.print(sprint("<%s>", f)); 9790e96539fSCharles.Forsyth printargs(g, argl); 9800e96539fSCharles.Forsyth if (f != nil) 9810e96539fSCharles.Forsyth g.print(sprint("</%s>", f)); 9820e96539fSCharles.Forsyth g.print("\n"); 9830e96539fSCharles.Forsyth g.prevfont = f; 9840e96539fSCharles.Forsyth} 9850e96539fSCharles.Forsyth 9860e96539fSCharles.Forsyth# 9870e96539fSCharles.Forsyth# output concatenated elements of argl, alternating between fonts f1 and f2 9880e96539fSCharles.Forsyth# 9890e96539fSCharles.Forsythaltfont(g: ref Global, f1, f2: string, argl: list of string, newline: int) 9900e96539fSCharles.Forsyth{ 9910e96539fSCharles.Forsyth reset_font(g); 9920e96539fSCharles.Forsyth if (argl == nil) { 9930e96539fSCharles.Forsyth g.def_goobie = f1; 9940e96539fSCharles.Forsyth return; 9950e96539fSCharles.Forsyth } 9960e96539fSCharles.Forsyth case f1 { 9970e96539fSCharles.Forsyth "L" => f1 = "TT"; 9980e96539fSCharles.Forsyth "R" => f1 = nil; 9990e96539fSCharles.Forsyth } 10000e96539fSCharles.Forsyth case f2 { 10010e96539fSCharles.Forsyth "L" => f2 = "TT"; 10020e96539fSCharles.Forsyth "R" => f2 = nil; 10030e96539fSCharles.Forsyth } 10040e96539fSCharles.Forsyth f := f1; 10050e96539fSCharles.Forsyth for (; argl != nil; argl = tl argl) { 10060e96539fSCharles.Forsyth if (f != nil) 10070e96539fSCharles.Forsyth g.print(sprint("<%s>%s</%s>", f, hd argl, f)); 10080e96539fSCharles.Forsyth else 10090e96539fSCharles.Forsyth g.print(hd argl); 10100e96539fSCharles.Forsyth if (f == f1) 10110e96539fSCharles.Forsyth f = f2; 10120e96539fSCharles.Forsyth else 10130e96539fSCharles.Forsyth f = f1; 10140e96539fSCharles.Forsyth } 10150e96539fSCharles.Forsyth if (newline) 10160e96539fSCharles.Forsyth g.print("\n"); 10170e96539fSCharles.Forsyth g.prevfont = f; 10180e96539fSCharles.Forsyth} 10190e96539fSCharles.Forsyth 10200e96539fSCharles.Forsyth# not yet implemented 10210e96539fSCharles.Forsythmap_font(nil: ref Global, nil: string) 10220e96539fSCharles.Forsyth{ 10230e96539fSCharles.Forsyth} 10240e96539fSCharles.Forsyth 10250e96539fSCharles.Forsythreset_font(g: ref Global) 10260e96539fSCharles.Forsyth{ 10270e96539fSCharles.Forsyth if (g.curfont != nil) { 10280e96539fSCharles.Forsyth g.print(sprint("</%s>", g.curfont)); 10290e96539fSCharles.Forsyth g.prevfont = g.curfont; 10300e96539fSCharles.Forsyth g.curfont = nil; 10310e96539fSCharles.Forsyth } 10320e96539fSCharles.Forsyth} 10330e96539fSCharles.Forsyth 10340e96539fSCharles.Forsythprintargs(g: ref Global, argl: list of string) 10350e96539fSCharles.Forsyth{ 10360e96539fSCharles.Forsyth for (; argl != nil; argl = tl argl) 10370e96539fSCharles.Forsyth if (tl argl != nil) 10380e96539fSCharles.Forsyth g.print(hd argl + " "); 10390e96539fSCharles.Forsyth else 10400e96539fSCharles.Forsyth g.print(hd argl); 10410e96539fSCharles.Forsyth} 10420e96539fSCharles.Forsyth 10430e96539fSCharles.Forsyth# any parameter can be nil 10440e96539fSCharles.Forsythaddhit(g: ref Global, chap, mtype, page: string) 10450e96539fSCharles.Forsyth{ 10460e96539fSCharles.Forsyth # g.print(sprint("Adding %s / %s (%s) . . .", chap, page, mtype)); # debug 10470e96539fSCharles.Forsyth # always keep a spare slot at the end 10480e96539fSCharles.Forsyth if (g.nhits >= len g.hits - 1) 10490e96539fSCharles.Forsyth g.hits = (array[len g.hits + 32] of Hit)[0:] = g.hits; 10500e96539fSCharles.Forsyth g.hits[g.nhits].glob = chap + " " + mtype + " " + page; 10510e96539fSCharles.Forsyth g.hits[g.nhits].chap = chap; 10520e96539fSCharles.Forsyth g.hits[g.nhits].mtype = mtype; 10530e96539fSCharles.Forsyth g.hits[g.nhits++].page = page; 10540e96539fSCharles.Forsyth} 10550e96539fSCharles.Forsyth 10560e96539fSCharles.ForsythGlobal.dobreak(g: self ref Global) 10570e96539fSCharles.Forsyth{ 10580e96539fSCharles.Forsyth if (! g.broken) { 10590e96539fSCharles.Forsyth g.broken = true; 10600e96539fSCharles.Forsyth g.print("<BR>\n"); 10610e96539fSCharles.Forsyth } 10620e96539fSCharles.Forsyth} 10630e96539fSCharles.Forsyth 10640e96539fSCharles.ForsythGlobal.print(g: self ref Global, s: string) 10650e96539fSCharles.Forsyth{ 10660e96539fSCharles.Forsyth g.bufio->g.bout.puts(s); 10670e96539fSCharles.Forsyth if (g.sop || g.broken) { 10680e96539fSCharles.Forsyth # first non-white space, non-HTML we print takes us past the start of the paragraph & line 10690e96539fSCharles.Forsyth # (or even white space, if we're in no-fill mode) 10700e96539fSCharles.Forsyth for (i := 0; i < len s; i++) { 10710e96539fSCharles.Forsyth case s[i] { 10720e96539fSCharles.Forsyth '<' => 10730e96539fSCharles.Forsyth while (++i < len s && s[i] != '>') 10740e96539fSCharles.Forsyth ; 10750e96539fSCharles.Forsyth continue; 10760e96539fSCharles.Forsyth ' ' or '\t' or '\n' => 10770e96539fSCharles.Forsyth if (g.fill) 10780e96539fSCharles.Forsyth continue; 10790e96539fSCharles.Forsyth } 10800e96539fSCharles.Forsyth g.sop = false; 10810e96539fSCharles.Forsyth g.broken = false; 10820e96539fSCharles.Forsyth break; 10830e96539fSCharles.Forsyth } 10840e96539fSCharles.Forsyth } 10850e96539fSCharles.Forsyth} 10860e96539fSCharles.Forsyth 10870e96539fSCharles.ForsythGlobal.softbr(g: self ref Global): string 10880e96539fSCharles.Forsyth{ 10890e96539fSCharles.Forsyth if (g.broken) 10900e96539fSCharles.Forsyth return nil; 10910e96539fSCharles.Forsyth g.broken = true; 10920e96539fSCharles.Forsyth return "<BR>"; 10930e96539fSCharles.Forsyth} 10940e96539fSCharles.Forsyth 10950e96539fSCharles.Forsyth# provide a paragraph marker, unless we're already at the start of a section 10960e96539fSCharles.ForsythGlobal.softp(g: self ref Global): string 10970e96539fSCharles.Forsyth{ 10980e96539fSCharles.Forsyth if (g.sop) 10990e96539fSCharles.Forsyth return nil; 11000e96539fSCharles.Forsyth else if (! g.ipd) 11010e96539fSCharles.Forsyth return "<BR>"; 11020e96539fSCharles.Forsyth if (g.fill) 11030e96539fSCharles.Forsyth return "<P>"; 11040e96539fSCharles.Forsyth else 11050e96539fSCharles.Forsyth return "<P style=\"white-space: pre\">"; 11060e96539fSCharles.Forsyth} 11070e96539fSCharles.Forsyth 11080e96539fSCharles.Forsyth# 110979aa5773SCharles.Forsyth# get (remainder of) a line 111079aa5773SCharles.Forsyth# 111179aa5773SCharles.Forsythgetline(g: ref Global): string 111279aa5773SCharles.Forsyth{ 111379aa5773SCharles.Forsyth line := ""; 111479aa5773SCharles.Forsyth while ((token := getnext(g)) != "\n") { 111579aa5773SCharles.Forsyth if (token == nil) 111679aa5773SCharles.Forsyth return line; 111779aa5773SCharles.Forsyth line += token; 111879aa5773SCharles.Forsyth } 111979aa5773SCharles.Forsyth return line+"\n"; 112079aa5773SCharles.Forsyth} 112179aa5773SCharles.Forsyth 112279aa5773SCharles.Forsyth# 11230e96539fSCharles.Forsyth# Get next logical character. Expand it with escapes. 11240e96539fSCharles.Forsyth# 11250e96539fSCharles.Forsythgetnext(g: ref Global): string 11260e96539fSCharles.Forsyth{ 11270e96539fSCharles.Forsyth iob := g.bufio; 11280e96539fSCharles.Forsyth Iobuf: import iob; 11290e96539fSCharles.Forsyth 11300e96539fSCharles.Forsyth font: string; 11310e96539fSCharles.Forsyth token: string; 11320e96539fSCharles.Forsyth bin := g.bin; 11330e96539fSCharles.Forsyth 11340e96539fSCharles.Forsyth g.sol = (g.lastc == '\n'); 11350e96539fSCharles.Forsyth 11360e96539fSCharles.Forsyth c := bin.getc(); 11370e96539fSCharles.Forsyth if (c < 0) 11380e96539fSCharles.Forsyth return nil; 11390e96539fSCharles.Forsyth g.lastc = c; 11400e96539fSCharles.Forsyth if (c >= Runeself) { 11410e96539fSCharles.Forsyth for (i := 0; i < len Entities; i++) 11420e96539fSCharles.Forsyth if (Entities[i].value == c) 11430e96539fSCharles.Forsyth return Entities[i].name; 11440e96539fSCharles.Forsyth return sprint("&#%d;", c); 11450e96539fSCharles.Forsyth } 11460e96539fSCharles.Forsyth case c { 11470e96539fSCharles.Forsyth '<' => 11480e96539fSCharles.Forsyth return "<"; 11490e96539fSCharles.Forsyth '>' => 11500e96539fSCharles.Forsyth return ">"; 11510e96539fSCharles.Forsyth '\\' => 11520e96539fSCharles.Forsyth c = bin.getc(); 11530e96539fSCharles.Forsyth if (c < 0) 11540e96539fSCharles.Forsyth return nil; 11550e96539fSCharles.Forsyth g.lastc = c; 11560e96539fSCharles.Forsyth case c { 11570e96539fSCharles.Forsyth 115867caa6f2SCharles.Forsyth ' ' => 115967caa6f2SCharles.Forsyth return " "; 116067caa6f2SCharles.Forsyth 11610e96539fSCharles.Forsyth # chars to ignore 11620e96539fSCharles.Forsyth '|' or '&' or '^' => 11630e96539fSCharles.Forsyth return getnext(g); 11640e96539fSCharles.Forsyth 11650e96539fSCharles.Forsyth # ignore arg 11660e96539fSCharles.Forsyth 'k' => 11670e96539fSCharles.Forsyth nil = bin.getc(); 11680e96539fSCharles.Forsyth return getnext(g); 11690e96539fSCharles.Forsyth 11700e96539fSCharles.Forsyth # defined strings 11710e96539fSCharles.Forsyth '*' => 11720e96539fSCharles.Forsyth case bin.getc() { 11730e96539fSCharles.Forsyth 'R' => 11740e96539fSCharles.Forsyth return "®"; 11750e96539fSCharles.Forsyth } 11760e96539fSCharles.Forsyth return getnext(g); 11770e96539fSCharles.Forsyth 11780e96539fSCharles.Forsyth # special chars 11790e96539fSCharles.Forsyth '(' => 11800e96539fSCharles.Forsyth token[0] = bin.getc(); 11810e96539fSCharles.Forsyth token[1] = bin.getc(); 11820e96539fSCharles.Forsyth for (i := 0; i < len tspec; i++) 11830e96539fSCharles.Forsyth if (token == tspec[i].name) 11840e96539fSCharles.Forsyth return tspec[i].value; 11850e96539fSCharles.Forsyth return "¿"; 11860e96539fSCharles.Forsyth 'c' => 11870e96539fSCharles.Forsyth c = bin.getc(); 11880e96539fSCharles.Forsyth if (c < 0) 11890e96539fSCharles.Forsyth return nil; 11900e96539fSCharles.Forsyth else if (c == '\n') { 11910e96539fSCharles.Forsyth g.lastc = c; 11920e96539fSCharles.Forsyth g.sol = true; 11930e96539fSCharles.Forsyth token[0] = bin.getc(); 11940e96539fSCharles.Forsyth return token; 11950e96539fSCharles.Forsyth } 11960e96539fSCharles.Forsyth # DEBUG: should there be a "return xxx" here? 11970e96539fSCharles.Forsyth 'e' => 11980e96539fSCharles.Forsyth return "\\"; 11990e96539fSCharles.Forsyth 'f' => 12000e96539fSCharles.Forsyth g.lastc = c = bin.getc(); 12010e96539fSCharles.Forsyth if (c < 0) 12020e96539fSCharles.Forsyth return nil; 12030e96539fSCharles.Forsyth case c { 12040e96539fSCharles.Forsyth '2' or 'I' => 12050e96539fSCharles.Forsyth font = "I"; 12060e96539fSCharles.Forsyth '3' or 'B' => 12070e96539fSCharles.Forsyth font = "B"; 12080e96539fSCharles.Forsyth '5' or 'L' => 12090e96539fSCharles.Forsyth font = "TT"; 12100e96539fSCharles.Forsyth 'P' => 12110e96539fSCharles.Forsyth font = g.prevfont; 12120e96539fSCharles.Forsyth * => # includes '1' and 'R' 12130e96539fSCharles.Forsyth font = nil; 12140e96539fSCharles.Forsyth } 12150e96539fSCharles.Forsyth# There are serious problems with this. We don't know the fonts properly at this stage. 12160e96539fSCharles.Forsyth# g.prevfont = g.curfont; 12170e96539fSCharles.Forsyth# g.curfont = font; 12180e96539fSCharles.Forsyth# if (g.prevfont != nil) 12190e96539fSCharles.Forsyth# token = sprint("</%s>", g.prevfont); 12200e96539fSCharles.Forsyth# if (g.curfont != nil) 12210e96539fSCharles.Forsyth# token += sprint("<%s>", g.curfont); 12220e96539fSCharles.Forsyth if (token == nil) 122379aa5773SCharles.Forsyth return "<i></i>"; # looks odd but it avoids inserting a space in <pre> text 12240e96539fSCharles.Forsyth return token; 12250e96539fSCharles.Forsyth 's' => 12260e96539fSCharles.Forsyth sign := '+'; 12270e96539fSCharles.Forsyth size := 0; 12280e96539fSCharles.Forsyth relative := false; 12290e96539fSCharles.Forsyth getsize: 12300e96539fSCharles.Forsyth for (;;) { 12310e96539fSCharles.Forsyth c = bin.getc(); 12320e96539fSCharles.Forsyth if (c < 0) 12330e96539fSCharles.Forsyth return nil; 12340e96539fSCharles.Forsyth case c { 12350e96539fSCharles.Forsyth '+' => 12360e96539fSCharles.Forsyth relative = true; 12370e96539fSCharles.Forsyth '-' => 12380e96539fSCharles.Forsyth sign = '-'; 12390e96539fSCharles.Forsyth relative = true; 12400e96539fSCharles.Forsyth '0' to '9' => 12410e96539fSCharles.Forsyth size = size * 10 + (c - '0'); 12420e96539fSCharles.Forsyth * => 12430e96539fSCharles.Forsyth bin.ungetc(); 12440e96539fSCharles.Forsyth break getsize; 12450e96539fSCharles.Forsyth } 12460e96539fSCharles.Forsyth g.lastc = c; 12470e96539fSCharles.Forsyth } 12480e96539fSCharles.Forsyth if (size == 0) 12490e96539fSCharles.Forsyth token = "</FONT>"; 12500e96539fSCharles.Forsyth else if (relative) 12510e96539fSCharles.Forsyth token = sprint("<FONT SIZE=%c%d>", sign, size); 12520e96539fSCharles.Forsyth else 12530e96539fSCharles.Forsyth token = sprint("<FONT SIZE=%d>", size); 12540e96539fSCharles.Forsyth return token; 12550e96539fSCharles.Forsyth } 12560e96539fSCharles.Forsyth } 12570e96539fSCharles.Forsyth token[0] = c; 12580e96539fSCharles.Forsyth return token; 12590e96539fSCharles.Forsyth} 12600e96539fSCharles.Forsyth 12610e96539fSCharles.Forsyth# 12620e96539fSCharles.Forsyth# Return strings before and after the left-most instance of separator; 12630e96539fSCharles.Forsyth# (s, nil) if no match or separator is last char in s. 12640e96539fSCharles.Forsyth# 12650e96539fSCharles.Forsythsplit(s: string, sep: int): (string, string) 12660e96539fSCharles.Forsyth{ 12670e96539fSCharles.Forsyth for (i := 0; i < len s; i++) 12680e96539fSCharles.Forsyth if (s[i] == sep) 12690e96539fSCharles.Forsyth return (s[:i], s[i+1:]); # s[len s:] is a valid slice, with value == nil 12700e96539fSCharles.Forsyth return (s, nil); 12710e96539fSCharles.Forsyth} 12720e96539fSCharles.Forsyth 12730e96539fSCharles.ForsythGlobal_init(): ref Global 12740e96539fSCharles.Forsyth{ 12750e96539fSCharles.Forsyth g := ref Global; 12760e96539fSCharles.Forsyth g.bufio = load Bufio Bufio->PATH; 12770e96539fSCharles.Forsyth g.chaps = array[20] of Chaps; 12780e96539fSCharles.Forsyth g.types = array[20] of Types; 12790e96539fSCharles.Forsyth g.mantitle = ""; 12800e96539fSCharles.Forsyth g.href.title = g.mantitle; # ?? 12810e96539fSCharles.Forsyth g.mtime = 0; 12820e96539fSCharles.Forsyth g.nhits = 0; 12830e96539fSCharles.Forsyth g.oldstyle.names = false; 12840e96539fSCharles.Forsyth g.oldstyle.fmt = false; 12850e96539fSCharles.Forsyth g.topname = "System"; 12860e96539fSCharles.Forsyth g.list_type = Lnone; 12870e96539fSCharles.Forsyth g.def_sm = 0; 12880e96539fSCharles.Forsyth g.hangingdt = 0; 12890e96539fSCharles.Forsyth g.indents = 0; 12900e96539fSCharles.Forsyth g.sop = true; 12910e96539fSCharles.Forsyth g.broken = true; 12920e96539fSCharles.Forsyth g.ipd = true; 12930e96539fSCharles.Forsyth g.fill = true; 12940e96539fSCharles.Forsyth g.example = false; 12950e96539fSCharles.Forsyth g.pre = false; 12960e96539fSCharles.Forsyth g.lastc = '\n'; 12970e96539fSCharles.Forsyth return g; 12980e96539fSCharles.Forsyth} 12990e96539fSCharles.Forsyth 13000e96539fSCharles.ForsythGlobal.mk_href_chap(g: self ref Global, chap: string) 13010e96539fSCharles.Forsyth{ 13020e96539fSCharles.Forsyth if (chap != nil) 13030e96539fSCharles.Forsyth g.href.chap = sprint("<A href=\"%s/%s?man=*\"><B>%s</B></A>", g.mandir, chap, chap); 13040e96539fSCharles.Forsyth} 13050e96539fSCharles.Forsyth 13060e96539fSCharles.ForsythGlobal.mk_href_man(g: self ref Global, man: string, oldstyle: int) 13070e96539fSCharles.Forsyth{ 13080e96539fSCharles.Forsyth rman := man; 13090e96539fSCharles.Forsyth if (oldstyle) 13100e96539fSCharles.Forsyth rman = str->tolower(man); # compensate for tradition of putting titles in all CAPS 13110e96539fSCharles.Forsyth g.href.man = sprint("<A href=\"%s?man=%s\"><B>%s</B></A>", g.mandir, rman, man); 13120e96539fSCharles.Forsyth} 13130e96539fSCharles.Forsyth 13140e96539fSCharles.ForsythGlobal.mk_href_mtype(g: self ref Global, chap, mtype: string) 13150e96539fSCharles.Forsyth{ 13160e96539fSCharles.Forsyth g.href.mtype = sprint("<A href=\"%s/%s/%s\"><B>%s</B></A>", g.mandir, chap, mtype, mtype); 13170e96539fSCharles.Forsyth} 13180e96539fSCharles.Forsyth 13190e96539fSCharles.Forsyth# We assume that anything >= Runeself is already in UTF. 13200e96539fSCharles.Forsyth# 13210e96539fSCharles.Forsythhttpunesc(s: string): string 13220e96539fSCharles.Forsyth{ 13230e96539fSCharles.Forsyth t := ""; 13240e96539fSCharles.Forsyth for (i := 0; i < len s; i++) { 13250e96539fSCharles.Forsyth c := s[i]; 13260e96539fSCharles.Forsyth if (c == '&' && i + 1 < len s) { 13270e96539fSCharles.Forsyth (char, rem) := str->splitl(s[i+1:], ";"); 13280e96539fSCharles.Forsyth if (rem == nil) 13290e96539fSCharles.Forsyth break; # require the terminating ';' 13300e96539fSCharles.Forsyth if (char == nil) 13310e96539fSCharles.Forsyth continue; 13320e96539fSCharles.Forsyth if (char[0] == '#' && len char > 1) { 13330e96539fSCharles.Forsyth c = int char[1:]; 13340e96539fSCharles.Forsyth i += len char; 13350e96539fSCharles.Forsyth if (c < 256 && c >= 161) { 13360e96539fSCharles.Forsyth t[len t] = Entities[c-161].value; 13370e96539fSCharles.Forsyth continue; 13380e96539fSCharles.Forsyth } 13390e96539fSCharles.Forsyth } else { 13400e96539fSCharles.Forsyth for (j := 0; j < len Entities; j++) 13410e96539fSCharles.Forsyth if (Entities[j].name == char) 13420e96539fSCharles.Forsyth break; 13430e96539fSCharles.Forsyth if (j < len Entities) { 13440e96539fSCharles.Forsyth i += len char; 13450e96539fSCharles.Forsyth t[len t] = Entities[j].value; 13460e96539fSCharles.Forsyth continue; 13470e96539fSCharles.Forsyth } 13480e96539fSCharles.Forsyth } 13490e96539fSCharles.Forsyth } 13500e96539fSCharles.Forsyth t[len t] = c; 13510e96539fSCharles.Forsyth } 13520e96539fSCharles.Forsyth return t; 13530e96539fSCharles.Forsyth} 13540e96539fSCharles.Forsyth 13550e96539fSCharles.Forsyth 13560e96539fSCharles.Forsyth 13570e96539fSCharles.Forsythtitle(g: ref Global, t: string, search: int) 13580e96539fSCharles.Forsyth{ 13590e96539fSCharles.Forsyth if(search) 13600e96539fSCharles.Forsyth ; # not yet used 136130dcb98cSCharles.Forsyth g.print(header+"\n"); 13620e96539fSCharles.Forsyth g.print(sprint("<TITLE>Inferno's %s</TITLE>\n", demark(t))); 13630e96539fSCharles.Forsyth g.print("</HEAD>\n"); 1364*7cdb1d14SCharles.Forsyth g.print("<BODY>"+initial+"\n"); 13650e96539fSCharles.Forsyth 13660e96539fSCharles.Forsyth} 1367