12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639 |
- #include <u.h>
- #include <libc.h>
- #include <ctype.h>
- #include <bio.h>
- enum
- {
- SSIZE = 10,
- Maxnh= 8, /* highest NH level */
- HH= 4, /* heading level used for SH and NH */
- Maxmstack= 10, /* deepest macro/string nesting */
- Narg= 20, /* max args to a macro */
- Maxsstack= 5, /* deepest nesting of .so's */
- Nline= 1024,
- Maxget= 10,
- Maxif = 20,
- Maxfsp = 100,
- /* list types */
- Lordered = 1,
- Lunordered,
- Ldef,
- Lother,
- };
- char *delim = "$$";
- char *basename;
- char *title;
- int eqnmode;
- int quiet;
- float indent; /* from .in */
- Biobuf bout;
- int isup;
- int isdown;
- int debug;
- int nh[Maxnh];
- int ifwastrue[Maxif];
- int list, listnum, example;
- int hangingau, hangingdt, hanginghead, hangingcenter;
- int indirective, paragraph, sol, titleseen, ignore_nl, weBref;
- void dohangingcenter(void);
- typedef struct Goobie Goobie;
- typedef struct Goobieif Goobieif;
- struct Goobie
- {
- char *name;
- void (*f)(int, char**);
- };
- typedef void F(int, char**);
- typedef void Fif(char*, char*);
- struct Goobieif
- {
- char *name;
- Fif *f;
- };
- /* if, ie */
- Fif g_as, g_ds, g_el, g_ie, g_if;
- Goobieif gtabif[] = {
- { "as", g_as },
- { "ds", g_ds },
- { "if", g_if },
- { "ie", g_ie },
- { "el", g_el },
- { nil, nil },
- };
- /* pseudo ops */
- F g_notyet, g_ignore, g_hrule, g_startgif;
- /* ms macros */
- F g_AU, g_B, g_BI, g_CW, g_I, g_IP, g_LP, g_PP, g_SH, g_NH;
- F g_P1, g_P2, g_TL, g_R, g_AB, g_AE, g_EQ, g_TS, g_TE, g_FS, g_FE;
- F g_PY, g_IH, g_MH, g_HO, g_BX, g_QS, g_QE, g_RS, g_RE;
- /* pictures macro */
- F g_BP;
- /* real troff */
- F g_br, g_ft, g_sp, g_de, g_lf, g_so, g_rm, g_in;
- F g_nr, g_ig, g_RT, g_BS, g_BE, g_LB, g_ta;
- /* macros to include ML in output */
- F g__H, g__T;
- Goobie gtab[] =
- {
- { "_T", g__T, },
- { "_H", g__H, },
- { "1C", g_ignore, },
- { "2C", g_ignore, },
- { "AB", g_AB, },
- { "AE", g_AE, },
- { "AI", g_ignore, },
- { "AU", g_AU, },
- { "B", g_B, },
- { "B1", g_hrule, },
- { "B2", g_hrule, },
- { "BI", g_BI, },
- { "BP", g_BP, },
- { "BT", g_ignore, },
- { "BX", g_BX, },
- { "CW", g_CW, },
- { "CT", g_ignore, },
- { "DA", g_ignore, },
- { "DE", g_P2, },
- { "DS", g_P1, },
- { "EG", g_ignore, },
- { "EN", g_ignore, },
- { "EQ", g_startgif, },
- { "FE", g_FE, },
- { "FP", g_ignore, },
- { "FS", g_FS, },
- { "HO", g_HO, },
- { "I", g_I, },
- { "IH", g_IH, },
- { "IM", g_ignore, },
- { "IP", g_IP, },
- { "KE", g_ignore, },
- { "KF", g_ignore, },
- { "KS", g_ignore, },
- { "LG", g_ignore, },
- { "LP", g_LP, },
- { "LT", g_ignore, },
- { "MF", g_ignore, },
- { "MH", g_MH, },
- { "MR", g_ignore, },
- { "ND", g_ignore, },
- { "NH", g_NH, },
- { "NL", g_ignore, },
- { "P1", g_P1, },
- { "P2", g_P2, },
- { "PE", g_ignore, },
- { "PF", g_ignore, },
- { "PP", g_PP, },
- { "PS", g_startgif, },
- { "PY", g_PY, },
- { "QE", g_QE, },
- { "QP", g_QS, },
- { "QS", g_QS, },
- { "R", g_R, },
- { "RE", g_RE, },
- { "RP", g_ignore, },
- { "RS", g_RS, },
- { "SG", g_ignore, },
- { "SH", g_SH, },
- { "SM", g_ignore, },
- { "TA", g_ignore, },
- { "TE", g_ignore, },
- { "TH", g_TL, },
- { "TL", g_TL, },
- { "TM", g_ignore, },
- { "TR", g_ignore, },
- { "TS", g_startgif, },
- { "UL", g_I, },
- { "UX", g_ignore, },
- { "WH", g_ignore, },
- { "RT", g_RT, },
- { "br", g_br, },
- { "ti", g_br, },
- { "nf", g_P1, },
- { "fi", g_P2, },
- { "ft", g_ft, },
- { "sp", g_sp, },
- { "rm", g_rm, },
- { "de", g_de, },
- { "am", g_de, },
- { "lf", g_lf, },
- { "so", g_so, },
- { "ps", g_ignore },
- { "vs", g_ignore },
- { "nr", g_nr },
- { "in", g_in },
- { "ne", g_ignore },
- { "ig", g_ig },
- { "BS", g_BS },
- { "BE", g_BE },
- { "LB", g_LB },
- { nil, nil },
- };
- typedef struct Entity Entity;
- struct Entity
- {
- char *name;
- int value;
- };
- Entity entity[] =
- {
- { "&#SPACE;", L' ', },
- { "&#RS;", L'\n', },
- { "&#RE;", L'\r', },
- { """, L'"', },
- { "Æ", L'Æ', },
- { "Á", L'Á', },
- { "Â", L'Â', },
- { "À", L'À', },
- { "Å", L'Å', },
- { "Ã", L'Ã', },
- { "Ä", L'Ä', },
- { "Ç", L'Ç', },
- { "Ð", L'Ð', },
- { "É", L'É', },
- { "Ê", L'Ê', },
- { "È", L'È', },
- { "Ë", L'Ë', },
- { "Í", L'Í', },
- { "Î", L'Î', },
- { "Ì", L'Ì', },
- { "Ï", L'Ï', },
- { "Ñ", L'Ñ', },
- { "Ó", L'Ó', },
- { "Ô", L'Ô', },
- { "Ò", L'Ò', },
- { "Ø", L'Ø', },
- { "Õ", L'Õ', },
- { "Ö", L'Ö', },
- { "Þ", L'Þ', },
- { "Ú", L'Ú', },
- { "Û", L'Û', },
- { "Ù", L'Ù', },
- { "Ü", L'Ü', },
- { "Ý", L'Ý', },
- { "á", L'á', },
- { "â", L'â', },
- { "æ", L'æ', },
- { "à", L'à', },
- { "&", L'&', },
- { "å", L'å', },
- { "ã", L'ã', },
- { "ä", L'ä', },
- { "ç", L'ç', },
- { "é", L'é', },
- { "ê", L'ê', },
- { "è", L'è', },
- { "ð", L'ð', },
- { "ë", L'ë', },
- { ">", L'>', },
- { "í", L'í', },
- { "î", L'î', },
- { "ì", L'ì', },
- { "ï", L'ï', },
- { "<", L'<', },
- { "ñ", L'ñ', },
- { "ó", L'ó', },
- { "ô", L'ô', },
- { "ò", L'ò', },
- { "ø", L'ø', },
- { "õ", L'õ', },
- { "ö", L'ö', },
- { "ß", L'ß', },
- { "þ", L'þ', },
- { "ú", L'ú', },
- { "û", L'û', },
- { "ù", L'ù', },
- { "ü", L'ü', },
- { "ý", L'ý', },
- { "ÿ", L'ÿ', },
- { "¡", L'¡', },
- { "¢", L'¢', },
- { "£", L'£', },
- { "¤", L'¤', },
- { "¥", L'¥', },
- { "¦", L'¦', },
- { "§", L'§', },
- { "¨", L'¨', },
- { "©", L'©', },
- { "ª", L'ª', },
- { "«", L'«', },
- { "¬", L'¬', },
- { "­", L'', },
- { "®", L'®', },
- { "¯", L'¯', },
- { "°", L'°', },
- { "±", L'±', },
- { "²", L'²', },
- { "³", L'³', },
- { "´", L'´', },
- { "µ", L'µ', },
- { "¶", L'¶', },
- { "·", L'·', },
- { "¸", L'¸', },
- { "¹", L'¹', },
- { "º", L'º', },
- { "»", L'»', },
- { "¼", L'¼', },
- { "½", L'½', },
- { "¾", L'¾', },
- { "¿", L'¿', },
- { "*", L'•', },
- { "¤", L'□', },
- { "º", L'◊', },
- { "(tm)", L'™', },
- {"Α", L'Α',},
- {"Β", L'Β',},
- {"Γ", L'Γ',},
- {"Δ", L'Δ',},
- {"Ε", L'Ε',},
- {"Ζ", L'Ζ',},
- {"Η", L'Η',},
- {"Θ", L'Θ',},
- {"Ι", L'Ι',},
- {"Κ", L'Κ',},
- {"Λ", L'Λ',},
- {"Μ", L'Μ',},
- {"Ν", L'Ν',},
- {"Ξ", L'Ξ',},
- {"Ο", L'Ο',},
- {"Π", L'Π',},
- {"Ρ", L'Ρ',},
- {"΢", L'',},
- {"Σ", L'Σ',},
- {"Τ", L'Τ',},
- {"Υ", L'Υ',},
- {"Φ", L'Φ',},
- {"Χ", L'Χ',},
- {"Ψ", L'Ψ',},
- {"Ω", L'Ω',},
- {"α", L'α',},
- {"β", L'β',},
- {"γ", L'γ',},
- {"δ", L'δ',},
- {"ε", L'ε',},
- {"ζ", L'ζ',},
- {"η", L'η',},
- {"θ", L'θ',},
- {"ι", L'ι',},
- {"κ", L'κ',},
- {"λ", L'λ',},
- {"μ", L'μ',},
- {"ν", L'ν',},
- {"ξ", L'ξ',},
- {"ο", L'ο',},
- {"π", L'π',},
- {"ρ", L'ρ',},
- {"ς", L'ς',},
- {"σ", L'σ',},
- {"τ", L'τ',},
- {"υ", L'υ',},
- {"φ", L'φ',},
- {"χ", L'χ',},
- {"ψ", L'ψ',},
- {"ω", L'ω',},
- { "<-", L'←', },
- { "^", L'↑', },
- { "->", L'→', },
- { "v", L'↓', },
- { "!=", L'≠', },
- { "<=", L'≤', },
- { "...", L'⋯', },
- {"∈", L'∈', },
- {"–", L'–', },
- {"—", L'—', },
- { "CYRILLIC XYZZY", L'й', },
- { "CYRILLIC XYZZY", L'ъ', },
- { "CYRILLIC Y", L'ь', },
- { "CYRILLIC YA", L'я', },
- { "CYRILLIC YA", L'ё', },
- { "¿", L'ℱ', },
- { nil, 0 },
- };
- typedef struct Troffspec Troffspec;
- struct Troffspec
- {
- char *name;
- char *value;
- };
- Troffspec tspec[] =
- {
- { "A*", "Å", },
- { "o\"", "ö", },
- { "ff", "ff", },
- { "fi", "fi", },
- { "fl", "fl", },
- { "Fi", "ffi", },
- { "ru", "_", },
- { "em", "­", },
- { "14", "¼", },
- { "12", "½", },
- { "co", "©", },
- { "de", "°", },
- { "dg", "¡", },
- { "fm", "´", },
- { "rg", "®", },
- { "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", "DEATHSTAR", },
- { "sc", "§", },
- { "dd", "++", },
- { "lh", "<=", },
- { "rh", "=>", },
- { "lt", "(", },
- { "rt", ")", },
- { "lc", "|", },
- { "rc", "|", },
- { "lb", "(", },
- { "rb", ")", },
- { "lf", "|", },
- { "rf", "|", },
- { "lk", "|", },
- { "rk", "|", },
- { "bv", "|", },
- { "ts", "s", },
- { "br", "|", },
- { "or", "|", },
- { "ul", "_", },
- { "rn", " ", },
- { "**", "*", },
- { "tm", "™", },
- { nil, nil, },
- };
- typedef struct Font Font;
- struct Font
- {
- char *start;
- char *end;
- };
- Font bfont = { "<B>", "</B>" };
- Font ifont = { "<I>", "</I>" };
- Font bifont = { "<B><I>", "</I></B>" };
- Font cwfont = { "<TT>", "</TT>" };
- Font *fstack[Maxfsp];
- int fsp = -1;
- typedef struct String String;
- struct String
- {
- String *next;
- char *name;
- char *val;
- };
- String *numregs, *strings;
- char *strstack[Maxmstack];
- char *mustfree[Maxmstack];
- int strsp = -1;
- int elsetop = -1;
- typedef struct Mstack Mstack;
- struct Mstack
- {
- char *ptr;
- char *argv[Narg+1];
- };
- String *macros;
- Mstack mstack[Maxmstack];
- int msp = -1;
- typedef struct Srcstack Srcstack;
- struct Srcstack
- {
- char filename[256];
- int fd;
- int lno;
- int rlno;
- Biobuf in;
- };
- Srcstack sstack[Maxsstack];
- Srcstack *ssp = &sstack[-1];
- char token[128];
- void closel(void);
- void closefont(void);
- void*
- emalloc(uint n)
- {
- void *p;
- p = mallocz(n, 1);
- if(p == nil){
- fprint(2, "ms2html: malloc failed: %r\n");
- exits("malloc");
- }
- return p;
- }
- /* define a string variable */
- void
- dsnr(char *name, char *val, String **l)
- {
- String *s;
- for(s = *l; s != nil; s = *l){
- if(strcmp(s->name, name) == 0)
- break;
- l = &s->next;
- }
- if(s == nil){
- s = emalloc(sizeof(String));
- *l = s;
- s->name = strdup(name);
- } else
- free(s->val);
- s->val = strdup(val);
- }
- void
- ds(char *name, char *val)
- {
- dsnr(name, val, &strings);
- }
- /* look up a defined string */
- char*
- getds(char *name)
- {
- String *s;
- for(s = strings; s != nil; s = s->next)
- if(strcmp(name, s->name) == 0)
- break;
- if(s != nil)
- return s->val;
- return "";
- }
- char *
- getnr(char *name)
- {
- String *s;
- for(s = numregs; s != nil; s = s->next)
- if(strcmp(name, s->name) == 0)
- break;
- if(s != nil)
- return s->val;
- return "0";
- }
- void
- pushstr(char *p)
- {
- if(p == nil)
- return;
- if(strsp >= Maxmstack - 1)
- return;
- strstack[++strsp] = p;
- }
- /* lookup a defined macro */
- char*
- getmacro(char *name)
- {
- String *s;
- for(s = macros; s != nil; s = s->next)
- if(strcmp(name, s->name) == 0)
- return s->val;
- return nil;
- }
- enum
- {
- Dstring,
- Macro,
- Input,
- };
- int lastsrc;
- void
- pushsrc(char *name)
- {
- Dir *d;
- int fd;
- if(ssp == &sstack[Maxsstack-1]){
- fprint(2, "ms2html: .so's too deep\n");
- return;
- }
- d = nil;
- if(name == nil){
- d = dirfstat(0);
- if(d == nil){
- fprint(2, "ms2html: can't stat %s: %r\n", name);
- return;
- }
- name = d->name;
- fd = 0;
- } else {
- fd = open(name, OREAD);
- if(fd < 0){
- fprint(2, "ms2html: can't open %s: %r\n", name);
- return;
- }
- }
- ssp++;
- ssp->fd = fd;
- Binit(&ssp->in, fd, OREAD);
- snprint(ssp->filename, sizeof(ssp->filename), "%s", name);
- ssp->lno = ssp->rlno = 1;
- free(d);
- }
- /* get next logical byte. from stdin or a defined string */
- int
- getrune(void)
- {
- int i;
- Rune r;
- int c;
- Mstack *m;
- while(strsp >= 0){
- i = chartorune(&r, strstack[strsp]);
- if(r != 0){
- strstack[strsp] += i;
- lastsrc = Dstring;
- return r;
- }
- if (mustfree[strsp]) {
- free(mustfree[strsp]);
- mustfree[strsp] = nil;
- }
- strsp--;
- }
- while(msp >= 0){
- m = &mstack[msp];
- i = chartorune(&r, m->ptr);
- if(r != 0){
- m->ptr += i;
- lastsrc = Macro;
- return r;
- }
- for(i = 0; m->argv[i] != nil; i++)
- free(m->argv[i]);
- msp--;
- }
- lastsrc = Input;
- for(;;) {
- if(ssp < sstack)
- return -1;
- c = Bgetrune(&ssp->in);
- if(c >= 0){
- r = c;
- break;
- }
- close(ssp->fd);
- ssp--;
- }
- return r;
- }
- void
- ungetrune(void)
- {
- switch(lastsrc){
- case Dstring:
- if(strsp >= 0)
- strstack[strsp]--;
- break;
- case Macro:
- if(msp >= 0)
- mstack[msp].ptr--;
- break;
- case Input:
- if(ssp >= sstack)
- Bungetrune(&ssp->in);
- break;
- }
- }
- int vert;
- char*
- changefont(Font *f)
- {
- token[0] = 0;
- if(fsp == Maxfsp)
- return token;
- if(fsp >= 0 && fstack[fsp])
- strcpy(token, fstack[fsp]->end);
- if(f != nil)
- strcat(token, f->start);
- fstack[++fsp] = f;
- return token;
- }
- char*
- changebackfont(void)
- {
- token[0] = 0;
- if(fsp >= 0){
- if(fstack[fsp])
- strcpy(token, fstack[fsp]->end);
- fsp--;
- }
- if(fsp >= 0 && fstack[fsp])
- strcat(token, fstack[fsp]->start);
- return token;
- }
- char*
- changesize(int amount)
- {
- static int curamount;
- static char buf[200];
- int i;
- buf[0] = 0;
- if (curamount >= 0)
- for (i = 0; i < curamount; i++)
- strcat(buf, "</big>");
- else
- for (i = 0; i < -curamount; i++)
- strcat(buf, "</small>");
- curamount = 0;
- if (amount >= 0)
- for (i = 0; i < amount; i++)
- strcat(buf, "<big>");
- else
- for (i = 0; i < -amount; i++)
- strcat(buf, "<small>");
- curamount = amount;
- return buf;
- }
- /* get next logical character. expand it with escapes */
- char*
- getnext(void)
- {
- int r;
- Entity *e;
- Troffspec *t;
- Rune R;
- char str[4];
- static char buf[8];
- r = getrune();
- if(r < 0)
- return nil;
- if(r > 128 || r == '<' || r == '>'){
- for(e = entity; e->name; e++)
- if(e->value == r)
- return e->name;
- sprint(buf, "&#%d;", r);
- return buf;
- }
- if (r == delim[eqnmode]){
- if (eqnmode == 0){
- eqnmode = 1;
- return changefont(&ifont);
- }
- eqnmode = 0;
- return changebackfont();
- }
- switch(r){
- case '\\':
- r = getrune();
- if(r < 0)
- return nil;
- switch(r){
- case ' ':
- return " ";
- /* chars to ignore */
- case '&':
- case '|':
- case '%':
- return "";
- /* small space in troff, nothing in nroff */
- case '^':
- return getnext();
- /* ignore arg */
- case 'k':
- getrune();
- return getnext();
- /* comment */
- case '"':
- while(getrune() != '\n')
- ;
- return "\n";
- /* ignore line */
- case '!':
- while(getrune() != '\n')
- ;
- ungetrune();
- return getnext();
- /* defined strings */
- case '*':
- r = getrune();
- if(r == '('){
- str[0] = getrune();
- str[1] = getrune();
- str[2] = 0;
- } else {
- str[0] = r;
- str[1] = 0;
- }
- pushstr(getds(str));
- return getnext();
- /* macro args */
- case '$':
- r = getrune();
- if(r < '1' || r > '9'){
- token[0] = '\\';
- token[1] = '$';
- token[2] = r;
- token[3] = 0;
- return token;
- }
- r -= '0';
- if(msp >= 0)
- pushstr(mstack[msp].argv[r]);
- return getnext();
- /* special chars */
- case '(':
- token[0] = getrune();
- token[1] = getrune();
- token[2] = 0;
- for(t = tspec; t->name; t++)
- if(strcmp(token, t->name) == 0)
- return t->value;
- return "¿";
- /* ignore immediately following newline */
- case 'c':
- r = getrune();
- if (r == '\n') {
- sol = ignore_nl = 1;
- if (indirective)
- break;
- }
- else
- ungetrune();
- return getnext();
- /* escape backslash */
- case 'e':
- return "\\";
- /* font change */
- case 'f':
- r = getrune();
- switch(r){
- case '(':
- str[0] = getrune();
- str[1] = getrune();
- str[2] = 0;
- token[0] = 0;
- if(strcmp("BI", str) == 0)
- return changefont(&bifont);
- else if(strcmp("CW", str) == 0)
- return changefont(&cwfont);
- else
- return changefont(nil);
- case '3':
- case 'B':
- return changefont(&bfont);
- case '2':
- case 'I':
- return changefont(&ifont);
- case '4':
- return changefont(&bifont);
- case '5':
- return changefont(&cwfont);
- case 'P':
- return changebackfont();
- case 'R':
- default:
- return changefont(nil);
- }
- /* number register */
- case 'n':
- r = getrune();
- if (r == '(') /*)*/ {
- r = getrune();
- if (r < 0)
- return nil;
- str[0] = r;
- r = getrune();
- if (r < 0)
- return nil;
- str[1] = r;
- str[2] = 0;
- }
- else {
- str[0] = r;
- str[1] = 0;
- }
- pushstr(getnr(str));
- return getnext();
- /* font size */
- case 's':
- r = getrune();
- switch(r){
- case '0':
- return changesize(0);
- case '-':
- r = getrune();
- if (!isdigit(r))
- return getnext();
- return changesize(-(r - '0'));
- case '+':
- r = getrune();
- if (!isdigit(r))
- return getnext();
- return changesize(r - '0');
- }
- return getnext();
- /* vertical movement */
- case 'v':
- r = getrune();
- if(r != '\''){
- ungetrune();
- return getnext();
- }
- r = getrune();
- if(r != '-')
- vert--;
- else
- vert++;
- while(r != '\'' && r != '\n')
- r = getrune();
- if(r != '\'')
- ungetrune();
-
- if(vert > 0)
- return "^";
- return getnext();
-
- /* horizontal line */
- case 'l':
- r = getrune();
- if(r != '\''){
- ungetrune();
- return "<HR>";
- }
- while(getrune() != '\'')
- ;
- return "<HR>";
- /* character height and slant */
- case 'S':
- case 'H':
- r = getrune();
- if(r != '\''){
- ungetrune();
- return "<HR>";
- }
- while(getrune() != '\'')
- ;
- return getnext();
- /* digit-width space */
- case '0':
- return " ";
- /*for .if, .ie, .el */
- case '{':
- return "\\{"; /*}*/
- case '}':
- return "";
- /* up and down */
- case 'u':
- if (isdown) {
- isdown = 0;
- return "</sub>";
- }
- isup = 1;
- return "<sup>";
- case 'd':
- if (isup) {
- isup = 0;
- return "</sup>";
- }
- isdown = 1;
- return "<sub>";
- }
- break;
- case '&':
- if(msp >= 0 || strsp >= 0)
- return "&";
- return "&";
- case '<':
- if(msp >= 0 || strsp >= 0)
- return "<";
- return "<";
- case '>':
- if(msp >= 0 || strsp >= 0)
- return ">";
- return ">";
- }
- if (r < Runeself) {
- token[0] = r;
- token[1] = 0;
- }
- else {
- R = r;
- token[runetochar(token,&R)] = 0;
- }
- return token;
- }
- /* if arg0 is set, read up to (and expand) to the next whitespace, else to the end of line */
- char*
- copyline(char *p, char *e, int arg0)
- {
- int c;
- Rune r;
- char *p1;
- while((c = getrune()) == ' ' || c == '\t')
- ;
- for(indirective = 1; p < e; c = getrune()) {
- if (c < 0)
- goto done;
- switch(c) {
- case '\\':
- break;
- case '\n':
- if (arg0)
- ungetrune();
- goto done;
- case ' ':
- case '\t':
- if (arg0)
- goto done;
- default:
- r = c;
- p += runetochar(p,&r);
- continue;
- }
- ungetrune();
- p1 = getnext();
- if (p1 == nil)
- goto done;
- if (*p1 == '\n') {
- if (arg0)
- ungetrune();
- break;
- }
- while((*p = *p1++) && p < e)
- p++;
- }
- done:
- indirective = 0;
- *p++ = 0;
- return p;
- }
- char*
- copyarg(char *p, char *e, int *nullarg)
- {
- int c, quoted, last;
- Rune r;
- *nullarg = 0;
- quoted = 0;
- do{
- c = getrune();
- } while(c == ' ' || c == '\t');
- if(c == '"'){
- quoted = 1;
- *nullarg = 1;
- c = getrune();
- }
- if(c == '\n')
- goto done;
- last = 0;
- for(; p < e; c = getrune()) {
- if (c < 0)
- break;
- switch(c) {
- case '\n':
- ungetrune();
- goto done;
- case '\\':
- r = c;
- p += runetochar(p,&r);
- if(last == '\\')
- r = 0;
- break;
- case ' ':
- case '\t':
- if(!quoted && last != '\\')
- goto done;
- r = c;
- p += runetochar(p,&r);
- break;
- case '"':
- if(quoted && last != '\\')
- goto done;
- r = c;
- p += runetochar(p,&r);
- break;
- default:
- r = c;
- p += runetochar(p,&r);
- break;
- }
- last = r;
- }
- done:
- *p++ = 0;
- return p;
- }
- int
- parseargs(char *p, char *e, char **argv)
- {
- int argc;
- char *np;
- int nullarg;
- indirective = 1;
- *p++ = 0;
- for(argc = 1; argc < Narg; argc++){
- np = copyarg(p, e, &nullarg);
- if(nullarg==0 && np == p+1)
- break;
- argv[argc] = p;
- p = np;
- }
- argv[argc] = nil;
- indirective = 0;
- return argc;
- }
- void
- dodirective(void)
- {
- char *p, *e;
- Goobie *g;
- Goobieif *gif;
- char line[Nline], *line1;
- int i, argc;
- char *argv[Narg];
- Mstack *m;
- /* read line, translate special bytes */
- e = line + sizeof(line) - UTFmax - 1;
- line1 = copyline(line, e, 1);
- if (!line[0])
- return;
- argv[0] = line;
- /* first look through user defined macros */
- p = getmacro(argv[0]);
- if(p != nil){
- if(msp == Maxmstack-1){
- fprint(2, "ms2html: macro stack overflow\n");
- return;
- }
- argc = parseargs(line1, e, argv);
- m = &mstack[++msp];
- m->ptr = p;
- memset(m->argv, 0, sizeof(m->argv));
- for(i = 0; i < argc; i++)
- m->argv[i] = strdup(argv[i]);
- return;
- }
- /* check for .if or .ie */
- for(gif = gtabif; gif->name; gif++)
- if(strcmp(gif->name, argv[0]) == 0){
- (*gif->f)(line1, e);
- return;
- }
- argc = parseargs(line1, e, argv);
- /* try standard ms macros */
- for(g = gtab; g->name; g++)
- if(strcmp(g->name, argv[0]) == 0){
- (*g->f)(argc, argv);
- return;
- }
- if(debug)
- fprint(2, "stdin %d(%s:%d): unknown directive %s\n",
- ssp->lno, ssp->filename, ssp->rlno, line);
- }
- void
- printarg(char *a)
- {
- char *e, *p;
-
- e = a + strlen(a);
- pushstr(a);
- while(strsp >= 0 && strstack[strsp] >= a && strstack[strsp] < e){
- p = getnext();
- if(p == nil)
- return;
- Bprint(&bout, "%s", p);
- }
- }
- void
- printargs(int argc, char **argv)
- {
- argc--;
- argv++;
- while(--argc > 0){
- printarg(*argv++);
- Bprint(&bout, " ");
- }
- if(argc == 0)
- printarg(*argv);
- }
- void
- dohangingdt(void)
- {
- switch(hangingdt){
- case 3:
- hangingdt--;
- break;
- case 2:
- Bprint(&bout, "<dd>");
- hangingdt = 0;
- break;
- }
- }
- void
- dohangingau(void)
- {
- if(hangingau == 0)
- return;
- Bprint(&bout, "</I></DL>\n");
- hangingau = 0;
- }
- void
- dohanginghead(void)
- {
- if(hanginghead == 0)
- return;
- Bprint(&bout, "</H%d>\n", hanginghead);
- hanginghead = 0;
- }
- /*
- * convert a man page to html and output
- */
- void
- doconvert(void)
- {
- char c, *p;
- Tm *t;
- pushsrc(nil);
- sol = 1;
- Bprint(&bout, "<html>\n");
- Bflush(&bout);
- for(;;){
- p = getnext();
- if(p == nil)
- break;
- c = *p;
- if(c == '.' && sol){
- dodirective();
- dohangingdt();
- ssp->lno++;
- ssp->rlno++;
- sol = 1;
- } else if(c == '\n'){
- if (ignore_nl)
- ignore_nl = 0;
- else {
- if(hangingau)
- Bprint(&bout, "<br>\n");
- else
- Bprint(&bout, "%s", p);
- dohangingdt();
- }
- ssp->lno++;
- ssp->rlno++;
- sol = 1;
- } else{
- Bprint(&bout, "%s", p);
- ignore_nl = sol = 0;
- }
- }
- dohanginghead();
- dohangingdt();
- closel();
- if(fsp >= 0 && fstack[fsp])
- Bprint(&bout, "%s", fstack[fsp]->end);
- Bprint(&bout, "<br> <br>\n");
- Bprint(&bout, "<A href=http://www.lucent.com/copyright.html>\n");
- t = localtime(time(nil));
- Bprint(&bout, "Copyright</A> © %d Alcatel-Lucent Inc. All rights reserved.\n",
- t->year+1900);
- Bprint(&bout, "</body></html>\n");
- }
- static void
- usage(void)
- {
- sysfatal("usage: ms2html [-q] [-b basename] [-d '$$'] [-t title]");
- }
- void
- main(int argc, char **argv)
- {
- quiet = 1;
- ARGBEGIN {
- case 't':
- title = EARGF(usage());
- break;
- case 'b':
- basename = EARGF(usage());
- break;
- case 'q':
- quiet = 0;
- break;
- case 'd':
- delim = EARGF(usage());
- break;
- case '?':
- default:
- usage();
- } ARGEND;
- Binit(&bout, 1, OWRITE);
- ds("R", "®");
- doconvert();
- exits(nil);
- }
- void
- g_notyet(int, char **argv)
- {
- fprint(2, "ms2html: .%s not yet supported\n", argv[0]);
- }
- void
- g_ignore(int, char **argv)
- {
- if(quiet)
- return;
- fprint(2, "ms2html: line %d: ignoring .%s\n", ssp->lno, argv[0]);
- }
- void
- g_PP(int, char**)
- {
- dohanginghead();
- closel();
- closefont();
- Bprint(&bout, "<P>\n");
- paragraph = 1;
- }
- void
- g_LP(int, char**)
- {
- dohanginghead();
- closel();
- closefont();
- Bprint(&bout, "<br> <br>\n");
- }
- /* close a list */
- void
- closel(void)
- {
- g_P2(1, nil);
- dohangingau();
- if(paragraph){
- Bprint(&bout, "</P>\n");
- paragraph = 0;
- }
- switch(list){
- case Lordered:
- Bprint(&bout, "</ol>\n");
- break;
- case Lunordered:
- Bprint(&bout, "</ul>\n");
- break;
- case Lother:
- case Ldef:
- Bprint(&bout, "</dl>\n");
- break;
- }
- list = 0;
-
- }
- void
- g_IP(int argc, char **argv)
- {
- switch(list){
- default:
- closel();
- if(argc > 1){
- if(strcmp(argv[1], "1") == 0){
- list = Lordered;
- listnum = 1;
- Bprint(&bout, "<OL>\n");
- } else if(strcmp(argv[1], "\\(bu") == 0){
- list = Lunordered;
- Bprint(&bout, "<UL>\n");
- } else {
- list = Lother;
- Bprint(&bout, "<DL COMPACT>\n");
- }
- } else {
- list = Lother;
- Bprint(&bout, "<DL>\n");
- }
- break;
- case Lother:
- case Lordered:
- case Lunordered:
- break;
- }
- switch(list){
- case Lother:
- Bprint(&bout, "<DT>");
- if(argc > 1)
- printarg(argv[1]);
- else
- Bprint(&bout, "<DT> ");
- Bprint(&bout, "<DD>\n");
- break;
- case Lordered:
- case Lunordered:
- Bprint(&bout, "<LI>\n");
- break;
- }
- }
- /*
- * .5i is one <DL><DT><DD>
- */
- void
- g_in(int argc, char **argv)
- {
- float f;
- int delta, x;
- char *p;
- f = indent/0.5;
- delta = f;
- if(argc <= 1){
- indent = 0.0;
- } else {
- f = strtod(argv[1], &p);
- switch(*p){
- case 'i':
- break;
- case 'c':
- f = f / 2.54;
- break;
- case 'P':
- f = f / 6;
- break;
- default:
- case 'u':
- case 'm':
- f = f * (12 / 72);
- break;
- case 'n':
- f = f * (6 / 72);
- break;
- case 'p':
- f = f / 72.0;
- break;
- }
- switch(argv[1][0]){
- case '+':
- case '-':
- indent += f;
- break;
- default:
- indent = f;
- break;
- }
- }
- if(indent < 0.0)
- indent = 0.0;
- f = (indent/0.5);
- x = f;
- delta = x - delta;
- while(delta < 0){
- Bprint(&bout, "</DL>\n");
- delta++;
- }
- while(delta > 0){
- Bprint(&bout, "<DL><DT><DD>\n");
- delta--;
- }
- }
- void
- g_HP(int, char**)
- {
- switch(list){
- default:
- closel();
- list = Ldef;
- hangingdt = 1;
- Bprint(&bout, "<DL><DT>\n");
- break;
- case Ldef:
- if(hangingdt)
- Bprint(&bout, "<DD>");
- Bprint(&bout, "<DT>");
- hangingdt = 1;
- break;
- }
- }
- void
- g_SH(int, char**)
- {
- dohanginghead();
- dohangingcenter();
- closel();
- closefont();
- Bprint(&bout, "<H%d>", HH);
- hanginghead = HH;
- }
- void
- g_NH(int argc, char **argv)
- {
- int i, level;
- closel();
- closefont();
- dohangingcenter();
- if(argc == 1)
- level = 0;
- else {
- level = atoi(argv[1])-1;
- if(level < 0 || level >= Maxnh)
- level = Maxnh - 1;
- }
- nh[level]++;
- Bprint(&bout, "<H%d>", HH);
- hanginghead = HH;
- Bprint(&bout, "%d", nh[0]);
- for(i = 1; i <= level; i++)
- Bprint(&bout, ".%d", nh[i]);
- Bprint(&bout, " ");
- for(i = level+1; i < Maxnh; i++)
- nh[i] = 0;
- }
- void
- g_TL(int, char**)
- {
- char *p, *np;
- char name[128];
- closefont();
- if(!titleseen){
- if(!title){
- /* get base part of filename */
- p = strrchr(ssp->filename, '/');
- if(p == nil)
- p = ssp->filename;
- else
- p++;
- strncpy(name, p, sizeof(name));
- name[sizeof(name)-1] = 0;
-
- /* dump any extensions */
- np = strchr(name, '.');
- if(np)
- *np = 0;
- title = p;
- }
- Bprint(&bout, "<title>\n");
- Bprint(&bout, "%s\n", title);
- Bprint(&bout, "</title>\n");
- Bprint(&bout, "<body BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\" LINK=\"#0000FF\" VLINK=\"#330088\" ALINK=\"#FF0044\">\n");
- titleseen = 1;
- }
- Bprint(&bout, "<center>");
- hangingcenter = 1;
- Bprint(&bout, "<H%d>", 1);
- hanginghead = 1;
- }
- void
- dohangingcenter(void)
- {
- if(hangingcenter){
- Bprint(&bout, "</center>");
- hangingcenter = 1;
- }
- }
- void
- g_AU(int, char**)
- {
- closel();
- dohanginghead();
- Bprint(&bout, "<DL><DD><I>");
- hangingau = 1;
- }
- void
- pushfont(Font *f)
- {
- if(fsp == Maxfsp)
- return;
- if(fsp >= 0 && fstack[fsp])
- Bprint(&bout, "%s", fstack[fsp]->end);
- if(f != nil)
- Bprint(&bout, "%s", f->start);
- fstack[++fsp] = f;
- }
- void
- popfont(void)
- {
- if(fsp >= 0){
- if(fstack[fsp])
- Bprint(&bout, "%s", fstack[fsp]->end);
- fsp--;
- }
- }
- /*
- * for 3 args print arg3 \fxarg1\fP arg2
- * for 2 args print arg1 \fxarg2\fP
- * for 1 args print \fxarg1\fP
- */
- void
- font(Font *f, int argc, char **argv)
- {
- if(argc == 1){
- pushfont(nil);
- return;
- }
- if(argc > 3)
- printarg(argv[3]);
- pushfont(f);
- printarg(argv[1]);
- popfont();
- if(argc > 2)
- printarg(argv[2]);
- Bprint(&bout, "\n");
- }
- void
- closefont(void)
- {
- if(fsp >= 0 && fstack[fsp])
- Bprint(&bout, "%s", fstack[fsp]->end);
- fsp = -1;
- }
- void
- g_B(int argc, char **argv)
- {
- font(&bfont, argc, argv);
- }
- void
- g_R(int argc, char **argv)
- {
- font(nil, argc, argv);
- }
- void
- g_BI(int argc, char **argv)
- {
- font(&bifont, argc, argv);
- }
- void
- g_CW(int argc, char **argv)
- {
- font(&cwfont, argc, argv);
- }
- char*
- lower(char *p)
- {
- char *x;
- for(x = p; *x; x++)
- if(*x >= 'A' && *x <= 'Z')
- *x -= 'A' - 'a';
- return p;
- }
- void
- g_I(int argc, char **argv)
- {
- int anchor;
- char *p;
- anchor = 0;
- if(argc > 2){
- p = argv[2];
- if(p[0] == '(')
- if(p[1] >= '0' && p[1] <= '9')
- if(p[2] == ')'){
- anchor = 1;
- Bprint(&bout, "<A href=\"/magic/man2html/%c/%s\">",
- p[1], lower(argv[1]));
- }
- }
- font(&ifont, argc, argv);
- if(anchor)
- Bprint(&bout, "</A>");
- }
- void
- g_br(int, char**)
- {
- if(hangingdt){
- Bprint(&bout, "<dd>");
- hangingdt = 0;
- }else
- Bprint(&bout, "<br>\n");
- }
- void
- g_P1(int, char**)
- {
- if(example == 0){
- example = 1;
- Bprint(&bout, "<DL><DT><DD><TT><PRE>\n");
- }
- }
- void
- g_P2(int, char**)
- {
- if(example){
- example = 0;
- Bprint(&bout, "</PRE></TT></DL>\n");
- }
- }
- void
- g_SM(int, char **argv)
- {
- Bprint(&bout, "%s", argv[1]);
- }
- void
- g_ft(int argc, char **argv)
- {
- if(argc < 2){
- pushfont(nil);
- return;
- }
- switch(argv[1][0]){
- case '3':
- case 'B':
- pushfont(&bfont);
- break;
- case '2':
- case 'I':
- pushfont(&ifont);
- break;
- case '4':
- pushfont(&bifont);
- break;
- case '5':
- pushfont(&cwfont);
- break;
- case 'P':
- popfont();
- break;
- case 'R':
- default:
- pushfont(nil);
- break;
- }
- }
- void
- g_sp(int argc, char **argv)
- {
- int n;
- n = 1;
- if(argc > 1){
- n = atoi(argv[1]);
- if(n < 1)
- n = 1;
- if(argv[1][strlen(argv[1])-1] == 'i')
- n *= 4;
- }
- if(n > 5){
- Bprint(&bout, "<br> <br>\n");
- Bprint(&bout, "<HR>\n");
- Bprint(&bout, "<br> <br>\n");
- } else
- for(; n > 0; n--)
- Bprint(&bout, "<br> <br>\n");
- }
- void
- rm_loop(char *name, String **l)
- {
- String *s;
- for(s = *l; s != nil; s = *l){
- if(strcmp(name, s->name) == 0){
- *l = s->next;
- free(s->name);
- free(s->val);
- free(s);
- break;
- }
- l = &s->next;
- }
- }
- void
- g_rm(int argc, char **argv)
- {
- Goobie *g;
- char *name;
- int i;
- for(i = 1; i < argc; i++) {
- name = argv[i];
- rm_loop(name, &strings);
- rm_loop(name, ¯os);
- for(g = gtab; g->name; g++)
- if (strcmp(g->name, name) == 0) {
- g->f = g_ignore;
- break;
- }
- }
- }
- void
- g_AB(int, char**)
- {
- closel();
- dohangingcenter();
- Bprint(&bout, "<center><H4>ABSTRACT</H4></center><DL><DD>\n");
- }
- void
- g_AE(int, char**)
- {
- Bprint(&bout, "</DL>\n");
- }
- void
- g_FS(int, char **)
- {
- char *argv[3];
- argv[0] = "IP";
- argv[1] = nil;
- argv[2] = nil;
- g_IP(1, argv);
- Bprint(&bout, "NOTE:<I> ");
- }
- void
- g_FE(int, char **)
- {
- Bprint(&bout, "</I><DT> <DD>");
- closel();
- Bprint(&bout, "<br>\n");
- }
- void
- g_de(int argc, char **argv)
- {
- int r;
- char *p, *cp;
- String *m;
- int len;
- if(argc < 2)
- return;
- m = nil;
- len = 0;
- if(strcmp(argv[0], "am") == 0){
- for(m = macros; m != nil; m = m->next)
- if(strcmp(argv[1], m->name) == 0){
- len = strlen(m->val);
- break;
- }
- if(m == nil){
- /* nothing to append to */
- for(;;){
- p = Brdline(&ssp->in, '\n');
- if(p == nil)
- break;
- p[Blinelen(&ssp->in)-1] = 0;
- if(strcmp(p, "..") == 0)
- break;
- }
- return;
- }
- }
- if(m == nil){
- m = emalloc(sizeof(*m));
- m->next = macros;
- macros = m;
- m->name = strdup(argv[1]);
- m->val = nil;
- len = 0;
- }
- /* read up to a .. removing double backslashes */
- for(;;){
- p = Brdline(&ssp->in, '\n');
- if(p == nil)
- break;
- p[Blinelen(&ssp->in)-1] = 0;
- if(strcmp(p, "..") == 0)
- break;
- m->val = realloc(m->val, len + Blinelen(&ssp->in)+1);
- cp = m->val + len;
- while(*p){
- r = *p++;
- if(r == '\\' && *p == '\\')
- p++;
- *cp++ = r;
- }
- *cp++ = '\n';
- len = cp - m->val;
- *cp = 0;
- }
- }
- void
- g_hrule(int, char**)
- {
- Bprint(&bout, "<HR>\n");
- }
- void
- g_BX(int argc, char **argv)
- {
- Bprint(&bout, "<HR>\n");
- printargs(argc, argv);
- Bprint(&bout, "<HR>\n");
- }
- void
- g_IH(int, char**)
- {
- Bprint(&bout, "Bell Laboratories, Naperville, Illinois, 60540\n");
- }
- void
- g_MH(int, char**)
- {
- Bprint(&bout, "Bell Laboratories, Murray Hill, NJ, 07974\n");
- }
- void
- g_PY(int, char**)
- {
- Bprint(&bout, "Bell Laboratories, Piscataway, NJ, 08854\n");
- }
- void
- g_HO(int, char**)
- {
- Bprint(&bout, "Bell Laboratories, Holmdel, NJ, 07733\n");
- }
- void
- g_QS(int, char**)
- {
- Bprint(&bout, "<BLOCKQUOTE>\n");
- }
- void
- g_QE(int, char**)
- {
- Bprint(&bout, "</BLOCKQUOTE>\n");
- }
- void
- g_RS(int, char**)
- {
- Bprint(&bout, "<DL><DD>\n");
- }
- void
- g_RE(int, char**)
- {
- Bprint(&bout, "</DL>\n");
- }
- int gif;
- void
- g_startgif(int, char **argv)
- {
- int fd;
- int pfd[2];
- char *e, *p;
- char name[32];
- Dir *d;
- if(strcmp(argv[0], "EQ") == 0)
- e = ".EN";
- else if(strcmp(argv[0], "TS") == 0)
- e = ".TE";
- else if(strcmp(argv[0], "PS") == 0)
- e = ".PE";
- else
- return;
- if(basename)
- p = basename;
- else{
- p = strrchr(sstack[0].filename, '/');
- if(p != nil)
- p++;
- else
- p = sstack[0].filename;
- }
- snprint(name, sizeof(name), "%s.%d.gif", p, gif++);
- fd = create(name, OWRITE, 0664);
- if(fd < 0){
- fprint(2, "ms2html: can't create %s: %r\n", name);
- return;
- }
- if(pipe(pfd) < 0){
- fprint(2, "ms2html: can't create pipe: %r\n");
- close(fd);
- return;
- }
- switch(rfork(RFFDG|RFPROC)){
- case -1:
- fprint(2, "ms2html: can't fork: %r\n");
- close(fd);
- return;
- case 0:
- dup(fd, 1);
- close(fd);
- dup(pfd[0], 0);
- close(pfd[0]);
- close(pfd[1]);
- execl("/bin/troff2gif", "troff2gif", nil);
- fprint(2, "ms2html: couldn't exec troff2gif: %r\n");
- _exits(nil);
- default:
- close(fd);
- close(pfd[0]);
- fprint(pfd[1], ".ll 7i\n");
- /* fprint(pfd[1], ".EQ\ndelim %s\n.EN\n", delim); */
- /* fprint(pfd[1], ".%s\n", argv[0]); */
- for(;;){
- p = Brdline(&ssp->in, '\n');
- if(p == nil)
- break;
- ssp->lno++;
- ssp->rlno++;
- if(write(pfd[1], p, Blinelen(&ssp->in)) < 0)
- break;
- if(strncmp(p, e, 3) == 0)
- break;
- }
- close(pfd[1]);
- waitpid();
- d = dirstat(name);
- if(d == nil)
- break;
- if(d->length == 0){
- remove(name);
- free(d);
- break;
- }
- free(d);
- fprint(2, "ms2html: created auxiliary file %s\n", name);
- Bprint(&bout, "<br><img src=\"%s\"><br>\n", name);
- break;
- }
- }
- void
- g_lf(int argc, char **argv)
- {
- if(argc > 2)
- snprint(ssp->filename, sizeof(ssp->filename), argv[2]);
- if(argc > 1)
- ssp->rlno = atoi(argv[1]);
- }
- void
- g_so(int argc, char **argv)
- {
- ssp->lno++;
- ssp->rlno++;
- if(argc > 1)
- pushsrc(argv[1]);
- }
- void
- g_BP(int argc, char **argv)
- {
- int fd;
- char *p, *ext;
- char name[32];
- Dir *d;
- if(argc < 2)
- return;
- p = strrchr(argv[1], '/');
- if(p != nil)
- p++;
- else
- p = argv[1];
- ext = strrchr(p, '.');
- if(ext){
- if(strcmp(ext, ".jpeg") == 0
- || strcmp(ext, ".gif") == 0){
- Bprint(&bout, "<br><img src=\"%s\"><br>\n", argv[1]);
- return;
- }
- }
- snprint(name, sizeof(name), "%s.%d%d.gif", p, getpid(), gif++);
- fd = create(name, OWRITE, 0664);
- if(fd < 0){
- fprint(2, "ms2html: can't create %s: %r\n", name);
- return;
- }
- switch(rfork(RFFDG|RFPROC)){
- case -1:
- fprint(2, "ms2html: can't fork: %r\n");
- close(fd);
- return;
- case 0:
- dup(fd, 1);
- close(fd);
- execl("/bin/ps2gif", "ps2gif", argv[1], nil);
- fprint(2, "ms2html: couldn't exec ps2gif: %r\n");
- _exits(nil);
- default:
- close(fd);
- waitpid();
- d = dirstat(name);
- if(d == nil)
- break;
- if(d->length == 0){
- remove(name);
- free(d);
- break;
- }
- free(d);
- fprint(2, "ms2html: created auxiliary file %s\n", name);
- Bprint(&bout, "<br><img src=\"%s\"><br>\n", name);
- break;
- }
- }
- /* insert straight HTML into output */
- void
- g__H(int argc, char **argv)
- {
- int i;
- for(i = 1; i < argc; i++)
- Bprint(&bout, "%s ", argv[i]);
- Bprint(&bout, "\n");
- }
- /* HTML page title */
- void
- g__T(int argc, char **argv)
- {
- if(titleseen)
- return;
- Bprint(&bout, "<title>\n");
- printargs(argc, argv);
- Bprint(&bout, "</title></head><body>\n");
- titleseen = 1;
- }
- void
- g_nr(int argc, char **argv)
- {
- char *val;
- if (argc > 1) {
- if (argc == 2)
- val = "0";
- else
- val = argv[2];
- dsnr(argv[1], val, &numregs);
- }
- }
- void
- zerodivide(void)
- {
- fprint(2, "stdin %d(%s:%d): division by 0\n",
- ssp->lno, ssp->filename, ssp->rlno);
- }
- int
- numval(char **pline, int recur)
- {
- char *p;
- int neg, x, y;
- x = neg = 0;
- p = *pline;
- while(*p == '-') {
- neg = 1 - neg;
- p++;
- }
- if (*p == '(') {
- p++;
- x = numval(&p, 1);
- if (*p != ')')
- goto done;
- p++;
- }
- else while(*p >= '0' && *p <= '9')
- x = 10*x + *p++ - '0';
- if (neg)
- x = -x;
- if (recur)
- for(;;) {
- switch(*p++) {
- case '+':
- x += numval(&p, 0);
- continue;
- case '-':
- x -= numval(&p, 0);
- continue;
- case '*':
- x *= numval(&p, 0);
- continue;
- case '/':
- y = numval(&p, 0);
- if (y == 0) {
- zerodivide();
- x = 0;
- goto done;
- }
- x /= y;
- continue;
- case '<':
- if (*p == '=') {
- p++;
- x = x <= numval(&p, 0);
- continue;
- }
- x = x < numval(&p, 0);
- continue;
- case '>':
- if (*p == '=') {
- p++;
- x = x >= numval(&p, 0);
- continue;
- }
- x = x > numval(&p, 0);
- continue;
- case '=':
- if (*p == '=')
- p++;
- x = x == numval(&p, 0);
- continue;
- case '&':
- x &= numval(&p, 0);
- continue;
- case ':':
- x |= numval(&p, 0);
- continue;
- case '%':
- y = numval(&p, 0);
- if (!y) {
- zerodivide();
- goto done;
- }
- x %= y;
- continue;
- }
- --p;
- break;
- }
- done:
- *pline = p;
- return x;
- }
- int
- iftest(char *p, char **bp)
- {
- char *p1;
- int c, neg, rv;
- rv = neg = 0;
- if (*p == '!') {
- neg = 1;
- p++;
- }
- c = *p;
- if (c >= '0' && c <= '9' || c == '+' || c == '-' || c == '('/*)*/) {
- if (numval(&p,1) >= 1)
- rv = 1;
- goto done;
- }
- switch(c) {
- case 't':
- case 'o':
- rv = 1;
- case 'n':
- case 'e':
- p++;
- goto done;
- }
- for(p1 = ++p; *p != c; p++)
- if (!*p)
- goto done;
- for(p++;;) {
- if (*p != *p1++) {
- while(*p && *p++ != c);
- goto done;
- }
- if (*p++ == c)
- break;
- }
- rv = 1;
- done:
- if (neg)
- rv = 1 - rv;
- while(*p == ' ' || *p == '\t')
- p++;
- *bp = p;
- return rv;
- }
- void
- scanline(char *p, char *e, int wantnl)
- {
- int c;
- Rune r;
- while((c = getrune()) == ' ' || c == '\t') ;
- while(p < e) {
- if (c < 0)
- break;
- if (c < Runeself) {
- if (c == '\n') {
- if (wantnl)
- *p++ = c;
- break;
- }
- *p++ = c;
- }
- else {
- r = c;
- p += runetochar(p, &r);
- }
- c = getrune();
- }
- *p = 0;
- }
- void
- pushbody(char *line)
- {
- char *b;
- if (line[0] == '\\' && line[1] == '{' /*}*/ )
- line += 2;
- if (strsp < Maxmstack - 1) {
- pushstr(b = strdup(line));
- mustfree[strsp] = b;
- }
- }
- void
- skipbody(char *line)
- {
- int c, n;
- if (line[0] != '\\' || line[1] != '{' /*}*/ )
- return;
- for(n = 1;;) {
- while((c = getrune()) != '\\')
- if (c < 0)
- return;
- c = getrune();
- if (c == '{')
- n++;
- else if ((c == '}' && (c = getrune()) == '\n' && !--n)
- || c < 0)
- return;
- }
- }
- int
- ifstart(char *line, char *e, char **bp)
- {
- int it;
- char *b;
- b = copyline(line, e, 1);
- ungetrune();
- b[-1] = getrune();
- scanline(b, e, 1);
- it = iftest(line, bp);
- return it;
- }
- void
- g_ie(char *line, char *e)
- {
- char *b;
- if (elsetop >= Maxif-1) {
- fprint(2, "ms2html: .ie's too deep\n");
- return;
- }
- if (ifwastrue[++elsetop] = ifstart(line, e, &b))
- pushbody(b);
- else
- skipbody(b);
- }
- void
- g_if(char *line, char *e)
- {
- char *b;
- if (ifstart(line, e, &b))
- pushbody(b);
- else
- skipbody(b);
- }
- void
- g_el(char *line, char *e)
- {
- if (elsetop < 0)
- return;
- scanline(line, e, 1);
- if (ifwastrue[elsetop--])
- skipbody(line);
- else
- pushbody(line);
- }
- void
- g_ig(int argc, char **argv)
- {
- char *p, *s;
- s = "..";
- if (argc > 1)
- s = argv[1];
- for(;;) {
- p = Brdline(&ssp->in, '\n');
- if(p == nil)
- break;
- p[Blinelen(&ssp->in)-1] = 0;
- if(strcmp(p, s) == 0)
- break;
- }
- }
- void
- g_ds(char *line, char *e)
- {
- char *b;
- b = copyline(line, e, 1);
- if (b > line) {
- copyline(b, e, 0);
- if (*b == '"')
- b++;
- ds(line, b);
- }
- }
- void
- g_as(char *line, char *e)
- {
- String *s;
- char *b;
- b = copyline(line, e, 1);
- if (b == line)
- return;
- copyline(b, e, 0);
- if (*b == '"')
- b++;
- for(s = strings; s != nil; s = s->next)
- if(strcmp(line, s->name) == 0)
- break;
- if(s == nil){
- ds(line, b);
- return;
- }
- s->val = realloc(s->val, strlen(s->val) + strlen(b) + 1);
- strcat(s->val, b);
- }
- void
- g_BS(int argc, char **argv)
- {
- int i;
- if (argc > 1 && !weBref) {
- Bprint(&bout, "<a href=\"%s\"", argv[1]);
- for(i = 2; i < argc; i++)
- Bprint(&bout, " %s", argv[i]);
- Bprint(&bout, ">");
- weBref = 1;
- }
- }
- void
- g_BE(int, char**)
- {
- if (weBref) {
- Bprint(&bout, "</a>");
- weBref = 0;
- }
- }
- void
- g_LB(int argc, char **argv)
- {
- if (argc > 1) {
- if (weBref)
- g_BE(0,nil);
- Bprint(&bout, "<a name=\"%s\"></a>", argv[1]);
- }
- }
- void
- g_RT(int, char**)
- {
- g_BE(0,nil);
- dohanginghead();
- closel();
- closefont();
- }
|