10 Maxnh= 8, /* highest NH level */
11 HH= 4, /* heading level used for SH and NH */
12 Maxmstack= 10, /* deepest macro/string nesting */
13 Narg= 20, /* max args to a macro */
14 Maxsstack= 5, /* deepest nesting of .so's */
33 float indent; /* from .in */
42 int list, listnum, example;
43 int hangingau, hangingdt, hanginghead, hangingcenter;
44 int indirective, paragraph, sol, titleseen, ignore_nl, weBref;
45 void dohangingcenter(void);
47 typedef struct Goobie Goobie;
48 typedef struct Goobieif Goobieif;
52 void (*f)(int, char**);
55 typedef void F(int, char**);
56 typedef void Fif(char*, char*);
65 Fif g_as, g_ds, g_el, g_ie, g_if;
76 F g_notyet, g_ignore, g_hrule, g_startgif;
79 F g_AU, g_B, g_BI, g_CW, g_I, g_IP, g_LP, g_PP, g_SH, g_NH;
80 F g_P1, g_P2, g_TL, g_R, g_AB, g_AE, g_EQ, g_TS, g_TE, g_FS, g_FE;
81 F g_PY, g_IH, g_MH, g_HO, g_BX, g_QS, g_QE, g_RS, g_RE;
87 F g_br, g_ft, g_sp, g_de, g_lf, g_so, g_rm, g_in;
88 F g_nr, g_ig, g_RT, g_BS, g_BE, g_LB, g_ta;
90 /* macros to include ML in output */
117 { "EQ", g_startgif, },
143 { "PS", g_startgif, },
161 { "TS", g_startgif, },
190 typedef struct Entity Entity;
199 { "&#SPACE;", L' ', },
203 { "Æ", L'Æ', },
204 { "Á", L'Á', },
205 { "Â", L'Â', },
206 { "À", L'À', },
207 { "Å", L'Å', },
208 { "Ã", L'Ã', },
210 { "Ç", L'Ç', },
212 { "É", L'É', },
213 { "Ê", L'Ê', },
214 { "È", L'È', },
216 { "Í", L'Í', },
217 { "Î", L'Î', },
218 { "Ì", L'Ì', },
220 { "Ñ", L'Ñ', },
221 { "Ó", L'Ó', },
222 { "Ô", L'Ô', },
223 { "Ò", L'Ò', },
224 { "Ø", L'Ø', },
225 { "Õ", L'Õ', },
227 { "Þ", L'Þ', },
228 { "Ú", L'Ú', },
229 { "Û", L'Û', },
230 { "Ù", L'Ù', },
232 { "Ý", L'Ý', },
233 { "á", L'á', },
234 { "â", L'â', },
235 { "æ", L'æ', },
236 { "à", L'à', },
238 { "å", L'å', },
239 { "ã", L'ã', },
241 { "ç", L'ç', },
242 { "é", L'é', },
243 { "ê", L'ê', },
244 { "è", L'è', },
248 { "í", L'í', },
249 { "î", L'î', },
250 { "ì", L'ì', },
253 { "ñ", L'ñ', },
254 { "ó", L'ó', },
255 { "ô", L'ô', },
256 { "ò", L'ò', },
257 { "ø", L'ø', },
258 { "õ", L'õ', },
260 { "ß", L'ß', },
261 { "þ", L'þ', },
262 { "ú", L'ú', },
263 { "û", L'û', },
264 { "ù", L'ù', },
266 { "ý", L'ý', },
367 { "CYRILLIC XYZZY", L'й', },
368 { "CYRILLIC XYZZY", L'ъ', },
369 { "CYRILLIC Y", L'ь', },
370 { "CYRILLIC YA", L'я', },
371 { "CYRILLIC YA", L'ё', },
377 typedef struct Troffspec Troffspec;
386 { "A*", "Å", },
387 { "o\"", "ö", },
424 { "is", "Integral", },
435 { "es", "Ø", },
439 { "L1", "DEATHSTAR", },
465 typedef struct Font Font;
471 Font bfont = { "<B>", "</B>" };
472 Font ifont = { "<I>", "</I>" };
473 Font bifont = { "<B><I>", "</I></B>" };
474 Font cwfont = { "<TT>", "</TT>" };
475 Font *fstack[Maxfsp];
478 typedef struct String String;
485 String *numregs, *strings;
486 char *strstack[Maxmstack];
487 char *mustfree[Maxmstack];
491 typedef struct Mstack Mstack;
498 Mstack mstack[Maxmstack];
501 typedef struct Srcstack Srcstack;
510 Srcstack sstack[Maxsstack];
511 Srcstack *ssp = &sstack[-1];
516 void closefont(void);
525 fprint(2, "ms2html: malloc failed: %r\n");
532 /* define a string variable */
534 dsnr(char *name, char *val, String **l)
538 for(s = *l; s != nil; s = *l){
539 if(strcmp(s->name, name) == 0)
544 s = emalloc(sizeof(String));
546 s->name = strdup(name);
549 s->val = strdup(val);
553 ds(char *name, char *val)
555 dsnr(name, val, &strings);
558 /* look up a defined string */
564 for(s = strings; s != nil; s = s->next)
565 if(strcmp(name, s->name) == 0)
577 for(s = numregs; s != nil; s = s->next)
578 if(strcmp(name, s->name) == 0)
590 if(strsp >= Maxmstack - 1)
592 strstack[++strsp] = p;
596 /* lookup a defined macro */
602 for(s = macros; s != nil; s = s->next)
603 if(strcmp(name, s->name) == 0)
622 if(ssp == &sstack[Maxsstack-1]){
623 fprint(2, "ms2html: .so's too deep\n");
630 fprint(2, "ms2html: can't stat %s: %r\n", name);
636 fd = open(name, OREAD);
638 fprint(2, "ms2html: can't open %s: %r\n", name);
644 Binit(&ssp->in, fd, OREAD);
645 snprint(ssp->filename, sizeof(ssp->filename), "%s", name);
646 ssp->lno = ssp->rlno = 1;
650 /* get next logical byte. from stdin or a defined string */
660 i = chartorune(&r, strstack[strsp]);
662 strstack[strsp] += i;
666 if (mustfree[strsp]) {
667 free(mustfree[strsp]);
668 mustfree[strsp] = nil;
674 i = chartorune(&r, m->ptr);
680 for(i = 0; m->argv[i] != nil; i++)
689 c = Bgetrune(&ssp->in);
715 Bungetrune(&ssp->in);
728 if(fsp >= 0 && fstack[fsp])
729 strcpy(token, fstack[fsp]->end);
731 strcat(token, f->start);
742 strcpy(token, fstack[fsp]->end);
745 if(fsp >= 0 && fstack[fsp])
746 strcat(token, fstack[fsp]->start);
751 changesize(int amount)
753 static int curamount;
754 static char buf[200];
759 for (i = 0; i < curamount; i++)
760 strcat(buf, "</big>");
762 for (i = 0; i < -curamount; i++)
763 strcat(buf, "</small>");
766 for (i = 0; i < amount; i++)
767 strcat(buf, "<big>");
769 for (i = 0; i < -amount; i++)
770 strcat(buf, "<small>");
775 /* get next logical character. expand it with escapes */
789 if(r > 128 || r == '<' || r == '>'){
790 for(e = entity; e->name; e++)
793 sprint(buf, "&#%d;", r);
797 if (r == delim[eqnmode]){
800 return changefont(&ifont);
803 return changebackfont();
814 /* chars to ignore */
820 /* small space in troff, nothing in nroff */
831 while(getrune() != '\n')
836 while(getrune() != '\n')
841 /* defined strings */
858 if(r < '1' || r > '9'){
867 pushstr(mstack[msp].argv[r]);
872 token[0] = getrune();
873 token[1] = getrune();
875 for(t = tspec; t->name; t++)
876 if(strcmp(token, t->name) == 0)
880 /* ignore immediately following newline */
892 /* escape backslash */
905 if(strcmp("BI", str) == 0)
906 return changefont(&bifont);
907 else if(strcmp("CW", str) == 0)
908 return changefont(&cwfont);
910 return changefont(nil);
913 return changefont(&bfont);
916 return changefont(&ifont);
918 return changefont(&bifont);
920 return changefont(&cwfont);
922 return changebackfont();
925 return changefont(nil);
928 /* number register */
931 if (r == '(') /*)*/ {
954 return changesize(0);
959 return changesize(-(r - '0'));
964 return changesize(r - '0');
967 /* vertical movement */
979 while(r != '\'' && r != '\n')
989 /* horizontal line */
996 while(getrune() != '\'')
1000 /* character height and slant */
1008 while(getrune() != '\'')
1012 /* digit-width space */
1016 /*for .if, .ie, .el */
1039 if(msp >= 0 || strsp >= 0)
1043 if(msp >= 0 || strsp >= 0)
1047 if(msp >= 0 || strsp >= 0)
1057 token[runetochar(token,&R)] = 0;
1062 /* if arg0 is set, read up to (and expand) to the next whitespace, else to the end of line */
1064 copyline(char *p, char *e, int arg0)
1070 while((c = getrune()) == ' ' || c == '\t')
1072 for(indirective = 1; p < e; c = getrune()) {
1088 p += runetochar(p,&r);
1100 while((*p = *p1++) && p < e)
1110 copyarg(char *p, char *e, int *nullarg)
1112 int c, quoted, last;
1119 } while(c == ' ' || c == '\t');
1131 for(; p < e; c = getrune()) {
1140 p += runetochar(p,&r);
1146 if(!quoted && last != '\\')
1149 p += runetochar(p,&r);
1152 if(quoted && last != '\\')
1155 p += runetochar(p,&r);
1159 p += runetochar(p,&r);
1171 parseargs(char *p, char *e, char **argv)
1179 for(argc = 1; argc < Narg; argc++){
1180 np = copyarg(p, e, &nullarg);
1181 if(nullarg==0 && np == p+1)
1199 char line[Nline], *line1;
1204 /* read line, translate special bytes */
1205 e = line + sizeof(line) - UTFmax - 1;
1206 line1 = copyline(line, e, 1);
1211 /* first look through user defined macros */
1212 p = getmacro(argv[0]);
1214 if(msp == Maxmstack-1){
1215 fprint(2, "ms2html: macro stack overflow\n");
1218 argc = parseargs(line1, e, argv);
1221 memset(m->argv, 0, sizeof(m->argv));
1222 for(i = 0; i < argc; i++)
1223 m->argv[i] = strdup(argv[i]);
1227 /* check for .if or .ie */
1228 for(gif = gtabif; gif->name; gif++)
1229 if(strcmp(gif->name, argv[0]) == 0){
1230 (*gif->f)(line1, e);
1234 argc = parseargs(line1, e, argv);
1236 /* try standard ms macros */
1237 for(g = gtab; g->name; g++)
1238 if(strcmp(g->name, argv[0]) == 0){
1239 (*g->f)(argc, argv);
1244 fprint(2, "stdin %d(%s:%d): unknown directive %s\n",
1245 ssp->lno, ssp->filename, ssp->rlno, line);
1255 while(strsp >= 0 && strstack[strsp] >= a && strstack[strsp] < e){
1259 Bprint(&bout, "%s", p);
1264 printargs(int argc, char **argv)
1284 Bprint(&bout, "<dd>");
1296 Bprint(&bout, "</I></DL>\n");
1303 if(hanginghead == 0)
1305 Bprint(&bout, "</H%d>\n", hanginghead);
1310 * convert a man page to html and output
1320 Bprint(&bout, "<html>\n");
1327 if(c == '.' && sol){
1333 } else if(c == '\n'){
1338 Bprint(&bout, "<br>\n");
1340 Bprint(&bout, "%s", p);
1347 Bprint(&bout, "%s", p);
1348 ignore_nl = sol = 0;
1354 if(fsp >= 0 && fstack[fsp])
1355 Bprint(&bout, "%s", fstack[fsp]->end);
1356 Bprint(&bout, "<br> <br>\n");
1357 Bprint(&bout, "</body></html>\n");
1363 sysfatal("usage: ms2html [-q] [-b basename] [-d '$$'] [-t title]");
1367 main(int argc, char **argv)
1372 title = EARGF(usage());
1375 basename = EARGF(usage());
1381 delim = EARGF(usage());
1388 Binit(&bout, 1, OWRITE);
1397 g_notyet(int, char **argv)
1399 fprint(2, "ms2html: .%s not yet supported\n", argv[0]);
1403 g_ignore(int, char **argv)
1407 fprint(2, "ms2html: line %d: ignoring .%s\n", ssp->lno, argv[0]);
1416 Bprint(&bout, "<P>\n");
1426 Bprint(&bout, "<br> <br>\n");
1436 Bprint(&bout, "</P>\n");
1441 Bprint(&bout, "</ol>\n");
1444 Bprint(&bout, "</ul>\n");
1448 Bprint(&bout, "</dl>\n");
1457 g_IP(int argc, char **argv)
1463 if(strcmp(argv[1], "1") == 0){
1466 Bprint(&bout, "<OL>\n");
1467 } else if(strcmp(argv[1], "\\(bu") == 0){
1469 Bprint(&bout, "<UL>\n");
1472 Bprint(&bout, "<DL COMPACT>\n");
1476 Bprint(&bout, "<DL>\n");
1487 Bprint(&bout, "<DT>");
1491 Bprint(&bout, "<DT> ");
1492 Bprint(&bout, "<DD>\n");
1496 Bprint(&bout, "<LI>\n");
1502 * .5i is one <DL><DT><DD>
1505 g_in(int argc, char **argv)
1516 f = strtod(argv[1], &p);
1554 Bprint(&bout, "</DL>\n");
1558 Bprint(&bout, "<DL><DT><DD>\n");
1571 Bprint(&bout, "<DL><DT>\n");
1575 Bprint(&bout, "<DD>");
1576 Bprint(&bout, "<DT>");
1589 Bprint(&bout, "<H%d>", HH);
1594 g_NH(int argc, char **argv)
1605 level = atoi(argv[1])-1;
1606 if(level < 0 || level >= Maxnh)
1611 Bprint(&bout, "<H%d>", HH);
1614 Bprint(&bout, "%d", nh[0]);
1615 for(i = 1; i <= level; i++)
1616 Bprint(&bout, ".%d", nh[i]);
1619 for(i = level+1; i < Maxnh; i++)
1633 /* get base part of filename */
1634 p = strrchr(ssp->filename, '/');
1639 strncpy(name, p, sizeof(name));
1640 name[sizeof(name)-1] = 0;
1642 /* dump any extensions */
1643 np = strchr(name, '.');
1648 Bprint(&bout, "<title>\n");
1649 Bprint(&bout, "%s\n", title);
1650 Bprint(&bout, "</title>\n");
1651 Bprint(&bout, "<body BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\" LINK=\"#0000FF\" VLINK=\"#330088\" ALINK=\"#FF0044\">\n");
1655 Bprint(&bout, "<center>");
1657 Bprint(&bout, "<H%d>", 1);
1662 dohangingcenter(void)
1665 Bprint(&bout, "</center>");
1675 Bprint(&bout, "<DL><DD><I>");
1684 if(fsp >= 0 && fstack[fsp])
1685 Bprint(&bout, "%s", fstack[fsp]->end);
1687 Bprint(&bout, "%s", f->start);
1696 Bprint(&bout, "%s", fstack[fsp]->end);
1702 * for 3 args print arg3 \fxarg1\fP arg2
1703 * for 2 args print arg1 \fxarg2\fP
1704 * for 1 args print \fxarg1\fP
1707 font(Font *f, int argc, char **argv)
1720 Bprint(&bout, "\n");
1726 if(fsp >= 0 && fstack[fsp])
1727 Bprint(&bout, "%s", fstack[fsp]->end);
1732 g_B(int argc, char **argv)
1734 font(&bfont, argc, argv);
1738 g_R(int argc, char **argv)
1740 font(nil, argc, argv);
1744 g_BI(int argc, char **argv)
1746 font(&bifont, argc, argv);
1750 g_CW(int argc, char **argv)
1752 font(&cwfont, argc, argv);
1761 if(*x >= 'A' && *x <= 'Z')
1767 g_I(int argc, char **argv)
1776 if(p[1] >= '0' && p[1] <= '9')
1779 Bprint(&bout, "<A href=\"/magic/man2html/%c/%s\">",
1780 p[1], lower(argv[1]));
1783 font(&ifont, argc, argv);
1785 Bprint(&bout, "</A>");
1792 Bprint(&bout, "<dd>");
1795 Bprint(&bout, "<br>\n");
1803 Bprint(&bout, "<DL><DT><DD><TT><PRE>\n");
1812 Bprint(&bout, "</PRE></TT></DL>\n");
1817 g_SM(int, char **argv)
1819 Bprint(&bout, "%s", argv[1]);
1823 g_ft(int argc, char **argv)
1856 g_sp(int argc, char **argv)
1865 if(argv[1][strlen(argv[1])-1] == 'i')
1869 Bprint(&bout, "<br> <br>\n");
1870 Bprint(&bout, "<HR>\n");
1871 Bprint(&bout, "<br> <br>\n");
1874 Bprint(&bout, "<br> <br>\n");
1878 rm_loop(char *name, String **l)
1881 for(s = *l; s != nil; s = *l){
1882 if(strcmp(name, s->name) == 0){
1894 g_rm(int argc, char **argv)
1900 for(i = 1; i < argc; i++) {
1902 rm_loop(name, &strings);
1903 rm_loop(name, ¯os);
1904 for(g = gtab; g->name; g++)
1905 if (strcmp(g->name, name) == 0) {
1917 Bprint(&bout, "<center><H4>ABSTRACT</H4></center><DL><DD>\n");
1923 Bprint(&bout, "</DL>\n");
1935 Bprint(&bout, "NOTE:<I> ");
1941 Bprint(&bout, "</I><DT> <DD>");
1943 Bprint(&bout, "<br>\n");
1947 g_de(int argc, char **argv)
1959 if(strcmp(argv[0], "am") == 0){
1960 for(m = macros; m != nil; m = m->next)
1961 if(strcmp(argv[1], m->name) == 0){
1962 len = strlen(m->val);
1967 /* nothing to append to */
1969 p = Brdline(&ssp->in, '\n');
1972 p[Blinelen(&ssp->in)-1] = 0;
1973 if(strcmp(p, "..") == 0)
1981 m = emalloc(sizeof(*m));
1984 m->name = strdup(argv[1]);
1989 /* read up to a .. removing double backslashes */
1991 p = Brdline(&ssp->in, '\n');
1994 p[Blinelen(&ssp->in)-1] = 0;
1995 if(strcmp(p, "..") == 0)
1997 m->val = realloc(m->val, len + Blinelen(&ssp->in)+1);
2001 if(r == '\\' && *p == '\\')
2012 g_hrule(int, char**)
2014 Bprint(&bout, "<HR>\n");
2018 g_BX(int argc, char **argv)
2020 Bprint(&bout, "<HR>\n");
2021 printargs(argc, argv);
2022 Bprint(&bout, "<HR>\n");
2028 Bprint(&bout, "Bell Laboratories, Naperville, Illinois, 60540\n");
2034 Bprint(&bout, "Bell Laboratories, Murray Hill, NJ, 07974\n");
2040 Bprint(&bout, "Bell Laboratories, Piscataway, NJ, 08854\n");
2046 Bprint(&bout, "Bell Laboratories, Holmdel, NJ, 07733\n");
2052 Bprint(&bout, "<BLOCKQUOTE>\n");
2058 Bprint(&bout, "</BLOCKQUOTE>\n");
2064 Bprint(&bout, "<DL><DD>\n");
2070 Bprint(&bout, "</DL>\n");
2076 g_startgif(int, char **argv)
2084 if(strcmp(argv[0], "EQ") == 0)
2086 else if(strcmp(argv[0], "TS") == 0)
2088 else if(strcmp(argv[0], "PS") == 0)
2096 p = strrchr(sstack[0].filename, '/');
2100 p = sstack[0].filename;
2102 snprint(name, sizeof(name), "%s.%d.gif", p, gif++);
2103 fd = create(name, OWRITE, 0664);
2105 fprint(2, "ms2html: can't create %s: %r\n", name);
2110 fprint(2, "ms2html: can't create pipe: %r\n");
2114 switch(rfork(RFFDG|RFPROC)){
2116 fprint(2, "ms2html: can't fork: %r\n");
2125 execl("/bin/troff2gif", "troff2gif", nil);
2126 fprint(2, "ms2html: couldn't exec troff2gif: %r\n");
2131 fprint(pfd[1], ".ll 7i\n");
2132 /* fprint(pfd[1], ".EQ\ndelim %s\n.EN\n", delim); */
2133 /* fprint(pfd[1], ".%s\n", argv[0]); */
2135 p = Brdline(&ssp->in, '\n');
2140 if(write(pfd[1], p, Blinelen(&ssp->in)) < 0)
2142 if(strncmp(p, e, 3) == 0)
2156 fprint(2, "ms2html: created auxiliary file %s\n", name);
2157 Bprint(&bout, "<br><img src=\"%s\"><br>\n", name);
2163 g_lf(int argc, char **argv)
2166 snprint(ssp->filename, sizeof(ssp->filename), argv[2]);
2168 ssp->rlno = atoi(argv[1]);
2172 g_so(int argc, char **argv)
2182 g_BP(int argc, char **argv)
2192 p = strrchr(argv[1], '/');
2199 ext = strrchr(p, '.');
2201 if(strcmp(ext, ".jpeg") == 0
2202 || strcmp(ext, ".gif") == 0){
2203 Bprint(&bout, "<br><img src=\"%s\"><br>\n", argv[1]);
2209 snprint(name, sizeof(name), "%s.%d%d.gif", p, getpid(), gif++);
2210 fd = create(name, OWRITE, 0664);
2212 fprint(2, "ms2html: can't create %s: %r\n", name);
2216 switch(rfork(RFFDG|RFPROC)){
2218 fprint(2, "ms2html: can't fork: %r\n");
2224 execl("/bin/ps2gif", "ps2gif", argv[1], nil);
2225 fprint(2, "ms2html: couldn't exec ps2gif: %r\n");
2239 fprint(2, "ms2html: created auxiliary file %s\n", name);
2240 Bprint(&bout, "<br><img src=\"%s\"><br>\n", name);
2245 /* insert straight HTML into output */
2247 g__H(int argc, char **argv)
2251 for(i = 1; i < argc; i++)
2252 Bprint(&bout, "%s ", argv[i]);
2253 Bprint(&bout, "\n");
2256 /* HTML page title */
2258 g__T(int argc, char **argv)
2263 Bprint(&bout, "<title>\n");
2264 printargs(argc, argv);
2265 Bprint(&bout, "</title></head><body>\n");
2270 g_nr(int argc, char **argv)
2279 dsnr(argv[1], val, &numregs);
2286 fprint(2, "stdin %d(%s:%d): division by 0\n",
2287 ssp->lno, ssp->filename, ssp->rlno);
2291 numval(char **pline, int recur)
2309 else while(*p >= '0' && *p <= '9')
2310 x = 10*x + *p++ - '0';
2337 x = x <= numval(&p, 0);
2340 x = x < numval(&p, 0);
2345 x = x >= numval(&p, 0);
2348 x = x > numval(&p, 0);
2353 x = x == numval(&p, 0);
2379 iftest(char *p, char **bp)
2390 if (c >= '0' && c <= '9' || c == '+' || c == '-' || c == '('/*)*/) {
2391 if (numval(&p,1) >= 1)
2404 for(p1 = ++p; *p != c; p++)
2409 while(*p && *p++ != c);
2419 while(*p == ' ' || *p == '\t')
2426 scanline(char *p, char *e, int wantnl)
2431 while((c = getrune()) == ' ' || c == '\t') ;
2445 p += runetochar(p, &r);
2453 pushbody(char *line)
2457 if (line[0] == '\\' && line[1] == '{' /*}*/ )
2459 if (strsp < Maxmstack - 1) {
2460 pushstr(b = strdup(line));
2461 mustfree[strsp] = b;
2466 skipbody(char *line)
2470 if (line[0] != '\\' || line[1] != '{' /*}*/ )
2473 while((c = getrune()) != '\\')
2479 else if ((c == '}' && (c = getrune()) == '\n' && !--n)
2486 ifstart(char *line, char *e, char **bp)
2491 b = copyline(line, e, 1);
2495 it = iftest(line, bp);
2500 g_ie(char *line, char *e)
2504 if (elsetop >= Maxif-1) {
2505 fprint(2, "ms2html: .ie's too deep\n");
2508 if (ifwastrue[++elsetop] = ifstart(line, e, &b))
2515 g_if(char *line, char *e)
2519 if (ifstart(line, e, &b))
2526 g_el(char *line, char *e)
2530 scanline(line, e, 1);
2531 if (ifwastrue[elsetop--])
2538 g_ig(int argc, char **argv)
2546 p = Brdline(&ssp->in, '\n');
2549 p[Blinelen(&ssp->in)-1] = 0;
2550 if(strcmp(p, s) == 0)
2556 g_ds(char *line, char *e)
2560 b = copyline(line, e, 1);
2570 g_as(char *line, char *e)
2575 b = copyline(line, e, 1);
2581 for(s = strings; s != nil; s = s->next)
2582 if(strcmp(line, s->name) == 0)
2590 s->val = realloc(s->val, strlen(s->val) + strlen(b) + 1);
2595 g_BS(int argc, char **argv)
2599 if (argc > 1 && !weBref) {
2600 Bprint(&bout, "<a href=\"%s\"", argv[1]);
2601 for(i = 2; i < argc; i++)
2602 Bprint(&bout, " %s", argv[i]);
2612 Bprint(&bout, "</a>");
2618 g_LB(int argc, char **argv)
2623 Bprint(&bout, "<a name=\"%s\"></a>", argv[1]);