added source files for converter
sophuwu sophie@skisiel.com
Wed, 10 Jan 2024 03:53:42 +0100
15 files changed,
4060 insertions(+),
1759 deletions(-)
M
main.go
→
main.go
@@ -1,7 +1,6 @@
package main import ( - "bytes" _ "embed" "fmt" "net/http"@@ -28,7 +27,7 @@ w.WriteHeader(http.StatusOK)
w.Write(css) }) http.Handle("/favicon.ico", http.NotFoundHandler()) - http.Handle("/", http.RedirectHandler("/cgi-bin/man/man2html", http.StatusTemporaryRedirect)) + http.Handle("/", handleTMP) http.ListenAndServe("0.0.0.0:3234", nil) }@@ -73,21 +72,15 @@ exe = "mansearch"
} cmd := exec.Command("/usr/lib/cgi-bin/man/"+exe, opt...) - fmt.Println(cmd.Args) - var buff bytes.Buffer - cmd.Stdout = &buff cmd.Env = append(cmd.Env, q) - cmd.Env = append(cmd.Env, "MANPATH=/usr/man:/usr/share/man:/usr/local/man:/usr/local/share/man:/usr/X11R6/man:/opt/man:/snap/man") + // cmd.Env = append(cmd.Env, "MANPATH=/usr/man:/usr/share/man:/usr/local/man:/usr/local/share/man:/usr/X11R6/man:/opt/man:/snap/man") - err := cmd.Run() - if err != nil { - return - } + b, _ := cmd.CombinedOutput() w.Header().Set("Content-Type", "text/html; charset=utf-8") w.WriteHeader(http.StatusOK) - page := buff.String() + page := string(b) page = page[strings.Index(page, "<!"):] i := strings.Index(page, "</HEAD>") if i == -1 {
D
man2html
A
man2htmlsrc/abbrev.c
@@ -0,0 +1,62 @@
+#include <string.h> +#include "defs.h" +/* + * lookup_abbrev() is used for TX macros - is that + * something SUN-specific? + */ + +char *abbrev_list[] = { + "GSBG", "Getting Started ", + "SUBG", "Customizing SunOS", + "SHBG", "Basic Troubleshooting", + "SVBG", "SunView User's Guide", + "MMBG", "Mail and Messages", + "DMBG", "Doing More with SunOS", + "UNBG", "Using the Network", + "GDBG", "Games, Demos & Other Pursuits", + "CHANGE", "SunOS 4.1 Release Manual", + "INSTALL", "Installing SunOS 4.1", + "ADMIN", "System and Network Administration", + "SECUR", "Security Features Guide", + "PROM", "PROM User's Manual", + "DIAG", "Sun System Diagnostics", + "SUNDIAG", "Sundiag User's Guide", + "MANPAGES", "SunOS Reference Manual", + "REFMAN", "SunOS Reference Manual", + "SSI", "Sun System Introduction", + "SSO", "System Services Overview", + "TEXT", "Editing Text Files", + "DOCS", "Formatting Documents", + "TROFF", "Using <B>nroff</B> and <B>troff</B>", + "INDEX", "Global Index", + "CPG", "C Programmer's Guide", + "CREF", "C Reference Manual", + "ASSY", "Assembly Language Reference", + "PUL", "Programming Utilities and Libraries", + "DEBUG", "Debugging Tools", + "NETP", "Network Programming", + "DRIVER", "Writing Device Drivers", + "STREAMS", "STREAMS Programming", + "SBDK", "SBus Developer's Kit", + "WDDS", "Writing Device Drivers for the SBus", + "FPOINT", "Floating-Point Programmer's Guide", + "SVPG", "SunView 1 Programmer's Guide", + "SVSPG", "SunView 1 System Programmer's Guide", + "PIXRCT", "Pixrect Reference Manual", + "CGI", "SunCGI Reference Manual", + "CORE", "SunCore Reference Manual", + "4ASSY", "Sun-4 Assembly Language Reference", + "SARCH", "<FONT SIZE=\"-1\">SPARC</FONT> Architecture Manual", + "KR", "The C Programming Language", + 0, 0 }; + +char *lookup_abbrev (char *s) +{ + int i=0; + + if (!s) + return ""; + while (abbrev_list[i] && strcmp(s, abbrev_list[i])) + i = i+2; + return abbrev_list[i] ? abbrev_list[i+1] : s; +}
A
man2htmlsrc/cgibase.c
@@ -0,0 +1,173 @@
+/* + * Here are the routines of man2html that output a HREF string. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <ctype.h> /* tolower() */ +#include <string.h> /* strlen() */ +#include "defs.h" +#include <errno.h> +#include <limits.h> + +/* + * The default is to use cgibase. With relative html style + * we generate URLs of the form "../manX/page.html". + */ +static int relat_html_style = 0; + +/* + * Either the user is non-local (or local, but using httpd), + * in which case we use http:/cgi-bin, or the user is local + * and uses lynx, and we use lynxcgi:/usr/lib/cgi-bin. + */ + +static char *man2htmlpath = "/cgi-bin/man/man2html"; /* default */ +static char *cgibase_format = "http://%s"; /* host.domain:port */ +static char *cgibase_ll_format = "lynxcgi:%s"; /* directory */ +static char *cgibase = ""; /* default */ + +/* + * Separator between URL and argument string. + * + * With http:<path to script>/a/b?c+d+e the script is called + * with PATH_INFO=/a/b and QUERY_STRING=c+d+e and args $1=c, $2=d, $3=e. + * With lynxcgi:<full path to script>?c+d+e no PATH_INFO is possible. + */ +static char sep = '?'; /* or '/' */ + +void +set_separator(char s) { + sep = s; +} + +void +set_lynxcgibase(char *s) { + int n = strlen(cgibase_ll_format) + strlen(s); + char *t = (char *) xmalloc(n); + + sprintf(t, cgibase_ll_format, s); + cgibase = t; +} + +void +set_cgibase(char *s) { + int n = strlen(cgibase_format) + strlen(s); + char *t = (char *) xmalloc(n); + + sprintf(t, cgibase_format, s); + cgibase = t; +} + +void +set_man2htmlpath(char *s) { + man2htmlpath = xstrdup(s); +} + +void +set_relative_html_links(void) { + relat_html_style = 1; +} + +/* What shall we say in case of relat_html_style? */ +static char *signature = "<HR>\n" +"This document was created by\n" +"<A HREF=\"%s%s\">man2html</A>,\n" +"using the manual pages.<BR>\n" +"%s\n"; + +#define TIMEFORMAT "%T GMT, %B %d, %Y" +#define TIMEBUFSZ 500 + +void print_sig() +{ + char timebuf[TIMEBUFSZ]; + struct tm *timetm; + time_t now; + char *source_date_epoch; + unsigned long long epoch; + char *endptr; + + timebuf[0] = 0; +#ifdef TIMEFORMAT + sprintf(timebuf, "Time: "); + source_date_epoch = getenv("SOURCE_DATE_EPOCH"); + if (source_date_epoch) { + errno = 0; + epoch = strtoull(source_date_epoch, &endptr, 10); + if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0)) + || (errno != 0 && epoch == 0)) { + fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: strtoull: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + if (endptr == source_date_epoch) { + fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: No digits were found: %s\n", endptr); + exit(EXIT_FAILURE); + } + if (*endptr != '\0') { + fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: Trailing garbage: %s\n", endptr); + exit(EXIT_FAILURE); + } + if (epoch > ULONG_MAX) { + fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to: %lu but was found to be: %llu \n", ULONG_MAX ,epoch); + exit(EXIT_FAILURE); + } + now=epoch; + } + else { + now=time(NULL); + } + timetm=gmtime(&now); + strftime(timebuf+6, TIMEBUFSZ-6, TIMEFORMAT, timetm); + timebuf[TIMEBUFSZ-1] = 0; +#endif + printf(signature, cgibase, man2htmlpath, timebuf); +} + +void +include_file_html(char *g) { + printf("<A HREF=\"file:///usr/include/%s\">%s</A>>", g,g); +} + +void +man_page_html(char *sec, char *h) { + if (relat_html_style) { + if (!h) + printf("<A HREF=\"../index.html\">" + "Return to Main Contents</A>"); + else + printf("<A HREF=\"../man%s/%s.%s.html\">%s</A>", + sec, h, sec, h); + } else { + if (!h) + printf("<A HREF=\"%s%s\">Return to Main Contents</A>", + cgibase, man2htmlpath); + else if (!sec) + printf("<A HREF=\"%s%s%c%s\">%s</A>", + cgibase, man2htmlpath, sep, h, h); + else + printf("<A HREF=\"%s%s%c%s+%s\">%s</A>", + cgibase, man2htmlpath, sep, sec, h, h); + } +} + +void +ftp_html(char *f) { + printf("<A HREF=\"ftp://%s\">%s</A>", f, f); +} + +void +www_html(char *f) { + printf("<A HREF=\"http://%s\">%s</A>", f, f); +} + +void +mailto_html(char *g) { + printf("<A HREF=\"mailto:%s\">%s</A>", g, g); +} + +void +url_html(char *g) { + printf("<A HREF=\"%s\">%s</A>", g, g); +}
A
man2htmlsrc/defs.h
@@ -0,0 +1,52 @@
+extern int nroff; +extern int local_lynx; + +typedef struct STRDEF STRDEF; +struct STRDEF { + int nr,slen; + char *st; + STRDEF *next; +}; + +typedef struct LONGSTRDEF LONGSTRDEF; +struct LONGSTRDEF { + int nr,slen; + char *longname; + char *st; + LONGSTRDEF *next; +}; + + +typedef struct INTDEF INTDEF; +struct INTDEF { + int nr; + int val; + int incr; + INTDEF *next; +}; + +extern STRDEF *chardef, *strdef; +extern LONGSTRDEF *defdef; +extern INTDEF *intdef; + +#define V(A,B) ((A)*256+(B)) + +#include <sys/types.h> +extern LONGSTRDEF *find_longstrdef(LONGSTRDEF* head, int nr, char * longname, char ** out_longname); +extern void stdinit(void); +extern void print_sig(void); +extern char *lookup_abbrev(char *); +extern void include_file_html(char *); +extern void man_page_html(char*, char *); +extern void ftp_html(char *); +extern void www_html(char *); +extern void mailto_html(char *); +extern void url_html(char *); +extern void set_separator(char); +extern void set_lynxcgibase(char *); +extern void set_cgibase(char *); +extern void set_man2htmlpath(char *); +extern void set_relative_html_links(void); +extern void *xmalloc(size_t size); +extern void *xrealloc(void *ptr, size_t size); +extern char *xstrdup(const char *s);
A
man2htmlsrc/man2html.c
@@ -0,0 +1,3419 @@
+/* +** This program was written by Richard Verhoeven (NL:5482ZX35) +** at the Eindhoven University of Technology. Email: rcb5@win.tue.nl +** +** Permission is granted to distribute, modify and use this program +** as long as this comment is not removed or changed. +*/ + +/* BSD mandoc stuff added by Michael Hamilton. */ + +/* This program is rather buggy, but in spite of that it often works. + Improved things a little - April 1997 & January 1998 & Dec 2001 - + aeb@cwi.nl. */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> +#include <sys/stat.h> +#include "defs.h" +//#include "../src/version.h" + +#define version "1" + +/* BSD mandoc Bd/Ed example(?) blocks */ +#define BD_LITERAL 1 +#define BD_INDENT 2 + +#define SIZE(a) (sizeof(a)/sizeof(*a)) +#define DOCTYPE "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n" +#define CONTENTTYPE "Content-type: text/html; charset=UTF-8\n\n" + +static char NEWLINE[2]="\n"; +static char idxlabel[6] = "ixAAA"; + +#define INDEXFILE "/tmp/manindex.list" + +char *fname; +char *directory; +FILE *idxfile; + +char eqndelimopen=0, eqndelimclose=0; +char escapesym='\\', nobreaksym='\'', controlsym='.', fieldsym=0, padsym=0; + +char *buffer=NULL; +int buffpos=0, buffmax=0; +int scaninbuff=0; +int still_dd=0; +int tabstops[20] = { 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96 }; +int maxtstop=12; +int curpos=0; + +static char *scan_troff(char *c, int san, char **result); +static char *scan_troff_mandoc(char *c, int san, char **result); + +static char **argument=NULL; + +static char charb[3]; + +#ifdef GUNZIP +/* from src/utils.c */ +static int +is_shell_safe(const char *ss, int quoted) { + char *bad = " ;'\\\"<>|"; + char *p; + + if (quoted) + bad++; /* allow a space inside quotes */ + for (p = bad; *p; p++) + if (strchr(ss, *p)) + return 0; + return 1; +} +#endif + +/* reads the entire manpage into buffer *buf and returns number of chars read */ +static int +read_manpage_into_buffer(char *path, char **buf) { + int compressed = 0; + FILE * f = NULL; + char * ext; + int l = 0; + struct stat stbuf; + + *buf = NULL; + if (!path) + return -1; + + if (!strcmp(path, "-")) + f = stdin; + else /* strcmp(path, "-") */ + { + char * tmp = NULL; + char * command = NULL; + char * openpath = path; +#ifdef GUNZIP + + if (is_shell_safe(openpath, 1)) { + ext = strrchr(openpath, '.'); + compressed = (ext && !strcmp(ext, ".gz")); + + if (!compressed && stat(openpath, &stbuf)) { + tmp = (char*) xmalloc(strlen(path) + 4); + sprintf(tmp, "%s.gz", path); + if ((compressed = !stat(tmp, &stbuf))) + openpath = tmp; + } + } + + if (compressed) { + command = (char*) xmalloc(strlen(openpath) + sizeof(GUNZIP) + 4); + sprintf(command, GUNZIP " '%s'", openpath); + f = popen(command, "r"); + } else +#endif + f = fopen(openpath, "r"); + + if (tmp) free(tmp); + if (command) free(command); + + if (!f) + return -1; + + } /* strcmp(path, "-") */ + + + /* Read entire file into buf[1..l] */ +#define XTRA 5 + /* buf has 1 extra byte at the start, and XTRA extra bytes at the end */ + if (compressed || f == stdin) { + int sz = 1024; + int ct = 1, tot = 0; + char *p = NULL; + + clearerr(f); + while (ct > 0) { + tot += ct; + if (feof(f)) + break; + sz = 2*sz+tot; + p = xrealloc(p, sz); + ct = fread(p+tot,1,sz-tot-XTRA,f); + } + + *buf = p; + l = tot-1; + } else { + int ct; + + l = 0; + if (fstat(fileno(f), &stbuf) != -1) + l = stbuf.st_size; + *buf = (char *) xmalloc((l+1+XTRA)*sizeof(char)); + ct = fread(*buf+1,1,l,f); + if (ct < l) + l = ct; + } + fclose(f); + return l; +} + +static char * +expand_char(int nr) +{ + STRDEF *h; + + if (!nr) + return NULL; + + h = chardef; + if (h->nr != V('*','*')) { + printf("chardef corrupted\n"); + exit(1); + } + + for (h = chardef; h; h = h->next) + if (h->nr == nr) { + curpos += h->slen; + return h->st; + } + charb[0] = nr/256; + charb[1] = nr%256; + charb[2] = 0; + curpos += 2; + return charb; +} + +static char * +expand_string(int nr) +{ + STRDEF *h; + + if (!nr) + return NULL; + for (h = strdef; h; h = h->next) + if (h->nr == nr) { + curpos += h->slen; + return h->st; + } + return NULL; +} + + +static char outbuffer[1024]; +static int obp=0; +static int no_newline_output=0; /* boolean, set by \c */ +static int newline_for_fun=0; +static int output_possible=0; +static int out_length=0; + +static void +add_links(char *c) +{ + /* + ** Add the links to the output. + ** At the moment the following are recognized: + ** + ** name(*) -> ../man?/name.* + ** method://string -> method://string + ** www.host.name -> http://www.host.name + ** ftp.host.name -> ftp://ftp.host.name + ** name@host -> mailto:name@host + ** <name.h> -> file:///usr/include/name.h (guess) + ** + ** Other possible links to add in the future: + ** + ** /dir/dir/file -> file:///dir/dir/file + */ + int i,j,nr; + char *f, *g, *h; + char *idtest[6]; /* url, mailto, www, ftp, man page, include file */ + + out_length+=strlen(c); + + nr=0; + idtest[0]=strstr(c+1,"://"); + idtest[1]=strchr(c+1,'@'); + idtest[2]=strstr(c,"www."); + idtest[3]=strstr(c,"ftp."); + idtest[4]=strchr(c+1,'('); + idtest[5]=strstr(c+1,".h>"); + for (i=0; i<6; i++) nr += (idtest[i]!=NULL); + while (nr) { + j=-1; + for (i=0; i<6; i++) + if (idtest[i] && (j<0 || idtest[i]<idtest[j])) j=i; + switch (j) { + case 5: /* <name.h> */ + f=idtest[5]; + h=f+2; + g=f; + while (g>c && g[-1]!=';') g--; + if (g!=c) { + char t; + t=*g; + *g=0; + printf("%s",c); + *g=t;*h=0; + include_file_html(g); + c=f+6; + } else { + f[5]=0; + printf("%s",c); + f[5]=';'; + c=f+5; + } + break; + case 4: /* man page? */ + f=idtest[j]; + /* find section - accept (1), (3F), (3Xt), (n), (l) */ + g=strchr(f,')'); + if (g && g-f<7 /* section has length at most 5, like 3Xlib */ + /* preceded by name or html markup */ + && (isalnum(f[-1]) || f[-1]=='>') + /* section is n or l or starts with a digit */ + && strchr("123456789nl", f[1]) + && (g-f == 2 || (g-f == 3 && isdigit(f[1]) && isalpha(f[2])) + || (f[2] == 'X' && isdigit(f[1])) + || (strncmp(f+1,"3pm",g-f-1) == 0)) + ) { + /* this might be a link */ + h=f-1; + /* skip html markup */ + while (h>c && *h=='>') { + while (h!=c && *h!='<') h--; + if (h!=c) h--; + } + if (isalnum(*h)) { + char t,te,tg,*e; + e=h+1; + while (h>c && (isalnum(h[-1]) || h[-1]=='_' || + h[-1]=='-' || h[-1]=='.' || h[-1]==':')) + h--; + t=*h; *h=0; + printf("%s", c); + *h=t; + tg=*g; *g=0; + te=*e; *e=0; + man_page_html(f+1, h); /* section, page */ + *e=te; + *g=tg; + c=e; + } + } + *f=0; + printf("%s", c); + *f='('; + idtest[4]=f-1; + c=f; + break; /* man page */ + case 3: /* ftp */ + case 2: /* www */ + g=f=idtest[j]; + while (*g && (isalnum(*g) || *g=='_' || *g=='-' || *g=='+' || + *g=='.')) g++; + if (g[-1]=='.') g--; + if (g-f>4) { + char t; + t=*f; *f=0; + printf("%s",c); + *f=t; t=*g;*g=0; + if (j==3) + ftp_html(f); + else + www_html(f); + *g=t; + c=g; + } else { + f[3]=0; + printf("%s",c); + c=f+3; + f[3]='.'; + } + break; + case 1: /* mailto */ + g=f=idtest[1]; + while (g>c && (isalnum(g[-1]) || g[-1]=='_' || g[-1]=='-' || + g[-1]=='+' || g[-1]=='.' || g[-1]=='%')) g--; + h=f+1; + while (*h && (isalnum(*h) || *h=='_' || *h=='-' || *h=='+' || + *h=='.')) h++; + if (h[-1]=='.') h--; + if (h-f>4 && f-g>1) { + char t; + t=*g; + *g=0; + printf("%s",c); + *g=t;t=*h;*h=0; + mailto_html(g); + *h=t; + c=h; + } else { + *f=0; + printf("%s",c); + *f='@'; + idtest[1]=c; + c=f; + } + break; + case 0: /* url */ + g=f=idtest[0]; + while (g>c && isalpha(g[-1]) && islower(g[-1])) g--; + h=f+3; + while (*h && !isspace(*h) && *h!='<' && *h!='>' && *h!='"' && + *h!='&') h++; + if (f-g>2 && f-g<7 && h-f>3) { + char t; + t=*g; + *g=0; + printf("%s", c); + *g=t; t=*h; *h=0; + url_html(g); + *h=t; + c=h; + } else { + f[1]=0; + printf("%s", c); + f[1]='/'; + c=f+1; + } + break; + default: + break; + } + nr=0; + if (idtest[0] && idtest[0]<c) idtest[0]=strstr(c+1,"://"); + if (idtest[1] && idtest[1]<c) idtest[1]=strchr(c+1,'@'); + if (idtest[2] && idtest[2]<c) idtest[2]=strstr(c,"www."); + if (idtest[3] && idtest[3]<c) idtest[3]=strstr(c,"ftp."); + if (idtest[4] && idtest[4]<c) idtest[4]=strchr(c+1,'('); + if (idtest[5] && idtest[5]<c) idtest[5]=strstr(c+1,".h>"); + for (i=0; i<6; i++) nr += (idtest[i]!=NULL); + } + printf("%s", c); +} + +int current_font=0; +int current_size=0; +int fillout = 1; + +/* + * Kludge: remove \a - in the context + * .TH NAME 2 date "Version" "Title" + * we got output \aTitle\a. + */ +static void +out_html(char *c) { + if (!c) + return; + if (no_newline_output) { /* remove \n if present */ + int i=0; + while (c[i]) { + if (!no_newline_output) + c[i-1]=c[i]; + if (c[i]=='\n') + no_newline_output=0; + i++; + } + if (!no_newline_output) + c[i-1]=0; + } + if (scaninbuff) { + while (*c) { + if (buffpos >= buffmax) { + buffer = xrealloc(buffer, buffmax*2); + buffmax = buffmax*2; + } + if (*c != '\a') + buffer[buffpos++] = *c; + c++; + } + } else if (output_possible) { + while (*c) { + if (*c != '\a') + outbuffer[obp++] = *c; + if (*c == '\n' || obp > 1000) { + outbuffer[obp] = 0; + add_links(outbuffer); + obp = 0; + } + c++; + } + } +} + +/* --------------------------------------------------------------- */ +/* All references to dl_set and itemdepth are here. */ +/* --------------------------------------------------------------- */ +static int itemdepth=0; +static int dl_set[30]= { 0 }; +#define noDL 0 +#define DL 1 +#define UL 2 +#define OL 3 +static char *dl_open[4] = { "", "<DL COMPACT>\n", "<UL>", "<OL>" }; +static char *dl_close[4] = { "", "</DL>\n", "</UL>", "</OL>" }; + +static inline void +dl_begin(void) { + if (itemdepth < SIZE(dl_set) && dl_set[itemdepth] == noDL) { + out_html(dl_open[DL]); + dl_set[itemdepth]=DL; + } + out_html("<DT>"); +} + +static inline void +dl_end(void) { + if (itemdepth < SIZE(dl_set)) { + int type = dl_set[itemdepth]; + if (type == DL) { + out_html(dl_close[type]); + dl_set[itemdepth]=noDL; + } + } +} + +static inline void +dl_newlevel(void) { + itemdepth++; + if (itemdepth < SIZE(dl_set)) + dl_set[itemdepth]=noDL; + out_html("<DL COMPACT><DT><DD>"); +} + +static inline void +dl_endlevel(void) { + if (itemdepth) { + dl_end(); + out_html("</DL>\n"); + itemdepth--; + } +} + +static inline void +dl_down(void) { + while (itemdepth) + dl_endlevel(); + dl_end(); +} + +static inline int +dl_type(int type) { + return (itemdepth < SIZE(dl_set) && dl_set[itemdepth] == type); +} + +static inline void +dl_newlevel_type(int type) { + itemdepth++; + if (itemdepth < SIZE(dl_set)) { + dl_set[itemdepth]=type; + out_html(dl_open[type]); + } +} + +static inline void +dl_endlevel_type(void) { + if (itemdepth) { + if (itemdepth < SIZE(dl_set)) + out_html(dl_close[dl_set[itemdepth]]); + itemdepth--; + } +} +/* --------------------------------------------------------------- */ +/* This stuff is broken. +It generates + <DT><B>TIOCLINUX, subcode=0<DD> + Dump the screen. + </B><I>argp</I> points to a +from + .IP "\fBTIOCLINUX, subcode=0" + Dump the screen. + \fIargp\fP points to a +Bug 1: incorrect nesting: </B> is needed before <DD>. +Bug 2: incorrect font: after the .IP things are roman again. +*/ + +#define FO0 "" +#define FC0 "" +#define FO1 "<I>" +#define FC1 "</I>" +#define FO2 "<B>" +#define FC2 "</B>" +#define FO3 "<TT>" +#define FC3 "</TT>" + +char *switchfont[16] = { "" , FC0 FO1, FC0 FO2, FC0 FO3, + FC1 FO0, "" , FC1 FO2, FC1 FO3, + FC2 FO0, FC2 FO1, "" , FC2 FO3, + FC3 FO0, FC3 FO1, FC3 FO2, "" }; + +static char * +change_to_font(int nr) +{ + int i; + switch (nr) { + case '0': nr++; + case '1': case '2': case '3': case '4': + nr = nr-'1'; break; + case V('C','W'): nr=3; break; + case 'L': nr=3; break; + case 'B': nr=2; break; + case 'I': nr=1; break; + case 0: case 1: case 2: case 3: + break; + case 'P': case 'R': + default: nr=0; break; + } + i= current_font*4+nr%4; + current_font=nr%4; + return switchfont[i]; +} + +static char sizebuf[200]; + +static char * +change_to_size(int nr) +{ + int i; + switch (nr) { + case '0': case '1': case '2': case '3': case '4': case '5': case '6': + case '7': case '8': case '9': nr=nr-'0'; break; + case '\0': break; + default: nr=current_size+nr; if (nr>9) nr=9; if (nr< -9) nr=-9; break; + } + if (nr==current_size) return ""; + i=current_font; + sizebuf[0]=0; + strcat(sizebuf, change_to_font(0)); + if (current_size) strcat(sizebuf, "</FONT>"); + current_size=nr; + if (nr) { + int l; + strcat(sizebuf, "<FONT SIZE=\""); + l=strlen(sizebuf); + if (nr>0) sizebuf[l++]='+'; else sizebuf[l++]='-',nr=-nr; + sizebuf[l++]=nr+'0'; + sizebuf[l++]='"'; + sizebuf[l++]='>'; + sizebuf[l]=0; + } + strcat(sizebuf, change_to_font(i)); + return sizebuf; +} + +int asint=0; +int intresult=0; + +#define SKIPEOL while (*c && *c++!='\n') + +static int skip_escape=0; +static int single_escape=0; + + +#define EXPAND_BRACKET for (c++, i=0; *c != ']'; c++) i = i * 256 + *c; if (i < 256) i = i * 256 + ' ' + +static char * +scan_escape(char *c) { + char *h=NULL; + char *tmp = NULL; + char b[10]; + INTDEF *intd; + int exoutputp,exskipescape; + int i,j; + + intresult=0; + switch (*c) { + case 'e': h="\\"; curpos++;break; + case '0': + case ' ': h=" ";curpos++; break; + case '|': h=""; break; + case '"': SKIPEOL; c--; h=""; break; + case '$': + if (argument) { + c++; + if (*c == '*' || *c == '@') { + int len = 0; + int quote = (*c == '@') ? 2 : 0; + + for (i = 0; ((h = argument[i])); i++) + len += strlen(h) + 1 + quote; + tmp = (char*) xmalloc(len + 1); + *tmp = 0; + + for (i = 0; ((h = argument[i])); i++) { + sprintf(tmp + strlen(tmp), " %s%s%s", + quote ? "\"" : "", + h, + quote ? "\"" : ""); + }; + h = tmp + 1; + } else { + i=(*c -'1'); + if (!(h=argument[i])) h=""; + } + } + break; + case 'z': + c++; + if (*c=='\\') { c=scan_escape(c+1); c--;h=""; } + else { + b[0]=*c; + b[1]=0; + h=""; + } + break; + case 'k': c++; if (*c=='(') c+=2; + case '^': + case '!': + case '%': + case ':': + case 'a': + case 'd': + case 'r': + case 'u': + case '\n': + case '&': h=""; break; + case '(': + c++; + i= c[0]*256+c[1]; + c++; + h = expand_char(i); + break; + case '[': + EXPAND_BRACKET; + h = expand_char(i); + break; + case '*': + c++; + if (*c=='(') { + c++; + i= c[0]*256+c[1]; + c++; + } else if (*c == '[') { + EXPAND_BRACKET; + } else + i= *c *256+' '; + h = expand_string(i); + break; + case 'f': + c++; + if (*c=='\\') { + c++; + c=scan_escape(c); + c--; + i=intresult; + } else if (*c == '[') { + EXPAND_BRACKET; + } else if (*c != '(') + i=*c; + else { + c++; + i=c[0]*256+c[1]; + c++; + } + if (!skip_escape) h=change_to_font(i); else h=""; + break; + case 's': + c++; + j=0;i=0; + if (*c=='-') {j= -1; c++;} else if (*c=='+') {j=1; c++;} + if (*c=='0') c++; else if (*c=='\\') { + c++; + c=scan_escape(c); + i=intresult; if (!j) j=1; + } else + while (isdigit(*c) && (!i || (!j && i<4))) i=i*10+(*c++)-'0'; + if (!j) { j=1; if (i) i=i-10; } + if (!skip_escape) h=change_to_size(i*j); else h=""; + c--; + break; + case 'n': + c++; + j=0; + switch (*c) { + case '+': j=1; c++; break; + case '-': j=-1; c++; break; + default: break; + } + if (*c=='(') { + c++; + i=V(c[0],c[1]); + c=c+1; + } else { + i=V(c[0],' '); + } + intd=intdef; + while (intd && intd->nr!=i) intd=intd->next; + if (intd) { + intd->val=intd->val+j*intd->incr; + intresult=intd->val; + } else { + switch (i) { + case V('.','s'): intresult=current_size; break; + case V('.','f'): intresult=current_font; break; + default: intresult=0; break; + } + } + h=""; + break; + case 'w': + c++; + i=*c; + c++; + exoutputp=output_possible; + exskipescape=skip_escape; + output_possible=0; + skip_escape=1; + j=0; + while (*c!=i) { + j++; + if (*c==escapesym) c=scan_escape(c+1); else c++; + } + output_possible=exoutputp; + skip_escape=exskipescape; + intresult=j; + break; + case 'l': h="<HR>"; curpos=0; + case 'b': + case 'v': + case 'x': + case 'o': + case 'L': + case 'h': + c++; + i=*c; + c++; + exoutputp=output_possible; + exskipescape=skip_escape; + output_possible=0; + skip_escape=1; + while (*c != i) + if (*c==escapesym) c=scan_escape(c+1); + else c++; + output_possible=exoutputp; + skip_escape=exskipescape; + break; + case 'N': + /* convert \N'ddd' into &#ddd; */ + c++; + i=*c; + j=0; + b[j++] = '&'; + b[j++] = '#'; + while (*(++c) != i) + if (isdigit(*c) && j < sizeof(b) - 2) + b[j++] = *c; + b[j++] = ';'; + b[j] = '\0'; + h = b; + break; + case 'c': no_newline_output=1; break; + case '{': newline_for_fun++; h="";break; + case '}': if (newline_for_fun) newline_for_fun--; h="";break; + case 'p': h="<BR>\n";curpos=0; break; + case 't': h="\t";curpos=(curpos+8)&0xfff8; break; + case '<': h="<";curpos++; break; + case '>': h=">";curpos++; break; + case '\\': if (single_escape) { c--; break;} + default: b[0]=*c; b[1]=0; h=b; curpos++; break; + } + c++; + if (!skip_escape) out_html(h); + if (tmp) free(tmp); + return c; +} + +typedef struct TABLEITEM TABLEITEM; + +struct TABLEITEM { + char *contents; + int size,align,valign,colspan,rowspan,font,vleft,vright,space,width; + TABLEITEM *next; +}; + +static TABLEITEM emptyfield = {NULL,0,0,0,1,1,0,0,0,0,0,NULL}; +typedef struct TABLEROW TABLEROW; + +struct TABLEROW { + TABLEITEM *first; + TABLEROW *prev, *next; +}; + +static char *tableopt[]= { "center", "expand", "box", "allbox", "doublebox", + "tab", "linesize", "delim", NULL }; +static int tableoptl[] = { 6,6,3,6,9,3,8,5,0}; + + +static void clear_table(TABLEROW *table) +{ + TABLEROW *tr1,*tr2; + TABLEITEM *ti1,*ti2; + + tr1=table; + while (tr1->prev) tr1=tr1->prev; + while (tr1) { + ti1=tr1->first; + while (ti1) { + ti2=ti1->next; + if (ti1->contents) free(ti1->contents); + free(ti1); + ti1=ti2; + } + tr2=tr1; + tr1=tr1->next; + free(tr2); + } +} + +char *scan_expression(char *c, int *result); + +static char *scan_format(char *c, TABLEROW **result, int *maxcol) +{ + TABLEROW *layout, *currow; + TABLEITEM *curfield; + int i,j; + if (*result) { + clear_table(*result); + } + layout= currow=(TABLEROW*) xmalloc(sizeof(TABLEROW)); + currow->next=currow->prev=NULL; + currow->first=curfield=(TABLEITEM*) xmalloc(sizeof(TABLEITEM)); + *curfield=emptyfield; + while (*c && *c!='.') { + switch (*c) { + case 'C': case 'c': case 'N': case 'n': + case 'R': case 'r': case 'A': case 'a': + case 'L': case 'l': case 'S': case 's': + case '^': case '_': + if (curfield->align) { + curfield->next=(TABLEITEM*)xmalloc(sizeof(TABLEITEM)); + curfield=curfield->next; + *curfield=emptyfield; + } + curfield->align=toupper(*c); + c++; + break; + case 'i': case 'I': case 'B': case 'b': + curfield->font = toupper(*c); + c++; + break; + case 'f': case 'F': + c++; + curfield->font = toupper(*c); + if (*c != '.') c++; + if (*c != '.' && !isspace(*c)) c++; + break; + case 't': case 'T': curfield->valign='t'; c++; break; + case 'p': case 'P': + c++; + i=j=0; + if (*c=='+') { j=1; c++; } + if (*c=='-') { j=-1; c++; } + while (isdigit(*c)) i=i*10+(*c++)-'0'; + if (j) curfield->size= i*j; else curfield->size=j-10; + break; + case 'v': case 'V': + case 'w': case 'W': +// c=scan_expression(c+2,&curfield->width); + c++; + if (*c == '(') { + c=scan_expression(c+1,&curfield->width); + } else { + i=0; + while (isdigit(*c)) i=i*10+(*c++)-'0'; + curfield->width=i; + } + break; + case '|': + if (curfield->align) curfield->vleft++; + else curfield->vright++; + c++; + break; + case 'e': case 'E': + c++; + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + i=0; + while (isdigit(*c)) i=i*10+(*c++)-'0'; + curfield->space=i; + break; + case ',': case '\n': + currow->next=(TABLEROW*)xmalloc(sizeof(TABLEROW)); + currow->next->prev=currow; + currow=currow->next; + currow->next=NULL; + curfield=currow->first=(TABLEITEM*)xmalloc(sizeof(TABLEITEM)); + *curfield=emptyfield; + c++; + break; + default: + c++; + break; + } + } + if (*c=='.') while (*c++!='\n'); + *maxcol=0; + currow=layout; + while (currow) { + curfield=layout->first; + i=0; + while (curfield) { + i++; + curfield=curfield->next; + } + if (i>*maxcol) *maxcol=i; + currow=currow->next; + } + *result=layout; + return c; +} + +static TABLEROW * +next_row(TABLEROW *tr) +{ + if (tr->next) { + tr=tr->next; + if (!tr->next) next_row(tr); + return tr; + } else { + TABLEITEM *ti, *ti2; + tr->next=(TABLEROW*)xmalloc(sizeof(TABLEROW)); + tr->next->prev=tr; + ti=tr->first; + tr=tr->next; + tr->next=NULL; + if (ti) tr->first=ti2=(TABLEITEM*) xmalloc(sizeof(TABLEITEM)); + else tr->first=ti2=NULL; + while (ti!=ti2) { + *ti2=*ti; + ti2->contents=NULL; + if ((ti=ti->next)) { + ti2->next=(TABLEITEM*) xmalloc(sizeof(TABLEITEM)); + } + ti2=ti2->next; + } + return tr; + } +} + +char itemreset[20]="\\fR\\s0"; + +static char * +scan_table(char *c) { + char *h; + char *g; + int center=0, expand=0, box=0, border=0, linesize=1; + int i,j,maxcol=0, finished=0; + int oldfont, oldsize,oldfillout; + char itemsep='\t'; + TABLEROW *layout=NULL, *currow; + TABLEITEM *curfield; + while (*c++!='\n'); /* skip TS */ + h=c; + if (*h=='.') return c-1; + oldfont=current_font; + oldsize=current_size; + oldfillout=fillout; + out_html(change_to_font(0)); + out_html(change_to_size(0)); + if (!fillout) { + fillout=1; + out_html("</PRE>"); + } + while (*h && *h!='\n') h++; + if (h[-1]==';') { + /* scan table options */ + while (c<h) { + while (isspace(*c)) c++; + for (i=0; tableopt[i] && strncmp(tableopt[i],c,tableoptl[i]);i++); + c=c+tableoptl[i]; + switch (i) { + case 0: center=1; break; + case 1: expand=1; break; + case 2: box=1; break; + case 3: border=1; break; + case 4: box=2; break; + case 5: while (*c++!='('); itemsep=*c++; break; + case 6: while (*c++!='('); linesize=0; + while (isdigit(*c)) linesize=linesize*10+(*c++)-'0'; + break; + case 7: while (*c!=')') c++; + default: break; + } + c++; + } + c=h+1; + } + /* scan layout */ + c=scan_format(c,&layout, &maxcol); + currow=layout; + next_row(currow); + curfield=layout->first; + i=0; + while (!finished && *c) { + /* search item */ + h=c; + if ((*c=='_' || *c=='=') && (c[1]==itemsep || c[1]=='\n')) { + if (c[-1]=='\n' && c[1]=='\n') { + if (currow->prev) { + currow->prev->next=(TABLEROW*) xmalloc(sizeof(TABLEROW)); + currow->prev->next->next=currow; + currow->prev->next->prev=currow->prev; + currow->prev=currow->prev->next; + } else { + currow->prev=layout=(TABLEROW*) xmalloc(sizeof(TABLEROW)); + currow->prev->prev=NULL; + currow->prev->next=currow; + } + curfield=currow->prev->first= + (TABLEITEM*) xmalloc(sizeof(TABLEITEM)); + *curfield=emptyfield; + curfield->align=*c; + curfield->colspan=maxcol; + curfield=currow->first; + c=c+2; + } else { + if (curfield) { + curfield->align=*c; + do { + curfield=curfield->next; + } while (curfield && curfield->align=='S'); + } + if (c[1]=='\n') { + currow=next_row(currow); + curfield=currow->first; + } + c=c+2; + } + } else if (*c=='T' && c[1]=='{') { + h=c+2; + c=strstr(h,"\nT}"); + c++; + *c=0; + g=NULL; + scan_troff(h, 0, &g); + scan_troff(itemreset, 0, &g); + *c='T'; + c+=3; + if (curfield) { + curfield->contents=g; + do { + curfield=curfield->next; + } while (curfield && curfield->align=='S'); + } else + if (g) free(g); + if (c[-1]=='\n') { + currow=next_row(currow); + curfield=currow->first; + } + } else if (*c=='.' && c[1]=='T' && c[2]=='&' && c[-1]=='\n') { + TABLEROW *hr; + while (*c++!='\n'); + hr=currow; + currow=currow->prev; + hr->prev=NULL; + c=scan_format(c,&hr, &i); + hr->prev=currow; + currow->next=hr; + currow=hr; + next_row(currow); + curfield=currow->first; + } else if (*c=='.' && c[1]=='T' && c[2]=='E' && c[-1]=='\n') { + finished=1; + while (*c++!='\n'); + if (currow->prev) + currow->prev->next=NULL; + currow->prev=NULL; + clear_table(currow); + } else if (*c=='.' && c[-1]=='\n' && !isdigit(c[1])) { + /* skip troff request inside table (usually only .sp ) */ + while (*c++!='\n'); + } else { + h=c; + while (*c && (*c!=itemsep || c[-1]=='\\') && + (*c!='\n' || c[-1]=='\\')) c++; + i=0; + if (*c==itemsep) {i=1; *c='\n'; } + if (h[0]=='\\' && h[2]=='\n' && + (h[1]=='_' || h[1]=='^')) { + if (curfield) { + curfield->align=h[1]; + do { + curfield=curfield->next; + } while (curfield && curfield->align=='S'); + } + h=h+3; + } else { + g=NULL; + h=scan_troff(h,1,&g); + scan_troff(itemreset,0,&g); + if (curfield) { + curfield->contents=g; + do { + curfield=curfield->next; + } while (curfield && curfield->align=='S'); + } else if (g) free(g); + } + if (i) *c=itemsep; + c=h; + if (c[-1]=='\n') { + currow=next_row(currow); + curfield=currow->first; + } + } + } + /* calculate colspan and rowspan */ + currow=layout; + while (currow->next) currow=currow->next; + while (currow) { + TABLEITEM *ti, *ti1=NULL, *ti2=NULL; + ti=currow->first; + if (currow->prev) ti1=currow->prev->first; + while (ti) { + switch (ti->align) { + case 'S': + if (ti2) { + ti2->colspan++; + if (ti2->rowspan<ti->rowspan) ti2->rowspan=ti->rowspan; + } + break; + case '^': + if (ti1) ti1->rowspan++; + default: + if (!ti2) ti2=ti; + else { + do { + ti2=ti2->next; + } while (ti2 && curfield->align=='S'); + } + break; + } + ti=ti->next; + if (ti1) ti1=ti1->next; + } + currow=currow->prev; + } + /* produce html output */ + if (center) out_html("<CENTER>"); + if (box==2) out_html("<TABLE BORDER><TR><TD>"); + out_html("<TABLE"); + if (box || border) { + out_html(" BORDER"); + if (!border) out_html("><TR><TD><TABLE"); + if (expand) out_html(" WIDTH=100%"); + } + out_html(">\n"); + currow=layout; + while (currow) { + j=0; + out_html("<TR VALIGN=top>"); + curfield=currow->first; + while (curfield) { + if (curfield->align!='S' && curfield->align!='^') { + out_html("<TD"); + switch (curfield->align) { + case 'N': + curfield->space+=4; + case 'R': + out_html(" ALIGN=right"); + break; + case 'C': + out_html(" ALIGN=center"); + default: + break; + } + if (!curfield->valign && curfield->rowspan>1) + out_html(" VALIGN=center"); + if (curfield->colspan>1) { + char buf[5]; + out_html(" COLSPAN="); + sprintf(buf, "%i", curfield->colspan); + out_html(buf); + } + if (curfield->rowspan>1) { + char buf[5]; + out_html(" ROWSPAN="); + sprintf(buf, "%i", curfield->rowspan); + out_html(buf); + } + j=j+curfield->colspan; + out_html(">"); + if (curfield->size) out_html(change_to_size(curfield->size)); + if (curfield->font) out_html(change_to_font(curfield->font)); + switch (curfield->align) { + case '=': out_html("<HR><HR>"); break; + case '_': out_html("<HR>"); break; + default: + if (curfield->contents) out_html(curfield->contents); + break; + } + if (curfield->space) + for (i=0; i<curfield->space;i++) out_html(" "); + if (curfield->font) out_html(change_to_font(0)); + if (curfield->size) out_html(change_to_size(0)); + if (j>=maxcol && curfield->align>'@' && curfield->align!='_') + out_html("<BR>"); + out_html("</TD>"); + } + curfield=curfield->next; + } + out_html("</TR>\n"); + currow=currow->next; + } + if (box && !border) out_html("</TABLE>"); + out_html("</TABLE>"); + if (box==2) out_html("</TABLE>"); + if (center) out_html("</CENTER>\n"); + else out_html("\n"); + if (!oldfillout) out_html("<PRE>"); + fillout=oldfillout; + out_html(change_to_size(oldsize)); + out_html(change_to_font(oldfont)); + return c; +} + +char *scan_expression(char *c, int *result) { + int value=0,value2,sign=1,opex=0; + char oper='c'; + + if (*c=='!') { + c=scan_expression(c+1, &value); + value= (!value); + } else if (*c=='n') { + c++; + value=nroff; + } else if (*c=='t') { + c++; + value=1-nroff; + } else if (*c=='\'' || *c=='"' || *c<' ' || (*c=='\\' && c[1]=='(')) { + /* ?string1?string2? + ** test if string1 equals string2. + */ + char *st1=NULL, *st2=NULL, *h; + char *tcmp=NULL; + char sep; + sep=*c; + if (sep=='\\') { + tcmp=c; + c=c+3; + } + c++; + h=c; + while (*c!= sep && (!tcmp || strncmp(c,tcmp,4))) c++; + *c='\n'; + scan_troff(h, 1, &st1); + *c=sep; + if (tcmp) c=c+3; + c++; + h=c; + while (*c!=sep && (!tcmp || strncmp(c,tcmp,4))) c++; + *c='\n'; + scan_troff(h,1,&st2); + *c=sep; + if (!st1 && !st2) value=1; + else if (!st1 || !st2) value=0; + else value=(!strcmp(st1, st2)); + if (st1) free(st1); + if (st2) free(st2); + if (tcmp) c=c+3; + c++; + } else { + while (*c && !isspace(*c) && *c!=')') { + opex=0; + switch (*c) { + case '(': + c=scan_expression(c+1, &value2); + value2=sign*value2; + opex=1; + break; + case '.': + case '0': case '1': + case '2': case '3': + case '4': case '5': + case '6': case '7': + case '8': case '9': { + int num=0,denum=1; + value2=0; + while (isdigit(*c)) value2=value2*10+((*c++)-'0'); + if (*c=='.') { + c++; + while (isdigit(*c)) { + num=num*10+((*c++)-'0'); + denum=denum*10; + } + } + if (isalpha(*c)) { + /* scale indicator */ + switch (*c) { + case 'i': /* inch -> 10pt */ + value2=value2*10+(num*10+denum/2)/denum; + num=0; + break; + default: + break; + } + c++; + } + value2=value2+(num+denum/2)/denum; + value2=sign*value2; + opex=1; + break; + } + case '\\': + c=scan_escape(c+1); + value2=intresult*sign; + if (isalpha(*c)) c++; /* scale indicator */ + opex=1; + break; + case '-': + if (oper) { sign=-1; c++; break; } + case '>': + case '<': + case '+': + case '/': + case '*': + case '%': + case '&': + case '=': + case ':': + if (c[1]=='=') oper=(*c++) +16; else oper=*c; + c++; + break; + default: c++; break; + } + if (opex) { + sign=1; + switch (oper) { + case 'c': value=value2; break; + case '-': value=value-value2; break; + case '+': value=value+value2; break; + case '*': value=value*value2; break; + case '/': if (value2) value=value/value2; break; + case '%': if (value2) value=value%value2; break; + case '<': value=(value<value2); break; + case '>': value=(value>value2); break; + case '>'+16: value=(value>=value2); break; + case '<'+16: value=(value<=value2); break; + case '=': case '='+16: value=(value==value2); break; + case '&': value = (value && value2); break; + case ':': value = (value || value2); break; + default: fprintf(stderr, + "man2html: Unknown operator %c.\n", oper); + } + oper=0; + } + } + if (*c==')') c++; + } + *result=value; + return c; +} + +static void +trans_char(char *c, char s, char t) { + char *sl = c; + int slash = 0; + + while (*sl && (*sl != '\n' || slash)) { + if (!slash) { + if (*sl == escapesym) + slash = 1; + else if (*sl == s) + *sl = t; + } else + slash = 0; + sl++; + } +} + +/* + * Read STR until end-of-line (not preceded by \). + * Find whitespace separated words, and store starts in WORDS of lth MAXN. + * Return number of words in N. + * Replace each end-of-word by the character EOW (usually \n or 0). + * Return pointer to last char seen (either \n or 0). + * + * A part \"... is skipped. + * Quotes not preceded by \ are replaced by \a. + */ +static char * +fill_words(char *str, char *words[], int maxn, int *n, char eow) { + char *s = str, *t; + int backslash = 0; + int skipspace = 0; /* 1 if space is not end-of-word */ + + *n = 0; + words[*n] = s; + while (*s && (*s != '\n' || backslash)) { + if (!backslash) { + if (*s == '"') { + if (skipspace && *(s+1) == '"') { + /* "" inside the quoted text means " */ + for (t = s++; t > words[*n]; t--) + *t = *(t-1); + words[*n]++; + } else { + *s = '\a'; + skipspace = !skipspace; + } + } else if (*s == escapesym) { + backslash = 1; + } else if ((*s == ' ' || *s == '\t') && !skipspace) { + *s = eow; + if (words[*n] != s && *n < maxn-1) + (*n)++; + words[*n] = s+1; + } + } else { + if (*s == '"') { + s--; + *s = eow; + if (words[*n] != s && *n < maxn-1) + (*n)++; + s++; + while (*s && *s != '\n') s++; + words[*n] = s; + s--; + } + backslash = 0; + } + s++; + } + if (s != words[*n]) + (*n)++; + return s; +} + + +char *section_list[] = { + "1", "User Commands ", + "1C", "User Commands", + "1G", "User Commands", + "1S", "User Commands", + "1V", "User Commands ", + "2", "System Calls", + "2V", "System Calls", + "3", "C Library Functions", + "3C", "Compatibility Functions", + "3F", "Fortran Library Routines", + "3K", "Kernel VM Library Functions", + "3L", "Lightweight Processes Library", + "3M", "Mathematical Library", + "3N", "Network Functions", + "3R", "RPC Services Library", + "3S", "Standard I/O Functions", + "3V", "C Library Functions", + "3X", "Miscellaneous Library Functions", + "4", "Devices and Network Interfaces", + "4F", "Protocol Families", + "4I", "Devices and Network Interfaces", + "4M", "Devices and Network Interfaces", + "4N", "Devices and Network Interfaces", + "4P", "Protocols", + "4S", "Devices and Network Interfaces", + "4V", "Devices and Network Interfaces", + "5", "File Formats", + "5V", "File Formats", + "6", "Games and Demos", + "7", "Environments, Tables, and Troff Macros", + "7V", "Environments, Tables, and Troff Macros", + "8", "Maintenance Commands", + "8C", "Maintenance Commands", + "8S", "Maintenance Commands", + "8V", "Maintenance Commands", + "L", "Local Commands", +/* for Solaris: + "1", "User Commands", + "1B", "SunOS/BSD Compatibility Package Commands", + "1b", "SunOS/BSD Compatibility Package Commands", + "1C", "Communication Commands ", + "1c", "Communication Commands", + "1F", "FMLI Commands ", + "1f", "FMLI Commands", + "1G", "Graphics and CAD Commands ", + "1g", "Graphics and CAD Commands ", + "1M", "Maintenance Commands", + "1m", "Maintenance Commands", + "1S", "SunOS Specific Commands", + "1s", "SunOS Specific Commands", + "2", "System Calls", + "3", "C Library Functions", + "3B", "SunOS/BSD Compatibility Library Functions", + "3b", "SunOS/BSD Compatibility Library Functions", + "3C", "C Library Functions", + "3c", "C Library Functions", + "3E", "C Library Functions", + "3e", "C Library Functions", + "3F", "Fortran Library Routines", + "3f", "Fortran Library Routines", + "3G", "C Library Functions", + "3g", "C Library Functions", + "3I", "Wide Character Functions", + "3i", "Wide Character Functions", + "3K", "Kernel VM Library Functions", + "3k", "Kernel VM Library Functions", + "3L", "Lightweight Processes Library", + "3l", "Lightweight Processes Library", + "3M", "Mathematical Library", + "3m", "Mathematical Library", + "3N", "Network Functions", + "3n", "Network Functions", + "3R", "Realtime Library", + "3r", "Realtime Library", + "3S", "Standard I/O Functions", + "3s", "Standard I/O Functions", + "3T", "Threads Library", + "3t", "Threads Library", + "3W", "C Library Functions", + "3w", "C Library Functions", + "3X", "Miscellaneous Library Functions", + "3x", "Miscellaneous Library Functions", + "4", "File Formats", + "4B", "SunOS/BSD Compatibility Package File Formats", + "4b", "SunOS/BSD Compatibility Package File Formats", + "5", "Headers, Tables, and Macros", + "6", "Games and Demos", + "7", "Special Files", + "7B", "SunOS/BSD Compatibility Special Files", + "7b", "SunOS/BSD Compatibility Special Files", + "8", "Maintenance Procedures", + "8C", "Maintenance Procedures", + "8c", "Maintenance Procedures", + "8S", "Maintenance Procedures", + "8s", "Maintenance Procedures", + "9", "DDI and DKI", + "9E", "DDI and DKI Driver Entry Points", + "9e", "DDI and DKI Driver Entry Points", + "9F", "DDI and DKI Kernel Functions", + "9f", "DDI and DKI Kernel Functions", + "9S", "DDI and DKI Data Structures", + "9s", "DDI and DKI Data Structures", + "L", "Local Commands", +*/ + NULL, "Misc. Reference Manual Pages", + NULL, NULL +}; + +static char * +section_name(char *c) +{ + int i=0; + + if (!c) return ""; + while (section_list[i] && strcmp(c,section_list[i])) i=i+2; + if (section_list[i+1]) return section_list[i+1]; + else return c; +} + +int manidxlen = 0; +char *manidx = NULL; +int subs = 0; +int mip = 0; /* current offset in manidx[] */ +char label[5]="lbAA"; + +static void +manidx_need(int m) { + if (mip + m >= manidxlen) { + manidxlen += 10000; + manidx = xrealloc(manidx, manidxlen); + } +} + +static void +add_to_index(int level, char *item) +{ + char *c = NULL; + + label[3]++; + if (label[3]>'Z') { + label[3]='A'; + label[2]++; + } + + if (level != subs) { + manidx_need(6); + if (subs) { + strcpy(manidx+mip, "</DL>\n"); + mip += 6; + } else { + strcpy(manidx+mip, "<DL>\n"); + mip += 5; + } + } + subs = level; + + scan_troff(item, 1, &c); + manidx_need(100 + strlen(c)); + sprintf(manidx+mip, "<DT><A HREF=\"#%s\">%s</A><DD>\n", label, c); + if (c) free(c); + while (manidx[mip]) mip++; +} + +static char * +skip_till_newline(char *c) +{ + int lvl=0; + + while (*c && (*c!='\n' || lvl>0)) { + if (*c=='\\') { + c++; + if (*c=='}') lvl--; else if (*c=='{') lvl++; + } + c++; + } + c++; + if (lvl<0 && newline_for_fun) { + newline_for_fun = newline_for_fun+lvl; + if (newline_for_fun<0) newline_for_fun=0; + } + return c; +} + +int ifelseval=0; + +static char * +scan_request(char *c) { + /* BSD Mandoc stuff - by Michael Hamilton */ + static int mandoc_synopsis=0; /* True if we are in the synopsis section */ + static int mandoc_command=0; /* True if this is mandoc page */ + static int mandoc_bd_options; /* Only copes with non-nested Bd's */ + static int inXo=0; + + int i,j,mode = 0; + char *h; + char *wordlist[30]; + int words; + char *sl; + LONGSTRDEF *owndef; + + while (*c == ' ' || *c == '\t') + c++; + if (c[0] == '\n') + return c+1; + if (c[1] == '\n') + j = 1; + else + j = 2; + while (c[j] == ' ' || c[j] == '\t') + j++; + if (c[0] == escapesym) { + /* some pages use .\" .\$1 .\} */ + /* .\$1 is too difficult/stupid */ + if (c[1] == '$') + c = skip_till_newline(c); + else + c = scan_escape(c+1); + } else { + i=V(c[0],c[1]); + /* search macro database of self-defined macros */ + owndef = find_longstrdef(defdef, i, c, NULL); + if (owndef) { + char **oldargument; + int deflen; + int onff; + sl=fill_words(c+strlen(owndef->longname), wordlist, SIZE(wordlist), &words, '\n'); + c=sl+1; + *sl=0; + for (i=1; i<words; i++) + wordlist[i][-1]=0; + for (i=0; i<words; i++) { + char *hl=NULL; + if (mandoc_command) + scan_troff_mandoc(wordlist[i],1,&hl); + else + scan_troff(wordlist[i],2,&hl); + wordlist[i]=hl; + } + for (i=words; i<SIZE(wordlist); i++) + wordlist[i]=NULL; + deflen = strlen(owndef->st); + owndef->st[deflen+1]='a'; + for (i=0; (owndef->st[deflen+2+i] = owndef->st[i]); i++); + oldargument=argument; + argument=wordlist; + onff=newline_for_fun; + if (mandoc_command) + scan_troff_mandoc(owndef->st+deflen+2, 0, NULL); + else + scan_troff(owndef->st+deflen+2, 0, NULL); + newline_for_fun=onff; + argument=oldargument; + for (i=0; i<words; i++) if (wordlist[i]) free(wordlist[i]); + owndef->st[deflen+1]=0; + *sl='\n'; + } else switch (i) { + case V('a','b'): + h=c+j; + while (*h && *h !='\n') h++; + *h=0; + if (scaninbuff && buffpos) { + buffer[buffpos]=0; + printf("%s\n", buffer); + } + fprintf(stderr, "%s\n", c+2); /* XXX */ + exit(0); + break; + case V('d','i'): + { + STRDEF *de; + c=c+j; + i=V(c[0],c[1]); + if (*c == '\n') { c++;break; } + while (*c && *c!='\n') c++; + c++; + h=c; + while (*c && strncmp(c,".di",3)) while (*c && *c++!='\n'); + *c=0; + de=strdef; + while (de && de->nr !=i) de=de->next; + if (!de) { + de=(STRDEF*) xmalloc(sizeof(STRDEF)); + de->nr=i; + de->slen=0; + de->next=strdef; + de->st=NULL; + strdef=de; + } else { + if (de->st) free(de->st); + de->slen=0; + de->st=NULL; + } + scan_troff(h,0,&de->st); + *c='.'; + while (*c && *c++!='\n'); + break; + } + case V('d','s'): + mode=1; + case V('a','s'): + { + STRDEF *de; + int oldcurpos=curpos; + c=c+j; + while (*c == ' ') c++; + i=V(c[0],c[1]); + j=0; + while (c[j] && c[j]!='\n') j++; + if (j<3) { c=c+j; break; } + if (c[1] == ' ') c=c+1; else c=c+2; + while (isspace(*c)) c++; + if (*c == '"') c++; + de=strdef; + while (de && de->nr != i) de=de->next; + single_escape=1; + curpos=0; + if (!de) { + char *hl; + de=(STRDEF*) xmalloc(sizeof(STRDEF)); + de->nr=i; + de->slen=0; + de->next=strdef; + de->st=NULL; + strdef=de; + hl=NULL; + c=scan_troff(c, 1, &hl); + de->st=hl; + de->slen=curpos; + } else { + if (mode) { /* .ds */ + char *hl=NULL; + c=scan_troff(c, 1, &hl); + free(de->st); /* segfault XXX */ + de->slen=curpos; + de->st=hl; + } else { /* .as */ + c=scan_troff(c,1,&de->st); /* XXX */ + de->slen+=curpos; + } + } + single_escape=0; + curpos=oldcurpos; + } + break; + case V('b','r'): + if (still_dd) out_html("<DD>"); + else out_html("<BR>\n"); + curpos=0; + c=c+j; + if (c[0] == escapesym) { c=scan_escape(c+1); } + c=skip_till_newline(c);break; + case V('c','2'): + c=c+j; + if (*c!='\n') { nobreaksym=*c; } + else nobreaksym='\''; + c=skip_till_newline(c); + break; + case V('c','c'): + c=c+j; + if (*c!='\n') { controlsym=*c; } + else controlsym='.'; + c=skip_till_newline(c); + break; + case V('c','e'): + c=c+j; + if (*c == '\n') { i=1; } + else { + i=0; + while ('0'<=*c && *c<='9') { + i=i*10+*c-'0'; + c++; + } + } + c=skip_till_newline(c); + /* center next i lines */ + if (i>0) { + out_html("<CENTER>\n"); + while (i && *c) { + char *line=NULL; + c=scan_troff(c,1, &line); + if (line && strncmp(line, "<BR>", 4)) { + out_html(line); + out_html("<BR>\n"); + i--; + } + } + out_html("</CENTER>\n"); + curpos=0; + } + break; + case V('e','c'): + c=c+j; + if (*c!='\n') { escapesym=*c; } + else escapesym='\\'; + break; + c=skip_till_newline(c); + case V('e','o'): + escapesym=0; + c=skip_till_newline(c); + break; + case V('e','x'): + exit(0); + break; + case V('f','c'): + c=c+j; + if (*c == '\n') { + fieldsym=padsym=0; + } else { + fieldsym=c[0]; + padsym=c[1]; + } + c=skip_till_newline(c); + break; + case V('f','i'): + if (!fillout) { + out_html(change_to_font(0)); + out_html(change_to_size('0')); + out_html("</PRE>\n"); + } + curpos=0; + fillout=1; + c=skip_till_newline(c); + break; + case V('f','t'): + c=c+j; + if (*c == '\n') { + out_html(change_to_font(0)); + } else { + if (*c == escapesym) { + int fn; + c=scan_expression(c, &fn); + c--; + out_html(change_to_font(fn)); + } else { + out_html(change_to_font(*c)); + c++; + } + } + c=skip_till_newline(c); + break; + case V('e','l'): + /* .el anything : else part of if else */ + if (ifelseval) { + c=c+j; + c[-1]='\n'; + c=scan_troff(c,1,NULL); + } else + c=skip_till_newline(c+j); + break; + case V('i','e'): + /* .ie c anything : then part of if else */ + case V('i','f'): + /* .if c anything + * .if !c anything + * .if N anything + * .if !N anything + * .if 'string1'string2' anything + * .if !'string1'string2' anything + */ + c=c+j; + c=scan_expression(c, &i); + ifelseval=!i; + if (i) { + *c='\n'; + c++; + c=scan_troff(c,1,NULL); + } else + c=skip_till_newline(c); + break; + case V('i','g'): /* .ig: ignore until .. */ + { + char *endwith="..\n"; + i=3; + c=c+j; + while (*c == ' ') c++; + if (*c == escapesym && c[1] == '"') + while (*c != '\n') c++; + if (*c!='\n') { /* .ig yy: ignore until .yy, then call .yy */ + endwith=c-1;i=1; + c[-1]='.'; + while (*c && *c!='\n') c++,i++; + } + c++; + while (*c && strncmp(c,endwith,i)) + while (*c && *c++!='\n'); + while (*c && *c++!='\n'); + break; + } + case V('n','f'): + if (fillout) { + out_html(change_to_font(0)); + out_html(change_to_size('0')); + out_html("<PRE>\n"); + } + curpos=0; + fillout=0; + c=skip_till_newline(c); + break; + case V('p','s'): + c=c+j; + if (*c == '\n') { + out_html(change_to_size('0')); + } else { + j=0;i=0; + if (*c == '-') { j= -1;c++; } else if (*c == '+') { j=1;c++;} + c=scan_expression(c, &i); + if (!j) { j=1; if (i>5) i=i-10; } + out_html(change_to_size(i*j)); + } + c=skip_till_newline(c); + break; + case V('s','p'): + c=c+j; + if (fillout) out_html("<P>"); else { + out_html(NEWLINE); + NEWLINE[0]='\n'; + } + curpos=0; + c=skip_till_newline(c); + break; + case V('s','o'): + { + int l; char *buf; + char *name = NULL; + + curpos=0; + c += j; /* skip .so part and whitespace */ + if (*c == '/') { + h = c; + } else { /* .so man3/cpow.3 -> ../man3/cpow.3 */ +/* h = c-3; + h[0] = '.'; + h[1] = '.'; + h[2] = '/'; +*/ + h = c; + } + + while (*c != '\n') c++; + while (c[-1] == ' ') c--; + while (*c != '\n') *c++ = 0; + *c = 0; + scan_troff(h,1, &name); + if (name[3] == '/') h=name+3; else h=name; +#if NOCGI + if (!out_length) { + char *t,*s; + t=strrchr(fname, '/'); + if (!t) t=fname; + fprintf(stderr, "ln -s %s.html %s.html\n", h, t); + s=strrchr(t, '.');if (!s) s=t; + printf(CONTENTTYPE DOCTYPE); + printf("<HTML><HEAD><TITLE> Man page of %s</TITLE>\n" + "</HEAD><BODY>\n" + "See the man page for <A HREF=\"%s.html\">%s</A>.\n" + "</BODY></HTML>\n", + s, h, h); + } else +#endif + { + /* this works alright, except for section 3 */ + if ((l = read_manpage_into_buffer(h, &buf)) < 0) { + fprintf(stderr, + "man2html: unable to open or read file %s\n", h); + out_html("<BLOCKQUOTE>" + "man2html: unable to open or read file\n"); + out_html(h); + out_html("</BLOCKQUOTE>\n"); + } else { + buf[0]=buf[l]='\n'; + buf[l+1]=buf[l+2]=0; + scan_troff(buf+1,0,NULL); + if (buf) free(buf); + } + } + *c++='\n'; + break; + } + case V('t','a'): + c=c+j; + j=0; + while (*c!='\n') { + sl=scan_expression(c, &tabstops[j]); + if (*c == '-' || *c == '+') tabstops[j]+=tabstops[j-1]; + c=sl; + while (*c == ' ' || *c == '\t') c++; + if (j+1 < SIZE(tabstops)) + j++; + } + maxtstop=j; + curpos=0; + break; + case V('t','i'): +#if 0 + dl_down(); +#endif + out_html("<BR>\n"); + c=c+j; + c=scan_expression(c, &j); + for (i=0; i<j; i++) out_html(" "); + curpos=j; + c=skip_till_newline(c); + break; + case V('t','m'): + c=c+j; + h=c; + while (*c!='\n') c++; + *c=0; + fprintf(stderr,"%s\n", h); /* XXX */ + *c='\n'; + break; + case V('B',' '): + case V('B','\n'): + case V('I',' '): + case V('I','\n'): + /* parse one line in a certain font */ + out_html(change_to_font(*c)); + trans_char(c, '"', '\a'); + c=c+j; + if (*c == '\n') c++; + c=scan_troff(c, 1, NULL); + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('O','P'): /* groff man pages use this construction */ + /* .OP a b : [ <B>a</B> <I>b</I> ] */ + mode=1; + c[0]='B'; c[1]='I'; + out_html(change_to_font('R')); + out_html("["); + curpos++; + case V('B','R'): + case V('B','I'): + case V('I','B'): + case V('I','R'): + case V('R','B'): + case V('R','I'): + { + char font[2]; + font[0] = c[0]; font[1] = c[1]; + c = c+j; + if (*c == '\n') { + c++; + break; + } + sl = fill_words(c, wordlist, SIZE(wordlist), &words, '\n'); + c = sl+1; + /* .BR name (section) + ** indicates a link. It will be added in the output routine. + */ + for (i=0; i<words; i++) { + if (mode) { out_html(" "); curpos++; } + wordlist[i][-1]=' '; + out_html(change_to_font(font[i&1])); + scan_troff(wordlist[i],1,NULL); + } + out_html(change_to_font('R')); + if (mode) { out_html(" ]"); curpos++;} + out_html(NEWLINE); if (!fillout) curpos=0; else curpos++; + } + break; + case V('D','T'): + maxtstop = SIZE(tabstops); + for (j=0; j<maxtstop; j++) + tabstops[j]=(j+1)*8; + c=skip_till_newline(c); break; + case V('I','P'): + sl = fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n'); + c = sl+1; + dl_begin(); + if (words) { + scan_troff(wordlist[0], 1,NULL); + } + out_html("<DD>"); + curpos = 0; + break; + case V('T','P'): + dl_begin(); + c=skip_till_newline(c); + /* somewhere a definition ends with '.TP' */ + if (!*c) still_dd=1; else { + c=scan_troff(c,1,NULL); + out_html("<DD>"); + } + curpos=0; + break; + case V('I','X'): + /* general index */ + sl = fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n'); + c = sl+1; + j = 4; + while (idxlabel[j] == 'Z') idxlabel[j--]='A'; + idxlabel[j]++; +#ifdef MAKEINDEX + if (idxfile) { + fprintf(idxfile, "%s@%s@", fname, idxlabel); + for (j=0; j<words; j++) { + h=NULL; + scan_troff(wordlist[j], 1, &h); + fprintf(idxfile, "_\b@%s", h); + free(h); + } + fprintf(idxfile,"\n"); + } +#endif + out_html("<A NAME=\""); + out_html(idxlabel); + /* this will not work in mosaic (due to a bug). + ** Adding ' ' between '>' and '<' solves it, but creates + ** some space. A normal space does not work. + */ + out_html("\"></A>"); + break; + case V('P',' '): + case V('P','\n'): + case V('L','P'): + case V('P','P'): + dl_end(); + if (fillout) out_html("<P>\n"); else { + out_html(NEWLINE); + NEWLINE[0]='\n'; + } + curpos=0; + c=skip_till_newline(c); + break; + case V('H','P'): + dl_begin(); + still_dd=1; + c=skip_till_newline(c); + curpos=0; + break; + case V('P','D'): + c=skip_till_newline(c); + break; + case V('R','s'): /* BSD mandoc */ + case V('R','S'): + sl = fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n'); + j = 1; + if (words>0) scan_expression(wordlist[0], &j); + if (j>=0) { + dl_newlevel(); + c=skip_till_newline(c); + curpos=0; + break; + } + case V('R','e'): /* BSD mandoc */ + case V('R','E'): + dl_endlevel(); + c=skip_till_newline(c); + curpos=0; + break; + case V('S','B'): + out_html(change_to_size(-1)); + out_html(change_to_font('B')); + c=scan_troff(c+j, 1, NULL); + out_html(change_to_font('R')); + out_html(change_to_size('0')); + break; + case V('S','M'): + c=c+j; + if (*c == '\n') c++; + out_html(change_to_size(-1)); + trans_char(c,'"','\a'); + c=scan_troff(c,1,NULL); + out_html(change_to_size('0')); + break; + case V('S','s'): /* BSD mandoc */ + mandoc_command = 1; + case V('S','S'): + mode=1; + goto sh_below; + case V('S','h'): /* BSD mandoc */ + mandoc_command = 1; + case V('S','H'): + sh_below: + c=c+j; + if (*c == '\n') c++; + dl_down(); + out_html(change_to_font(0)); + out_html(change_to_size(0)); + if (!fillout) { + fillout=1; + out_html("</PRE>"); + } + trans_char(c,'"', '\a'); + add_to_index(mode, c); + out_html("<A NAME=\""); + out_html(label); + /* for mosaic users */ + if (mode) out_html("\"> </A>\n<H3>"); + else out_html("\"> </A>\n<H2>"); + mandoc_synopsis = (strncmp(c, "SYNOPSIS", 8) == 0); + c = (mandoc_command ? scan_troff_mandoc : scan_troff)(c,1,NULL); + if (mode) out_html("</H3>\n"); + else out_html("</H2>\n"); + curpos=0; + break; + case V('T','S'): + c=scan_table(c); + break; + case V('D','t'): /* BSD mandoc */ + mandoc_command = 1; + case V('T','H'): + if (!output_possible) { + sl = fill_words(c+j, wordlist, SIZE(wordlist), &words, 0); + /* + * fill_words changes `"' into `\a', + * remove all `\a' now + * robert@debian.org, Jan 2003 + */ + for (i=0; i<words; i++) { + if (wordlist[i][0] == '\a') { + char *tmp; + (wordlist[i])++; + if ((tmp = strchr(wordlist[i], '\a'))) + *tmp = '\0'; + } + } + *sl = 0; + if (words > 1) { + char *t = NULL; + char *s, *q; + int skip=0; + output_possible=1; + printf(CONTENTTYPE DOCTYPE); + out_html("<HTML><HEAD><TITLE>Man page of "); + scan_troff(wordlist[0], 0, &t); + /* we need to remove all html tags */ + for (s=q=t; *s; s++) { + if (skip && *s == '>') skip=0; + else if (!skip && *s == '<') skip=1; + else if (!skip) *q++ = *s; + } + *q = '\0'; + out_html(t); + free(t); + out_html("</TITLE>\n</HEAD><BODY>\n<H1>"); + scan_troff(wordlist[0], 0, NULL); + out_html("</H1>\nSection: "); + if (words>4) + scan_troff(wordlist[4], 0, NULL); + else + out_html(section_name(wordlist[1])); + out_html(" ("); + scan_troff(wordlist[1], 0, NULL); + if (words>2) { + out_html(")<BR>Updated: "); + scan_troff(wordlist[2], 1, NULL); + } else out_html(")"); + out_html("<BR><A HREF=\"#index\">Index</A>\n"); + man_page_html(0,0); /* Return to Main Contents */ + *sl='\n'; + out_html("<HR>\n"); + if (mandoc_command) out_html("<BR>BSD mandoc<BR>"); + } + c = sl+1; + } else + c = skip_till_newline(c); + curpos=0; + break; + case V('T','X'): + sl=fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n'); + *sl=0; + out_html(change_to_font('I')); + if (words>1) wordlist[1][-1]=0; + c=lookup_abbrev(wordlist[0]); + curpos+=strlen(c); + out_html(c); + out_html(change_to_font('R')); + if (words>1) + out_html(wordlist[1]); + *sl='\n'; + c=sl+1; + break; + case V('r','m'): + /* .rm xx : Remove request, macro or string */ + case V('r','n'): + /* .rn xx yy : Rename request, macro or string xx to yy */ + { + STRDEF *de; + c=c+j; + i=V(c[0],c[1]); + c=c+2; + while (isspace(*c) && *c!='\n') c++; + j=V(c[0],c[1]); + while (*c && *c!='\n') c++; + c++; + de=strdef; + while (de && de->nr!=j) de=de->next; + if (de) { + if (de->st) free(de->st); + de->nr=0; + } + de=strdef; + while (de && de->nr!=i) de=de->next; + if (de) de->nr=j; + break; + } + case V('n','x'): + /* .nx filename : next file. */ + case V('i','n'): + /* .in +-N : Indent */ + c=skip_till_newline(c); + break; + case V('n','r'): + /* .nr R +-N M: define and set number register R by +-N; + ** auto-increment by M + */ + { + INTDEF *intd; + c=c+j; + i=V(c[0],c[1]); + c=c+2; + intd=intdef; + while (intd && intd->nr!=i) intd=intd->next; + if (!intd) { + intd = (INTDEF*) xmalloc(sizeof(INTDEF)); + intd->nr=i; + intd->val=0; + intd->incr=0; + intd->next=intdef; + intdef=intd; + } + while (*c == ' ' || *c == '\t') c++; + c=scan_expression(c,&intd->val); + if (*c!='\n') { + while (*c == ' ' || *c == '\t') c++; + c=scan_expression(c,&intd->incr); + } + c=skip_till_newline(c); + break; + } + case V('a','m'): + /* .am xx yy : append to a macro. */ + /* define or handle as .ig yy */ + mode=1; + case V('d','e'): + /* .de xx yy : define or redefine macro xx; end at .yy (..) */ + /* define or handle as .ig yy */ + { + LONGSTRDEF *de; + char *longname; + int olen=0; + c=c+j; + sl=fill_words(c, wordlist, SIZE(wordlist), &words, '\n'); + i=V(c[0],c[1]);j=2; + longname = c; + if (words == 1) wordlist[1]=".."; else { + wordlist[1]--; + wordlist[1][0]='.'; + j=3; + } + c=sl+1; + *sl=0; + sl=c; + while (*c && strncmp(c,wordlist[1],j)) c=skip_till_newline(c); + de = find_longstrdef(defdef, i, longname, &longname); + if (mode && de) olen=strlen(de->st); + j=olen+c-sl; + h= (char*) xmalloc((j*2+5)*sizeof(char)); + if (h) { + for (j=0; j<olen; j++) + h[j]=de->st[j]; + if (!j || h[j-1]!='\n') + h[j++]='\n'; + while (sl!=c) { + if (sl[0] == '\\' && sl[1] == '\\') { + h[j++]='\\'; sl++; + } else + h[j++]=*sl; + sl++; + } + h[j]=0; + if (de) { + if (de->st) free(de->st); + de->st=h; + } else { + de = (LONGSTRDEF*) xmalloc(sizeof(LONGSTRDEF)); + de->nr=i; + de->longname=longname; + de->slen=0; + de->next=defdef; + de->st=h; + defdef=de; + } + } + } + c=skip_till_newline(c); + break; + + /* ----- BSD mandoc stuff below ----- */ + case V('U','x'): /* BSD mandoc */ + c=c+j; + out_html("UNIX"); + c=skip_till_newline(c); + break; + case V('A','t'): /* BSD mandoc - called with arg V */ + c=c+j; + out_html("AT&T System"); + break; + case V('B','l'): /* BSD mandoc */ + { + char *nl, t=0 /* just for gcc */; + c=c+j; + nl = strchr(c,'\n'); + if (nl) { + t = *nl; + *nl = 0; + } + if (strstr(c, "-bullet")) /* HTML Unnumbered List */ + dl_newlevel_type(UL); + else if (strstr(c, "-enum")) /* HTML Ordered List */ + dl_newlevel_type(OL); + else /* HTML Descriptive List */ + dl_newlevel_type(DL); + if (nl) + *nl = t; + if (fillout) out_html("<P>\n"); else { + out_html(NEWLINE); + NEWLINE[0]='\n'; + } + curpos=0; + c=skip_till_newline(c); + break; + } + case V('E','l'): /* BSD mandoc */ + c=c+j; + dl_endlevel_type(); + if (fillout) out_html("<P>\n"); else { + out_html(NEWLINE); + NEWLINE[0]='\n'; + } + curpos=0; + c=skip_till_newline(c); + break; + case V('I','t'): /* BSD mandoc */ + c=c+j; + if (dl_type(DL)) { + out_html("<DT>"); + out_html(change_to_font('B')); + if (*c == '\n') { + /* Don't allow embedded comms after a newline */ + c++; + c=scan_troff(c,1,NULL); + } else { + /* Do allow embedded comms on the same line. */ + c=scan_troff_mandoc(c,1,NULL); + } + out_html(change_to_font('R')); + out_html(NEWLINE); + if (inXo) + still_dd = 1; + else + out_html("<DD>"); + } else if (dl_type(UL) || dl_type(OL)) { + out_html("<LI>"); + c=scan_troff_mandoc(c,1,NULL); + out_html(NEWLINE); + } + if (fillout) curpos++; else curpos=0; + break; + case V('X','o'): /* BSD mandoc */ + c=c+j; + inXo = 1; + break; + case V('X','c'): /* BSD mandoc - Xc closes an Xo */ + c=c+j; + if (inXo) { + if (still_dd) + out_html("<DD>"); + inXo = 0; + } + break; + case V('S','m'): /* BSD mandoc - called with arg on/off */ + case V('B','k'): /* BSD mandoc - may be called with -words arg*/ + case V('E','k'): /* BSD mandoc */ + c=skip_till_newline(c); + break; + case V('D','d'): /* BSD mandoc */ + case V('O','s'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + c=scan_troff_mandoc(c, 1, NULL); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('B','t'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + out_html(" is currently in beta test."); + if (fillout) curpos++; else curpos=0; + break; + case V('B','x'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html("BSD "); + c=scan_troff_mandoc(c, 1, NULL); + if (fillout) curpos++; else curpos=0; + break; + case V('D','l'): /* BSD mandoc */ + c=c+j; + out_html(NEWLINE); + out_html("<BLOCKQUOTE>"); + out_html(change_to_font('L')); + if (*c == '\n') c++; + c=scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html("</BLOCKQUOTE>"); + if (fillout) curpos++; else curpos=0; + break; + case V('B','d'): /* BSD mandoc */ + { /* Seems like a kind of example/literal mode */ + char *nl, t=0 /* just for gcc */; + c=c+j; + nl = strchr(c,'\n'); + if (nl) { + t = *nl; + *nl = 0; + } + out_html(NEWLINE); + mandoc_bd_options = 0; /* Remember options for terminating Bl */ + if (strstr(c, "-offset indent")) { + mandoc_bd_options |= BD_INDENT; + out_html("<BLOCKQUOTE>\n"); + } + if (strstr(c, "-literal") || strstr(c, "-unfilled")) { + if (fillout) { + mandoc_bd_options |= BD_LITERAL; + out_html(change_to_font(0)); + out_html(change_to_size('0')); + out_html("<PRE>\n"); + } + curpos=0; + fillout=0; + } + if (nl) + *nl = t; + c=skip_till_newline(c); + break; + } + case V('E','d'): /* BSD mandoc */ + if (mandoc_bd_options & BD_LITERAL) { + if (!fillout) { + out_html(change_to_font(0)); + out_html(change_to_size('0')); + out_html("</PRE>\n"); + } + } + if (mandoc_bd_options & BD_INDENT) + out_html("</BLOCKQUOTE>\n"); + curpos=0; + fillout=1; + c=skip_till_newline(c); + break; + case V('B','e'): /* BSD mandoc */ + c=c+j; + if (fillout) out_html("<P>"); else { + out_html(NEWLINE); + NEWLINE[0]='\n'; + } + curpos=0; + c=skip_till_newline(c); + break; + case V('X','r'): /* BSD mandoc */ + { + /* Translate xyz 1 to xyz(1) + * Allow for multiple spaces. Allow the section to be missing. + */ + char buff[100]; + char *bufptr; + trans_char(c,'"','\a'); + bufptr = buff; + c = c+j; + if (*c == '\n') c++; /* Skip spaces */ + while (isspace(*c) && *c != '\n') c++; + while (isalnum(*c) && bufptr < buff + SIZE(buff)-4) { + /* Copy the xyz part */ + *bufptr++ = *c++; + } + while (isspace(*c) && *c != '\n') c++; /* Skip spaces */ + if (isdigit(*c)) { /* Convert the number if there is one */ + *bufptr++ = '('; + while (isalnum(*c) && bufptr < buff + SIZE(buff)-3) { + *bufptr++ = *c++; + } + *bufptr++ = ')'; + } + while (*c != '\n' && bufptr < buff + SIZE(buff)-2) { + /* Copy the remainder */ + if (!isspace(*c)) { + *bufptr++ = *c; + } + c++; + } + *bufptr++ = '\n'; + *bufptr = 0; + scan_troff_mandoc(buff, 1, NULL); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + } + break; + case V('F','l'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + out_html("-"); + if (*c!='\n') { + out_html(change_to_font('B')); + c=scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + } + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('P','a'): /* BSD mandoc */ + case V('P','f'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + c=scan_troff_mandoc(c, 1, NULL); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('P','p'): /* BSD mandoc */ + if (fillout) out_html("<P>\n"); else { + out_html(NEWLINE); + NEWLINE[0]='\n'; + } + curpos=0; + c=skip_till_newline(c); + break; + case V('D','q'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html("``"); + c=scan_troff_mandoc(c, 1, NULL); + out_html("''"); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('O','p'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html(change_to_font('R')); + out_html("["); + c=scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html("]"); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('O','o'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html(change_to_font('R')); + out_html("["); + c=scan_troff_mandoc(c, 1, NULL); + if (fillout) curpos++; else curpos=0; + break; + case V('O','c'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + c=scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html("]"); + if (fillout) curpos++; else curpos=0; + break; + case V('P','q'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html("("); + c=scan_troff_mandoc(c, 1, NULL); + out_html(")"); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('Q','l'): /* BSD mandoc */ + { /* Single quote first word in the line */ + char *sp; + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + sp = c; + do { /* Find first whitespace after the + * first word that isn't a mandoc macro + */ + while (*sp && isspace(*sp)) sp++; + while (*sp && !isspace(*sp)) sp++; + } while (*sp && isupper(*(sp-2)) && islower(*(sp-1))); + + /* Use a newline to mark the end of text to + * be quoted + */ + if (*sp) *sp = '\n'; + out_html("`"); /* Quote the text */ + c=scan_troff_mandoc(c, 1, NULL); + out_html("'"); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + } + case V('S','q'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html("`"); + c=scan_troff_mandoc(c, 1, NULL); + out_html("'"); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('A','r'): /* BSD mandoc */ + /* parse one line in italics */ + out_html(change_to_font('I')); + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') { /* An empty Ar means "file ..." */ + out_html("file ..."); + } else { + c=scan_troff_mandoc(c, 1, NULL); + } + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('A','d'): /* BSD mandoc */ + case V('E','m'): /* BSD mandoc */ + case V('V','a'): /* BSD mandoc */ + /* parse one line in italics */ + out_html(change_to_font('I')); + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + c=scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('N','d'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html(" - "); + c=scan_troff_mandoc(c, 1, NULL); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('N','m'): /* BSD mandoc */ + { + static char *mandoc_name = 0; + trans_char(c,'"','\a'); + c=c+j; + while (*c == ' ' || *c == '\t') c++; + if (!mandoc_name) { + /* Save the name of the first .Nm call */ + char *end, t=0 /* just for gcc */; + end = strpbrk(c, "\t \n"); + if (end && end != c) { + t = *end; + *end = 0; + mandoc_name = xstrdup(c); + *end = t; + } + } + if (mandoc_synopsis) { + /* + * Break lines only in the Synopsis. + * The Synopsis section seems to be treated + * as a special case - Bummer! + */ + static int count = 0; /* Don't break on the first Nm */ + if (count) { + out_html("<BR>"); + } + count++; + } + out_html(change_to_font('B')); + if (*c == '\n' || (ispunct(*c) && *(c+1) == '\n')) { + /* + * If Nm has no argument, use one from an earlier + * Nm command that did have one. Hope there aren't + * too many commands that do this. + */ + if (mandoc_name) + out_html(mandoc_name); + } + if (*c != '\n') { + c=scan_troff_mandoc(c, 1, NULL); + } + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + } + case V('C','d'): /* BSD mandoc */ + case V('C','m'): /* BSD mandoc */ + case V('I','c'): /* BSD mandoc */ + case V('M','s'): /* BSD mandoc */ + case V('O','r'): /* BSD mandoc */ + case V('S','y'): /* BSD mandoc */ + /* parse one line in bold */ + out_html(change_to_font('B')); + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + c=scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('D','v'): /* BSD mandoc */ + case V('E','v'): /* BSD mandoc */ + case V('F','r'): /* BSD mandoc */ + case V('L','i'): /* BSD mandoc */ + case V('N','o'): /* BSD mandoc */ + case V('N','s'): /* BSD mandoc */ + case V('T','n'): /* BSD mandoc */ + case V('n','N'): /* BSD mandoc */ + trans_char(c,'"','\a'); + c=c+j; + if (*c == '\n') c++; + out_html(change_to_font('B')); + c=scan_troff_mandoc(c, 1, NULL); + out_html(change_to_font('R')); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + break; + case V('%','A'): /* BSD mandoc biblio stuff */ + case V('%','D'): + case V('%','N'): + case V('%','O'): + case V('%','P'): + case V('%','Q'): + case V('%','V'): + c=c+j; + if (*c == '\n') c++; + c=scan_troff(c, 1, NULL); /* Don't allow embedded mandoc coms */ + if (fillout) curpos++; else curpos=0; + break; + case V('%','B'): + case V('%','J'): + case V('%','R'): + case V('%','T'): + c=c+j; + out_html(change_to_font('I')); + if (*c == '\n') c++; + c=scan_troff(c, 1, NULL); /* Don't allow embedded mandoc coms */ + out_html(change_to_font('R')); + if (fillout) curpos++; else curpos=0; + break; + /* ----- end of BSD mandoc stuff ----- */ + + default: + if (mandoc_command && + ((isupper(*c) && islower(c[1])) + || (islower(*c) && isupper(c[1])))) { + /* + * Let through any BSD mandoc commands that haven't + * been dealt with. + * I don't want to miss anything out of the text. + */ + char buf[4]; + strncpy(buf,c,2); + buf[2] = ' '; + buf[3] = 0; + out_html(buf); /* Print the command (it might just be text). */ + c=c+j; + trans_char(c,'"','\a'); + if (*c == '\n') c++; /* really? */ + out_html(change_to_font('R')); + c=scan_troff(c, 1, NULL); + out_html(NEWLINE); + if (fillout) curpos++; else curpos=0; + } else + c=skip_till_newline(c); + break; + } + } + if (fillout) { out_html(NEWLINE); curpos++; } + NEWLINE[0]='\n'; + return c; +} + +static int contained_tab=0; +static int mandoc_line=0;/* Signals whether to look for embedded mandoc cmds */ + +static char * +scan_troff(char *c, int san, char **result) { /* san : stop at newline */ + char *h; + char intbuff[500]; + int ibp=0; +#define FLUSHIBP if (ibp) { intbuff[ibp]=0; out_html(intbuff); ibp=0; } + char *exbuffer; + int exbuffpos, exbuffmax, exscaninbuff, exnewline_for_fun; + int usenbsp = 0; + + exbuffer = buffer; + exbuffpos = buffpos; + exbuffmax = buffmax; + exnewline_for_fun = newline_for_fun; + exscaninbuff = scaninbuff; + newline_for_fun = 0; + if (result) { + if (*result) { + buffer = *result; + buffpos = strlen(buffer); + buffmax = buffpos; + } else { + buffer = (char *) xmalloc(1000*sizeof(char)); + buffpos = 0; + buffmax = 1000; + } + scaninbuff = 1; + } + h = c; + /* start scanning */ + while (*h && (!san || newline_for_fun || *h != '\n')) { + if (*h == escapesym) { + h++; + FLUSHIBP; + h = scan_escape(h); + } else if (san != 2 && *h == controlsym && h[-1] == '\n') { + h++; + FLUSHIBP; + h = scan_request(h); + if (san && h[-1] == '\n') h--; + } else if (san != 2 && mandoc_line + && *(h) && isupper(*(h)) + && *(h+1) && islower(*(h+1)) + && *(h+2) && isspace(*(h+2))) { + /* BSD imbedded command eg ".It Fl Ar arg1 Fl Ar arg2" */ + FLUSHIBP; + h = scan_request(h); + if (san && h[-1] == '\n') h--; + } else if (san != 2 && *h == nobreaksym && h[-1] == '\n') { + h++; + FLUSHIBP; + h = scan_request(h); + if (san && h[-1] == '\n') h--; + } else { + if (h[-1] == '\n' && still_dd && isalnum(*h)) { + /* sometimes a .HP request is not followed by a .br request */ + FLUSHIBP; + out_html("<DD>"); + curpos=0; + still_dd=0; + } + switch (*h) { + case '&': + intbuff[ibp++]='&'; + intbuff[ibp++]='a'; + intbuff[ibp++]='m'; + intbuff[ibp++]='p'; + intbuff[ibp++]=';'; + curpos++; + break; + case '<': + intbuff[ibp++]='&'; + intbuff[ibp++]='l'; + intbuff[ibp++]='t'; + intbuff[ibp++]=';'; + curpos++; + break; + case '>': + intbuff[ibp++]='&'; + intbuff[ibp++]='g'; + intbuff[ibp++]='t'; + intbuff[ibp++]=';'; + curpos++; + break; + case '"': + intbuff[ibp++]='&'; + intbuff[ibp++]='q'; + intbuff[ibp++]='u'; + intbuff[ibp++]='o'; + intbuff[ibp++]='t'; + intbuff[ibp++]=';'; + curpos++; + break; + case '\n': + if (h[-1] == '\n' && fillout) { + intbuff[ibp++]='<'; + intbuff[ibp++]='P'; + intbuff[ibp++]='>'; + } + if (contained_tab && fillout) { + intbuff[ibp++]='<'; + intbuff[ibp++]='B'; + intbuff[ibp++]='R'; + intbuff[ibp++]='>'; + } + contained_tab=0; + curpos=0; + usenbsp=0; + intbuff[ibp++]='\n'; + break; + case '\t': + { + int curtab=0; + contained_tab=1; + FLUSHIBP; + /* like a typewriter, not like TeX */ + tabstops[SIZE(tabstops)-1] = curpos+1; + while (curtab < maxtstop && tabstops[curtab] <= curpos) + curtab++; + if (curtab < maxtstop) { + if (!fillout) { + while (curpos<tabstops[curtab]) { + intbuff[ibp++]=' '; + if (ibp>480) { FLUSHIBP; } + curpos++; + } + } else { + out_html("<TT>"); + while (curpos < tabstops[curtab]) { + out_html(" "); + curpos++; + } + out_html("</TT>"); + } + } + } + break; + default: + if (*h == ' ' && (h[-1] == '\n' || usenbsp)) { + FLUSHIBP; + if (!usenbsp && fillout) { + out_html("<BR>"); + curpos=0; + } + usenbsp=fillout; + if (usenbsp) out_html(" "); else intbuff[ibp++]=' '; + } else if (*h > 31 && *h < 127) { + intbuff[ibp++]=*h; + } else if (((unsigned char)(*h)) > 127) { +#ifdef NO_8BIT + intbuff[ibp++]='&'; + intbuff[ibp++]='#'; + intbuff[ibp++]='0'+((unsigned char)(*h))/100; + intbuff[ibp++]='0'+(((unsigned char)(*h))%100)/10; + intbuff[ibp++]='0'+((unsigned char)(*h))%10; + intbuff[ibp++]=';'; +#else + intbuff[ibp++]=*h; +#endif + } + curpos++; + break; + } + if (ibp>480) FLUSHIBP; + h++; + } + } + FLUSHIBP; + if (buffer) buffer[buffpos]=0; + if (san && *h) h++; + newline_for_fun=exnewline_for_fun; + if (result) { + *result = buffer; + buffer=exbuffer; + buffpos=exbuffpos; + buffmax=exbuffmax; + scaninbuff=exscaninbuff; + } + return h; +} + +static char *scan_troff_mandoc(char *c, int san, char **result) { + char *ret, *end = c; + int oldval = mandoc_line; + mandoc_line = 1; + while (*end && *end != '\n') { + end++; + } + + if (end > c + 2 + && ispunct(*(end - 1)) + && isspace(*(end - 2)) && *(end - 2) != '\n') { + /* + * Don't format lonely punctuation. E.g. in "xyz ," format + * the xyz and then append the comma removing the space. + */ + *(end - 2) = '\n'; + ret = scan_troff(c, san, result); + *(end - 2) = *(end - 1); + *(end - 1) = ' '; + } else { + ret = scan_troff(c, san, result); + } + mandoc_line = oldval; + return ret; +} + +STRDEF *foundpages=NULL; + +static void +error_page(int status, char *s, char *t, ...) { + va_list p; + + switch(status) { + case 403: + printf("Status: 403 Forbidden\n"); + break; + case 404: + printf("Status: 404 Not Found\n"); + break; + case 500: + printf("Status: 500 Internal Server Error\n"); + break; + case 0: + default: + break; + } + + printf(CONTENTTYPE DOCTYPE); + printf("<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n" + "<BODY>\n<H1>%s</H1>\n", s, s); + va_start(p, t); + vfprintf(stdout, t, p); + va_end(p); + printf("</BODY></HTML>\n"); + exit(0); +} + +char * +xstrdup(const char *s) { + char *p = strdup(s); + if (p == NULL) + error_page(500, "Out of memory", + "Sorry, out of memory, aborting...\n"); + return p; +} + +void * +xmalloc(size_t size) { + void *p = malloc(size); + if (p == NULL) + error_page(500, "Out of memory", + "Sorry, out of memory, aborting...\n"); + return p; +} + +void * +xrealloc(void *ptr, size_t size) { + void *p = realloc(ptr,size); + if (p == NULL) + error_page(500, "Out of memory", + "Sorry, out of memory, aborting...\n"); + return p; +} + +static void +usage(void) { + error_page(500, "man2html: bad invocation", + "Call: man2html [-l|-h host.domain:port] [-p|-q] [filename]\n" + "or: man2html -r [filename]\n"); +} + +static void +goto_dir(char *path, char **dir, char **name) { + char *s, *t, *u; + + s = xstrdup(path); + t = strrchr(s, '/'); + if (t) { + *t = 0; + u = strrchr(s, '/'); + *t = '/'; + if (u) { + *u = 0; + if (chdir(s) == 0) { + if (dir) + *dir = s; + if (name) + *name = u+1; + } +#if 0 + else /* complain or not - this need not be fatal */ + error_page("Error", "man2html: could not chdir to %s", s); +#endif + } + } +} + + + +/* + * Call: man2html [-l] [filename] + * + * The contents of FILENAME (or STDIN, in case FILENAME is "-" or absent) + * are converted from man-style nroff to html, and printed on STDOUT. + * + * Possible errors are reflected in the output. The return status is 0. + */ +int +main(int argc, char **argv) { + int l, c; + char *buf, *filename, *fnam = NULL; + +#ifdef __CYGWIN__ + int opterr; + + extern int optind; + extern char *optarg; +#endif + +/* printf("Content-type: text/html\n\n"); */ + + opterr = 0; /* no stderr error messages */ + while ((c = getopt (argc, argv, "D:E:hH:lL:M:pqr?vVf")) != -1) { + switch(c) { + case 'D': + goto_dir(optarg, 0, 0); break; + case 'E': + error_page(0, "Error", "%s", optarg); break; + case 'h': + set_cgibase("localhost"); break; + case 'H': + set_cgibase(optarg); break; + case 'l': + set_lynxcgibase("/usr/lib"); break; + case 'L': + set_lynxcgibase(optarg); break; + case 'M': + set_man2htmlpath(optarg); break; + case 'p': + set_separator('/'); break; + case 'q': + set_separator('?'); break; + case 'r': + set_relative_html_links(); break; + case 'v': + case 'V': + error_page(0, "Version", "%s from man-%s", argv[0], version); + exit(0); + case '?': + default: + usage(); + case 'f': /* It is rumoured that some other + incarnation of man2html uses this flag; + ignore when given for compatibility. */ + /* case 'F': this will assign a format for man_page_html() */ + break; + } + } + + /* Find filename */ + if (argc == optind+1) + fnam = argv[optind]; + else if (argc != optind) + usage(); + + filename = fnam; + directory = 0; + + /* Open input file */ + if (!fnam || !strcmp(fnam, "-")) { + fnam = "-"; + fname = "(stdin)"; + } else { + /* do a chdir() first, to get .so expansion right */ + goto_dir(fnam, &directory, &fnam); + fname = fnam; + } + + l = read_manpage_into_buffer(fnam, &buf); + if (l < 0) + error_page(404, "File not found", "Could not open %s\n", fname); + + buf[0] = '\n'; + buf[l+1] = '\n'; + buf[l+2] = buf[l+3] = 0; + +#ifdef MAKEINDEX + idxfile = fopen(INDEXFILE, "a"); +#endif + stdinit(); + + scan_troff(buf+1,0,NULL); + dl_down(); + out_html(change_to_font(0)); + out_html(change_to_size(0)); + if (!fillout) { + fillout=1; + out_html("</PRE>"); + } + out_html(NEWLINE); + if (output_possible) { + /* for mosaic users */ + if (manidx) { + printf("<HR>\n<A NAME=\"index\"> </A><H2>Index</H2>\n<DL>\n"); + manidx[mip]=0; + printf("%s", manidx); + if (subs) printf("</DL>\n"); + printf("</DL>\n"); + } + print_sig(); + printf("</BODY>\n</HTML>\n"); + } else { + if (!filename) + filename = fname; + if (*filename == '/') + error_page(403, "Invalid Man Page", + "The requested file %s is not a valid (unformatted) " + "man page.\nIf the file is a formatted man page, " + "you could try to load the\n" + "<A HREF=\"file://%s\">plain file</A>.\n", + filename, filename); + else + error_page(403, "Invalid Man Page", + "The requested file %s is not a valid (unformatted) " + "man page.", filename); + } + if (idxfile) + fclose(idxfile); + if (buf) + free(buf); + return 0; +}
A
man2htmlsrc/strdefs.c
@@ -0,0 +1,350 @@
+#include "defs.h" +#include <ctype.h> +#include <string.h> + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +int nroff = 1; + +#define NROFF (-666) +#define TROFF (-667) + +STRDEF *chardef, *strdef; +LONGSTRDEF *defdef; +INTDEF *intdef; + +static INTDEF standardint[] = { + { V('n',' '), NROFF, 0, NULL }, + { V('t',' '), TROFF, 0, NULL }, + { V('o',' '), 1, 0, NULL }, + { V('e',' '), 0, 0, NULL }, + { V('.','l'), 70, 0, NULL }, + { V('.','$'), 0, 0, NULL }, + { V('.','A'), NROFF, 0, NULL }, + { V('.','T'), TROFF, 0, NULL }, + { V('.','V'), 1, 0, NULL }, /* the me package tests for this */ + { 0, 0, 0, NULL } }; + +static STRDEF standardstring[] = { + { V('<','='), 2, "<=", NULL }, /* less equal */ + { V('>','='), 2, ">=;", NULL }, /* greather equal */ + { V('A','m'), 1, "&", NULL }, /* infinity */ + { V('B','a'), 1, "|", NULL }, /* vartical bar */ + { V('G','e'), 2, ">=;", NULL }, /* greather equal */ + { V('G','t'), 1, ">", NULL }, /* greather than */ + { V('I','f'), 1, "∞", NULL }, /* infinity */ + { V('L','e'), 2, "<=", NULL }, /* less equal */ + { V('L','q'), 1, "“", NULL }, /* left double quote */ + { V('L','t'), 1, "<", NULL }, /* less than */ + { V('N','a'), 3, "NaN", NULL }, /* not a number */ + { V('N','e'), 2, "!=", NULL }, /* not equal */ + { V('P','i'), 2, "Pi", NULL }, /* pi */ + { V('P','m'), 1, "±", NULL }, /* plus minus */ + { V('R',' '), 1, "®", NULL }, + { V('R','q'), 1, "”", NULL }, /* right double quote */ + { V('a','a'), 1, "'", NULL }, /* accute accent */ + { V('g','a'), 1, "`", NULL }, /* grave accent */ + { V('l','q'), 2, "``", NULL }, + { V('q',' '), 1, """, NULL }, /* straight double quote */ + { V('r','q'), 2, "''", NULL }, + { V('u','a'), 1, "^", NULL }, /* upwards arrow */ + { 0, 0, NULL, NULL} +}; + +static STRDEF standardchar[] = { + { V('*','*'), 1, "*", NULL }, /* math star */ + { V('*','A'), 1, "Α", NULL }, + { V('*','B'), 1, "Β", NULL }, + { V('*','C'), 1, "Ξ", NULL }, + { V('*','D'), 1, "Δ", NULL }, + { V('*','E'), 1, "Ε", NULL }, + { V('*','F'), 1, "Φ", NULL }, + { V('*','G'), 1, "Γ", NULL }, + { V('*','H'), 1, "Θ", NULL }, + { V('*','I'), 1, "Ι", NULL }, + { V('*','K'), 1, "Κ", NULL }, + { V('*','L'), 1, "Λ", NULL }, + { V('*','M'), 1, "Μ", NULL }, + { V('*','N'), 1, "Ν", NULL }, + { V('*','O'), 1, "Ο", NULL }, + { V('*','P'), 1, "Π", NULL }, + { V('*','Q'), 1, "Ψ", NULL }, + { V('*','R'), 1, "Ρ", NULL }, + { V('*','S'), 1, "Σ", NULL }, + { V('*','T'), 1, "Τ", NULL }, + { V('*','U'), 1, "Υ", NULL }, + { V('*','W'), 1, "Ω", NULL }, + { V('*','X'), 1, "Χ", NULL }, + { V('*','Y'), 1, "Η", NULL }, + { V('*','Z'), 1, "Ζ", NULL }, + { V('*','a'), 1, "α", NULL }, + { V('*','b'), 1, "β", NULL }, + { V('*','c'), 1, "ξ", NULL }, + { V('*','d'), 1, "δ", NULL }, + { V('*','e'), 1, "ε", NULL }, + { V('*','f'), 1, "φ", NULL }, + { V('*','g'), 1, "γ", NULL }, + { V('*','h'), 1, "θ", NULL }, + { V('*','i'), 1, "ι", NULL }, + { V('*','k'), 1, "κ", NULL }, + { V('*','l'), 1, "λ", NULL }, + { V('*','m'), 1, "μ", NULL }, + { V('*','n'), 1, "ν", NULL }, + { V('*','o'), 1, "ο", NULL }, + { V('*','p'), 1, "π", NULL }, + { V('*','q'), 1, "ψ", NULL }, + { V('*','r'), 1, "ρ", NULL }, + { V('*','s'), 1, "σ", NULL }, + { V('*','t'), 1, "τ", NULL }, + { V('*','u'), 1, "υ", NULL }, + { V('*','w'), 1, "ω", NULL }, + { V('*','x'), 1, "χ", NULL }, + { V('*','y'), 1, "η", NULL }, + { V('*','z'), 1, "ζ", NULL }, + { V('\'','A'), 1, "Á", NULL }, + { V('\'','E'), 1, "É", NULL }, + { V('\'','I'), 1, "Í", NULL }, + { V('\'','O'), 1, "Ó", NULL }, + { V('\'','U'), 1, "Ú", NULL }, + { V('\'','Y'), 1, "Ý", NULL }, + { V('\'','a'), 1, "á", NULL }, + { V('\'','e'), 1, "é", NULL }, + { V('\'','i'), 1, "í", NULL }, + { V('\'','o'), 1, "ó", NULL }, + { V('\'','u'), 1, "ú", NULL }, + { V('\'','y'), 1, "ý", NULL }, + { V('!','='), 1, "≠", NULL }, + { V('%','0'), 1, "‰", NULL }, + { V('+','-'), 1, "±", NULL }, + { V(',','C'), 1, "Ç", NULL }, + { V(',','c'), 1, "ç", NULL }, + { V('-','>'), 1, "→", NULL }, + { V('-','D'), 1, "Ð", NULL }, + { V('.','i'), 1, "ı", NULL }, + { V('/','L'), 1, "Ł", NULL }, + { V('/','O'), 1, "Ø", NULL }, + { V('/','l'), 1, "ł", NULL }, + { V('/','o'), 1, "ø", NULL }, + { V('1','2'), 1, "½", NULL }, + { V('1','4'), 1, "¼", NULL }, + { V('3','4'), 1, "¾", NULL }, + { V(':','A'), 1, "Ä", NULL }, + { V(':','E'), 1, "Ë", NULL }, + { V(':','I'), 1, "Ï", NULL }, + { V(':','O'), 1, "Ö", NULL }, + { V(':','U'), 1, "Ü", NULL }, + { V(':','a'), 1, "ä", NULL }, + { V(':','e'), 1, "ë", NULL }, + { V(':','i'), 1, "ï", NULL }, + { V(':','o'), 1, "ö", NULL }, + { V(':','u'), 1, "ü", NULL }, + { V(':','y'), 1, "ÿ", NULL }, + { V('<','-'), 1, "←", NULL }, + { V('<','='), 1, "≤", NULL }, + { V('<','>'), 1, "↔", NULL }, + { V('=','='), 1, "≡", NULL }, + { V('=','~'), 1, "≅", NULL }, + { V('>','='), 1, "≥", NULL }, + { V('A','E'), 1, "Æ", NULL }, + { V('A','h'), 1, "&alepfsym;", NULL }, + { V('C','R'), 1, "␍", NULL }, + { V('C','s'), 1, "¤", NULL }, + { V('D','o'), 1, "$", NULL }, + { V('E','u'), 1, "€", NULL }, + { V('F','c'), 1, "»", NULL }, + { V('F','i'), 3, "ffi", NULL }, + { V('F','l'), 3, "ffl", NULL }, + { V('F','o'), 1, "«", NULL }, + { V('O','E'), 1, "Œ", NULL }, + { V('P','o'), 1, "£", NULL }, + { V('S','1'), 1, "¹", NULL }, + { V('S','2'), 1, "²", NULL }, + { V('S','3'), 1, "³", NULL }, + { V('S','d'), 1, "ð", NULL }, + { V('T','P'), 1, "Þ", NULL }, + { V('T','p'), 1, "þ", NULL }, + { V('Y','e'), 1, "¥", NULL }, + { V('^','A'), 1, "Â", NULL }, + { V('^','E'), 1, "Ê", NULL }, + { V('^','I'), 1, "Î", NULL }, + { V('^','O'), 1, "Ô", NULL }, + { V('^','U'), 1, "Û", NULL }, + { V('^','a'), 1, "â", NULL }, + { V('^','e'), 1, "ê", NULL }, + { V('^','i'), 1, "î", NULL }, + { V('^','o'), 1, "ô", NULL }, + { V('^','u'), 1, "û", NULL }, + { V('`','A'), 1, "À", NULL }, + { V('`','E'), 1, "È", NULL }, + { V('`','I'), 1, "Ì", NULL }, + { V('`','O'), 1, "Ò", NULL }, + { V('`','U'), 1, "Ù", NULL }, + { V('`','a'), 1, "à", NULL }, + { V('`','e'), 1, "è", NULL }, + { V('`','i'), 1, "ì", NULL }, + { V('`','o'), 1, "ò", NULL }, + { V('`','u'), 1, "ù", NULL }, + { V('a','a'), 1, "´", NULL }, + { V('a','e'), 1, "æ", NULL }, + { V('a','p'), 1, "≈", NULL }, + { V('a','q'), 1, "'", NULL }, + { V('a','t'), 1, "@", NULL }, + { V('a','~'), 1, "~", NULL }, + { V('b','a'), 1, "|", NULL }, + { V('b','b'), 1, "|", NULL }, + { V('b','r'), 1, "|", NULL }, + { V('b','r'), 1, "|", NULL }, + { V('b','u'), 1, "•", NULL }, + { V('b','v'), 1, "|", NULL }, + { V('c','*'), 1, "⊗", NULL }, + { V('c','+'), 1, "⊕", NULL }, + { V('c','i'), 1, "○", NULL }, + { V('c','o'), 1, "©", NULL }, + { V('c','q'), 1, "'", NULL }, + { V('c','t'), 1, "¢", NULL }, + { V('d','A'), 1, "⇓", NULL }, + { V('d','a'), 1, "↓", NULL }, + { V('d','d'), 1, "=", NULL }, + { V('d','e'), 1, "°", NULL }, + { V('d','g'), 1, "-", NULL }, + { V('d','i'), 1, "÷", NULL }, + { V('d','q'), 1, """, NULL }, + { V('e','m'), 3, "---", NULL }, /* em dash */ + { V('e','n'), 1, "-", NULL }, /* en dash */ + { V('e','q'), 1, "=", NULL }, + { V('e','s'), 1, "Ø", NULL }, + { V('e','u'), 1, "€", NULL }, + { V('f','/'), 1, "⁄", NULL }, + { V('f','c'), 1, "›", NULL }, + { V('f','f'), 2, "ff", NULL }, + { V('f','i'), 2, "fi", NULL }, + { V('f','l'), 2, "fl", NULL }, + { V('f','m'), 1, "´", NULL }, + { V('f','o'), 1, "‹", NULL }, + { V('g','a'), 1, "`", NULL }, + { V('h','A'), 1, "⇔", NULL }, + { V('h','y'), 1, "-", NULL }, + { V('i','f'), 1, "∞", NULL }, + { V('i','s'), 8, "Integral", NULL }, /* integral sign */ + { V('l','A'), 1, "⇐", NULL }, + { V('l','B'), 1, "[", NULL }, + { V('l','C'), 1, "{", NULL }, + { V('l','a'), 1, "<", NULL }, + { V('l','b'), 1, "[", NULL }, + { V('l','c'), 2, "|¯", NULL }, + { V('l','f'), 2, "|_", NULL }, + { V('l','h'), 1, "☚", NULL }, + { V('l','k'), 1, "<FONT SIZE=\"+2\">{</FONT>", NULL }, + { V('l','q'), 1, "\"", NULL }, + { V('l','z'), 1, "◊", NULL }, + { V('m','c'), 1, "µ", NULL }, + { V('m','i'), 1, "-", NULL }, + { V('m','u'), 1, "×", NULL }, + { V('n','o'), 1, "¬", NULL }, + { V('o','A'), 1, "Å", NULL }, + { V('o','a'), 1, "å", NULL }, + { V('o','e'), 1, "œ", NULL }, + { V('o','q'), 1, "'", NULL }, + { V('o','r'), 1, "|", NULL }, + { V('p','d'), 1, "d", NULL }, /* partial derivative */ + { V('p','l'), 1, "+", NULL }, + { V('p','s'), 1, "¶", NULL }, + { V('r','!'), 1, "¡", NULL }, + { V('r','?'), 1, "¿", NULL }, + { V('r','A'), 1, "⇒", NULL }, + { V('r','B'), 1, "]", NULL }, + { V('r','C'), 1, "}", NULL }, + { V('r','a'), 1, ">", NULL }, + { V('r','c'), 2, "¯|", NULL }, + { V('r','f'), 2, "_|", NULL }, + { V('r','g'), 1, "®", NULL }, + { V('r','h'), 1, "☛", NULL }, + { V('r','k'), 1, "<FONT SIZE=\"+2\">}</FONT>", NULL }, + { V('r','n'), 1, "¯", NULL }, + { V('r','q'), 1, "\"", NULL }, + { V('r','s'), 1, "\\", NULL }, + { V('r','u'), 1, "_", NULL }, + { V('s','c'), 1, "§", NULL }, + { V('s','h'), 1, "#", NULL }, + { V('s','l'), 1, "/", NULL }, + { V('s','q'), 1, "□", NULL }, + { V('s','s'), 1, "ß", NULL }, + { V('t','f'), 1, "∴", NULL }, + { V('t','i'), 1, "~", NULL }, + { V('t','m'), 1, "™", NULL }, + { V('t','s'), 1, "s", NULL }, /* should be terminal sigma */ + { V('u','A'), 1, "⇑", NULL }, + { V('u','a'), 1, "↑", NULL }, + { V('u','l'), 1, "_", NULL }, + { V('~','A'), 1, "Ã", NULL }, + { V('~','N'), 1, "Ñ", NULL }, + { V('~','O'), 1, "Õ", NULL }, + { V('~','a'), 1, "ã", NULL }, + { V('~','n'), 1, "ñ", NULL }, + { V('~','o'), 1, "õ", NULL }, + { 0, 0, NULL, NULL } + + +}; + +void stdinit(void) { + STRDEF *stdf; + int i; + + stdf = &standardchar[0]; + i = 0; + while (stdf->nr) { + if (stdf->st) stdf->st = xstrdup(stdf->st); + stdf->next = &standardchar[i]; + stdf = stdf->next; + i++; + } + chardef=&standardchar[0]; + + stdf=&standardstring[0]; + i=0; + while (stdf->nr) { + /* waste a little memory, and make a copy, to avoid + the segfault when we free non-malloced memory */ + if (stdf->st) stdf->st = xstrdup(stdf->st); + stdf->next = &standardstring[i]; + stdf = stdf->next; + i++; + } + strdef=&standardstring[0]; + + intdef=&standardint[0]; + i=0; + while (intdef->nr) { + if (intdef->nr == NROFF) intdef->nr = nroff; else + if (intdef->nr == TROFF) intdef->nr = !nroff; + intdef->next = &standardint[i]; + intdef = intdef->next; + i++; + } + intdef = &standardint[0]; + defdef = NULL; +} + + +LONGSTRDEF* find_longstrdef(LONGSTRDEF * head, int nr, char * longname, char ** out_longname) +{ + char *p, c; + LONGSTRDEF *de; + + p = longname; + while (p && !isspace(*p)) p++; + c = *p; + *p = 0; + + de = head; + while (de && (de->nr != nr || (de->longname && strcmp(longname, de->longname)))) + de = de->next; + + if (out_longname) + *out_longname = de ? de->longname : xstrdup(longname); + *p = c; + return de; +}
D
one/help.sh
@@ -1,1 +0,0 @@
-man ../share/man/man1/man2html.1.gz | ./man2html -botm 0 -cgiurl '/page/$section/$title' -leftm 0 -noheads -topm 0 > man2.html
D
one/man.cgi
@@ -1,404 +0,0 @@
-#!/usr/bin/perl -##---------------------------------------------------------------------------## -## File: -## @(#) man.cgi 1.2 97/08/12 12:58:26 @(#) -## Author: -## Earl Hood ehood@medusa.acs.uci.edu -## Description: -## man.cgi is a CGI program for viewing Unix manpages. The -## program man2html, -## <URL:http://www.oac.uci.edu/indiv/ehood/man2html.html>, -## is used to convert the output from man(1) to html. -## -## If man.cgi is invoked with no input data, it will output a -## form for the user to select a manpage to view. -## man.cgi can handle POST and GET methods. -## -## The code section "Configureable Globals" is designed to -## allow you to modify man.cgi to work with your particular -## system configuration. -##---------------------------------------------------------------------------## -## Copyright (C) 1995-1997, Earl Hood, ehood@medusa.acs.uci.edu -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 2 of the License, or -## (at your option) any later version. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with this program; if not, write to the Free Software -## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -## 02111-1307, USA -##---------------------------------------------------------------------------## - -######################################################################## -## Configureable Globals -######################################################################## -## Change the value of these variables to reflect your -## system configuration. -######################################################################## - -## "English" name for program - -$ProgName = "Manpage Viewer"; - -## cgi-bin directory as accessed by a URL. - -$CgiBin = "/cgi-bin"; - -## man program (should be a full pathname) - -$ManPrg = '/usr/bin/man'; - -## man(1) option to specify a section. "-s" is used for Solaris -## systems. If using Tom Christiansen's Perl man program, than -## define use "". - -#$SectOpt = ""; -$SectOpt = "-s"; - -## man2html program (needs to be a full pathname) - -$ManConvPrg = '/usr/bin/man2html'; - -## Flag if the -cgiurl option should be used - -$DoCgiurl = 1; - -## System specific arguments to man2html: -## HP => ("-leftm", "1", "-topm", "8") -## Sun => ("-sun") -## See man2html documentation for more information. - -#@ConvArgs = ("-compress"); -#@ConvArgs = ("-compress", "-leftm", "1", "-topm", "8"); -@ConvArgs = ("-compress", "-sun"); - -## Keyword search processing arguments for man2html. Normally, -## '-k' is adequate. However, if on a Solaris system, the -## '-solaris' option should be specified with '-k'. See -## man2html documentation on information about the '-solaris' option. - -#@KeyWArgs = ("-k"); # Normal -@KeyWArgs = ("-k", "-solaris"); # For Solaris - -## Possible manual sections. This array is used to determine the -## the choices available in an option menu. - -@Sections = ( - '1', '1F', '1M', - '2', - '3', '3C', '3F', '3G', '3I', '3N', '3S', '3X', - '4', - '5', - '6', - '7', - '8', - '9', '9F', -); - -## Form method. The value is either 'GET' or 'POST'. 'GET' is -## recommended since the URL sent by the client also contains -## the argument information. This allows a client's "Reload" function -## to reprocess a currently viewed manpage. - -$FormMethod = 'GET'; - -## Argument separator for CGI URL links. As clients become more -## SGML conformant, the simple use of '&' conflicts with -## SGML syntax. You can set this variable to control what is -## used as the separator. Possibilities: -## & -## & -## ; -## - -$ArgSep = '&'; - -## Man directories. Add paths to the list you want man(1) to -## know about - -@ManPath = qw( - /usr/man - /usr/openwin/man - /usr/man -); - -## PATH setting. Modify as see fit. Once useful modification -## is to have groff utils first in path since its nroff would -## be invoked over the systems nroff when man formats a manpage. - -@Path = qw( - /opt/FSFgroff/bin - /bin - /usr/bin -); - -######################################################################## -## END!!!! Configureable Globals section -######################################################################## - -######################################################################## -## Globals -######################################################################## - -($PROG = $0) =~ s/.*\///; # Name of program -$VERSION = '2.0.1'; # Version -%FORM = (); # Hash to hold form contents -$Error = ''; # Error string -$ENV{'MANPATH'} = join(":", @ManPath); -$ENV{'PATH'} = join(":", @Path); - -######################################################################## -## Main block -{ - # Set unbuffered I/O. Prevents buffering problems with - # "system()" calls. - select((select(STDOUT), $| = 1)[0]); - - # Print content-type header - printouttype("text/html"); - - # Print man form if called w/no arguments - printform() if noarg(); - - # If reached here, there is input to process - error("CGI input error") unless parseinput(); - printform() unless $FORM{'topic'}; - doit(); - exit 0; -} -######################################################################## -## Subroutines -######################################################################## - -#----------------------------------------------------------------------- -# printform outputs the man selection form to the client. -# -sub printform { - printhead($ProgName); - print STDOUT <<EndOfForm; -<p>The following form allows you to view a manpage on this system. -Please fill out the following fields and select <strong>Submit</strong> -to view a manpage. -</p> -<form method="$FormMethod" action="$CgiBin/man.cgi"> -<table border=0> -<tr> -<td align=right>Section:</td> -<td><select name=section> -<option value="all">All Sections</option> -<option value="keyword">Keyword Search</option> -EndOfForm - - # Print out possible section choices - local($section); - foreach $section (@Sections) { - print STDOUT qq|<option value="$section">Section $section</option>\n|; - } - -print STDOUT <<EndOfForm; -</select> -</td> -</tr> -<tr> -<td align=right>Topic:</td> -<td><input type="TEXT" name="topic"></td> -</tr> -<tr> -<td></td><td><input type="SUBMIT" value="Submit"><td> -</tr> -</table> -</form> -EndOfForm - printend(); - exit 0; -} - -#----------------------------------------------------------------------- -# doit does the conversion -# -sub doit { - my($section, $topic, $manexec, $manout, $tmp); - $manout = ''; - - # Get section and topic from input - #--------------------------------- - $section = $FORM{'section'}; - $topic = $FORM{'topic'}; - error("Questionable characters in topic") if isquestionable($topic); - - # Determine command arguments for man and man2html - #------------------------------------------------- - @ARGV = (); - @manargs = (); - $manexec = $ManPrg; - if ($section =~ /keyword/) { - $manexec .= " -k $topic"; - push(@manargs, "-k", $topic); - push(@ARGV, @KeyWArgs, - "-title", qq{Keyword search: "$topic"}); - } else { - error("No topic entered") unless $topic; - if ($section !~ /all/) { - push(@manargs, $SectOpt) if $SectOpt; - push(@manargs, $section); - } - push(@manargs, $topic); - $manexec .= " $section" if $section !~ /all/; - $manexec .= " $topic"; - $tmp = $topic; - $tmp .= "($section)" if $section !~ /all/; - push(@ARGV, @ConvArgs, - "-title", $tmp); - } - - # Check if doing man xref detection - #---------------------------------- - if ($DoCgiurl) { - push(@ARGV, "-cgiurl", - join('', $CgiBin, '/man.cgi?', - 'section=${section}${subsection}', - $ArgSep, - 'topic=${title}')); - } - - # Convert output from man to html - #-------------------------------- - close(STDERR); - open(MANPRG, "-|") or exec($ManPrg, @manargs); - $Man2Html::InFH = \*MANPRG; # set input filehandle - require $ManConvPrg or - error("Problem executing man->HTML converter"); -} - -######################################################################## -## Generic subroutines for CGI use -######################################################################## - -#----------------------------------------------------------------------- -# noarg returns true if no arguments were passed to script. -# -sub noarg { - $ENV{"REQUEST_METHOD"} eq "GET" && $ENV{"QUERY_STRING"} =~ /^\s*$/; -} - -#----------------------------------------------------------------------- -# parseinput converts the input data into the %FORM array -# -sub parseinput { - my($method) = ($ENV{"REQUEST_METHOD"}); - my($data); - if ($method eq "GET") { - $data = $ENV{"QUERY_STRING"}; - } elsif ($method eq "POST") { - read(STDIN, $data, $ENV{"CONTENT_LENGTH"}); - } else { - $Error = "Unrecgonized request method : $method"; - return 0; - } - my(@pairs, $name, $value); - if ($data ne '') { - @pairs = split(/&/, $data); - foreach (@pairs) { - ($name, $value) = split(/=/); - $name = expandstr($name); - $value = expandstr($value); - $FORM{$name} = $value; - } - } - 1; -} - -#----------------------------------------------------------------------- -# printouttype prints out specified content-type header back -# to client -# -sub printouttype { - my($type) = shift; - print STDOUT "Content-type: $type\r\n\r\n"; -} - -#----------------------------------------------------------------------- -# printhead outputs html prematter -# -sub printhead { - my($title, $h1) = @_; - $h1 = $title unless $h1; - - print STDOUT <<ENDOFHEAD; -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML//EN"> -<HTML> -<HEAD> -<TITLE>$title</TITLE> -</HEAD> -<BODY> -<H1>$h1</H1> -ENDOFHEAD -} - -#----------------------------------------------------------------------- -# printend outputs html postmatter -# -sub printend { - print STDOUT <<ENDOFEND; -<HR> -<ADDRESS> -Manpage viewer available with the -<a href="http://www.oac.uci.edu/indiv/ehood/man2html.html">man2html</a> -package. -</ADDRESS> -</BODY> -</HTML> -ENDOFEND -} - -#----------------------------------------------------------------------- -# error prints an error out to the client. -# -sub error { - my($str) = htmlize(shift); - printhead("$ProgName Error"); - $str .= ":" if $Error && $str; - $str .= " $Error"; - print STDOUT "<p>$str</p>"; - printend(); - exit 0; -} - -#----------------------------------------------------------------------- -# htmlize translates special characters to enitity refs. -# -sub htmlize { - my($str) = shift; - $str =~ s/&/\&/g; - $str =~ s/</\</g; - $str =~ s/>/\>/g; - $str; -} - -#----------------------------------------------------------------------- -# expandstr translates hex codes to characters -# -sub expandstr { - my($str) = shift; - $str =~ tr/+/ /; - $str =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/ge; - $str; -} - -#----------------------------------------------------------------------- -# isquestionable determines if $str contains questionable -# characters if $str is used in a subshell invocation. -# -sub isquestionable { - my($str) = shift; - $str !~ /^[a-zA-Z0-9_\-+ \t\/@%\.]+$/; -} - -########################################################################
D
one/man.html
@@ -1,433 +0,0 @@
-<HTML> -<HEAD> -<TITLE>man</TITLE> -</HEAD> -<BODY> -<H1>man</H1> -<HR> -<PRE> -<!-- Manpage converted by man2html 3.0.1 --> -<B><A HREF="/page/1/MAN2HTML">MAN2HTML(1)</A></B> General Commands Manual <B><A HREF="/page/1/MAN2HTML">MAN2HTML(1)</A></B> - -NAME - man2html - convert UNIX <B><A HREF="/page/1/nroff">nroff(1)</A></B> manual pages to HTML format - -SYNOPSIS - man2html [-bare] [-belem name] [-botm lines] [-cgiurl string] - [-cgiurlexp expr] [-compress] [-headmap mapfile] [-help] [-k] - [-leftm chars] [-nodepage] [-noheads] [-pgsize lines] - [-seealso] [-solaris] [-sun] [-title string] [-topm lines] - [-uelem name] - - Typical Usage: - - man2html [-options] < infile > outfile - - man topic | man2html [-options] > outfile - -DESCRIPTION - The man2html filter reads formatted nroff text from standard input - (stdin) and writes a HTML document to standard output (stdout). - - The formatted nroff output is surrounded with <PRE> tags with the fol‐ - lowing exceptions/additions: - - • Section heads are wrapped in HTML header tags. See the SEC‐ - TION HEAD MAP FILE section below for additional information. The - -noheads option can be used to disable this feature. - - • Bold words designated by a "<char><bs><char>" sequences are wrapped - in <B> tags (or the element specified via the -belem option). - - • Underlined words designated by a "_<bs><char>" sequences are - wrapped in <I> tags (or the element specified via the -uelem op‐ - tion). - -OPTIONS - -bare - This option will eliminate HTML <HEAD> and <BODY> tags from the - output. This is useful when you wish to incorporate the output - into another HTML document. - - -belem name - Use name as the name of the element to wrap overstriken charac‐ - ters. The default is B. - - -botm lines - The lines argument specifies the number of lines representing the - bottom margin of the formatted nroff input. The line count in‐ - cludes any running footers. The default value is 7. - - -cgiurl string - The string argument specifies a template URL for creating links to - other manpages. See the LINKING TO OTHER MANPAGES section below - for additional information. - - -cgiurlexp expr - The expr argument specifies a Perl expression evaluting to a URL - for creating links to other manpages. See the LINK‐ - ING TO OTHER MANPAGES section below for additional information. - - -compress - Compress consecutive blank lines into a single line. - - -headmap mapfile - The mapfile argument is read to determine which HTML header tags - are to be used for various section heading in the manpage. See - the SECTION HEAD MAP FILE section below for information on the - format of the map file. - - -help - Print out a short usage message and then exit immediately. - - -k Process input resulting from a manpage keyword search (man -k). - See the KEYWORD SEARCH section below for additional information. - - -leftm chars - The chars argument specifies the width of the number of characters - making up the left margin of the formatted nroff input. The de‐ - fault value is 0. - - -nodepage - By default, man2html merges multi-page formatted nroff into a sin‐ - gle page. This option may be used to disable depagination, caus‐ - ing running headers and footers in the formatted nroff input to be - carried over into the HTML output. - - -noheads - By default, man2html wraps section heads in HTML header tags. See - the SECTION HEAD MAP FILE section below for additional informa‐ - tion. This option may be specified to disabled this feature. - - -pgsize lines - The lines argument specifies the number of lines making up the - page size (length) of the formatted nroff input. The default - value is 66. - - -seealso - If the -cgiurl option has been specified, then this option re‐ - stricts the creation of links to other manual pages to the - SEE ALSO section only. - - -solaris - If the -k option has been specified, then this option modifies its - operation to process the alternate manual page keyword search for‐ - mat produced by the <B><A HREF="/page/1/man">man(1)</A></B> utility on systems running Solaris. - See the KEYWORD SEARCH section below for additional information. - - -sun Do not require a section head to have bold overstriking in the - formatted nroff input. The option is called sun because it was on - a Sun workstation that section heads in manpages were found to not - be overstruck. - - -title string - By default, man2html does not generate a HTML title (<TITLE>). - This option sets the title of the HTML output to the specified - string. - - -topm lines - The lines argument specifies number number of lines representing - the top margin of the formatted nroff input. The line count in‐ - cludes any running headers. The default value is 7. - - -uelem name - Use name as the name of the element to wrap underscored charac‐ - ters. The default is I. - -SECTION HEAD MAP FILE - The -headmap option may be used to customize which HTML header tags, - <H1> ... <H6>, are used in manpage section headings. Normally, - man2html treats lines that are flush to the left margin (-leftm), and - contain overstriking (overstrike check is canceled with the -sun op‐ - tion), as section heads. However, you can augment/override what HTML - header tags are used for any given section head. - - In order to write a section head map file, you will need to know about - <B><A HREF="/page/1/perl">perl(1)</A></B> associative arrays. You do not need to be an expert in perl to - write a map file, however, having knowledge of perl allows you to be - more clever. - - Augmenting the Default Map - To add to the default mapping defined by man2html, your map file will - contain lines with the following syntax: - - $SectionHead{'<section head text>'} = '<html header tag>'; - - where - - <section head text> - is the text of the manpage section head. For example: SYNOPSIS - or DESCRIPTION. - - <html header tag> - is the HTML header tag to wrap the section head in. Legal val‐ - ues are: <H1>, <H2>, <H3>, <H4>, <H5>, <H6>. - - Overriding the Default Map - To override the default mapping with your own, then your map file will - have the following syntax: - - %SectionHead = ( - '<section head text>', '<html header tag>', - '<section head text>', '<html header tag>', - # ... More section head/tag pairs - '<section head text>', '<html header tag>', - ); - - The Default Map - As of this writing, this is the default map used by man2html: - - %SectionHead = ( - '\S.*OPTIONS.*' => '<H2>', - 'AUTHORS?' => '<H2>', - 'BUGS' => '<H2>', - 'COMPATIBILITY' => '<H2>', - 'DEPENDENCIES' => '<H2>', - 'DESCRIPTION' => '<H2>', - 'DIAGNOSTICS' => '<H2>', - 'ENVIRONMENT' => '<H2>', - 'ERRORS' => '<H2>', - 'EXAMPLES' => '<H2>', - 'EXTERNAL INFLUENCES' => '<H2>', - 'FILES' => '<H2>', - 'LIMITATIONS' => '<H2>', - 'NAME' => '<H2>', - 'NOTES?' => '<H2>', - 'OPTIONS' => '<H2>', - 'REFERENCES' => '<H2>', - 'RETURN VALUE' => '<H2>', - 'SECTION.*:' => '<H2>', - 'SEE ALSO' => '<H2>', - 'STANDARDS CONFORMANCE' => '<H2>', - 'STYLE CONVENTION' => '<H2>', - 'SYNOPSIS' => '<H2>', - 'SYNTAX' => '<H2>', - 'WARNINGS' => '<H2>', - '\s+Section.*:' => '<H3>', - ); - $HeadFallback = '<H2>'; # Fallback tag if above is not found. - - Check the perl source code of man2html for the latest default mapping. - - You can reassign the $HeadFallback variable to a different value if you - choose. This value is used as the header tag of a section head if no - matches are found in the %SectionHead map. - - Using Regular Expressions in the Map File - You may have noticed unusual characters in the default map file, like - "\s" or "*". The man2html utility actual treats the - <section head text> as a perl regular expression. If you are comfort‐ - able with perl regular expressions, then you have their full power to - use in your map file. - - Caution: The man2html utility already anchors the regular expression to - the beginning of the line with left margin spacing specified by the - -leftm option. Therefore, do not use the `^' character to anchor your - regular expression to the beginning. However, you may end your expres‐ - sion with a `$' to anchor it to the end of the line. - - Since the <section head text> is actually a regular expression, you - will have to be careful of special characters if you want them to be - treated literally. Any of the characters `[ ] ( ) . ^ { } $ * ? + |' - should be escaped by prefixing them by the `\' character if you want - perl to treat them "as is". - - Caution: One should use single quotes instead of double quotes to de‐ - limit <section head text>. This will preserve any `\' characters for - character escaping or when the `\' is used for special perl character - matching sequences (e.g., \s, \w, \S). - - Other Tid-bits on the Map File - Comments can be inserted in the map file by using the '#' character. - Anything after, and including, the '#' character is ignored, up to the - end of line. - - You might be thinking that the above is quite-a-bit-of-stuff just for - doing manpage section heads. However, you will be surprised how much - better the HTML output looks with header tags, even though, everything - else is in a <PRE> tag. - -LINKING TO OTHER MANPAGES - The man2html utility allows the ability to link to other manpage refer‐ - ences. If the -cgiurl option is specified, man2html will create an‐ - chors that link to other manpages. - - The URL entered with the -cgiurl option is actually a template that de‐ - termines the actual URL used to link to other manpages. The following - variables are defined during run time that may be used in the template - string: - - $title The title of the manual page referenced. - - $section - The section number of the manual page referenced. - - $subsection - The subsection of the manual page referenced. - - Any other text in the template is preserved "as is". - - Caution: The man2html utility evaluates the template string as a perl - string expression. Therefore, one might need to surround the variable - names with '{}' (e.g., ${title}) so that man2html properly recognizes - the variable. - - Note: If a CGI program calling man2html is actually a shell script or a - perl program, make sure to properly escape the '$' character in the URL - template to avoid variable interpolation by the CGI program. - - Normally, the URL calls a CGI program (hence the option name), but the - URL can easily link to statically converted documents. - - Example1: - The following template string is specified to call a CGI program to re‐ - trieve the appropriate manpage linked to: - - /cgi-bin/man.cgi?section=${section}${subsection}&topic=${title} - - If the <B><A HREF="/page/1/ls">ls(1)</A></B> manpage is referenced in the SEE ALSO section, the above - template will translate to the following URL: - - /cgi-bin/man.cgi?section=1&topic=ls - - The actual HTML markup will look like the following: - - <A HREF="/cgi-bin/man.cgi?section=1&topic=ls"><B><A HREF="/page/1/ls">ls(1)</A></B></A> - - Example2: - The following template string is specified to retrieve pre-converted - manpages: - - http://foo.org/man$section/$title.$section$subsection.html - - If the <B><A HREF="/page/1/mount">mount(1M)</A></B> manpage is referenced, the above template will trans‐ - late to the following URL: - - http://foo.org/man1/mount.1M.html - - The actual HTML markup will look like the following: - - <A HREF="http://foo.org/man1/mount.1M.html"><B><A HREF="/page/1/mount">mount(1M)</A></B></A> - - -cgiurlexp - The option -cgiurlexp is a more general form of the -cgiurl option. - -cgiurlexp allows one to specify a general Perl expression. For exam‐ - ple: - - $title=~/^db_/i?"$title.html":"/cgi-bin/man?$title+$section" - - A -cgiurl string can be expressed as follows with -cgiurlexp: - - return "string" - -KEYWORD SEARCH - The man2html utility has the ability to process keyword search output - generated by the man -k or apropos commands, through the use of the -k - option. The man2html utility will generate an HTML document of the - keyword search input having the following format: - - • All manpage references are listed by section. - - • Within each section listing, the manpage references are sorted al‐ - phabetically (case-sensitive) in a <DL> tag. The manpage refer‐ - ences are listed in the <DT> section, and the summary text is - listed in the <DD> section. - - • Each manpage reference listed is a hyperlink to the actual manpage - as specified by the -cgiurl option. - - This ability to process keyword searches gives nice added functionality - to a WWW forms interface to <B><A HREF="/page/1/man">man(1)</A></B>. Even if you have statically con‐ - verted manpages to HTML via another man->HTML program, you can use - man2html and "man -k" to provide keyword search capabilities easily for - your HTML manpages. - - Processing Keyword Search Results - Unfortunately, there is no standard controlling the format of keyword - search results. The man2html utility tries it best to handle all the - variations. However, the keyword search results generated by the So‐ - laris operating system is different enough from other systems that a - special command-line option (-solaris) must be specified to handle its - output. - - Example of raw Solaris-type keyword search results: - strcpy strcpy (9f) - copy a string from one location to another. - strcpy string (3c) - string operations - strncpy strcpy (9f) - copy a string from one location to another. - strncpy string (3c) - string operations - - If keyword search results on your systems appear in the following for‐ - mat: - - <topic> <actual_manpage> (#) - Description - - then you need to specify the -solaris option in addition to the -k op‐ - tion. - -ADDITIONAL NOTES - Different systems format manpages differently. Here is a list of rec‐ - ommended command-line options for certain systems: - - Convex: <defaults should be okay> - HP: -leftm 1 -topm 8 - Sun: -sun (and -solaris when using -k) - - Some line spacing gets lost in the formatted nroff since the spacing - would occur in the middle of a page break. This can cause text to be - merged that shouldn't be merged when man2html depaginates the text. To - avoid this problem, man2html keeps track of the margin indent right be‐ - fore and after a page break. If the margin width of the line after the - page break is less than the line before the page break, then man2html - inserts a blank line in the HTML output. - - A manpage cross-reference is detected by the following pseudo expres‐ - sion: [A-z.-+_]+([0-9][A-z]?) - - The man2html utility only recognizes lines with " - " (the normal sepa‐ - rator between manpage references and summary text) while in keyword - search mode. - - The man2html utility can be hooked in a CGI script/program to convert - manpages on the fly. This is the reason for the -cgiurl option. - -LIMITATIONS - The order that section head mapping is searched is not defined. There‐ - fore, if two or more <section head text> can match a give manpage sec‐ - tion, there is no way to determine which map tag is chosen. - - If -seealso is specified, all xrefs are detected after the SEE ALSO - heading. In other words, sections after SEE ALSO may contain hyper‐ - linked xrefs. - -BUGS - Text that is flush to the left margin, but is not actually a section - head, can be mistaken for a section head. This mistake is more likely - when the -sun option is in affect. - -VERSION - This documentation describes man2html version 3.0.1 - -SEE ALSO - <B><A HREF="/page/1/man">man(1)</A></B>, <B><A HREF="/page/1/nroff">nroff(1)</A></B>, <B><A HREF="/page/1/perl">perl(1)</A></B> - - http://www.oac.uci.edu/indiv/ehood/man2html.html - -AUTHOR - Earl Hood - ehood@medusa.acs.uci.edu - -ERRORS AND OMISSIONS - Troff version of this document initially created for version 2.1.0 by - C. Jeffery Small (jeff@cjsa.com) by copying, reformatting, rearranging - and partially rewriting the contents of the ascii text file - doc/man2html.txt. - - 97/08/12 <B><A HREF="/page/1/MAN2HTML">MAN2HTML(1)</A></B> -</PRE> -<HR> -<ADDRESS> -Man(1) output converted with -<a href="http://www.oac.uci.edu/indiv/ehood/man2html.html">man2html</a> -</ADDRESS> -</BODY> -</HTML>
D
one/man2html
@@ -1,609 +0,0 @@
-#!/usr/bin/perl -use lib qw(/usr/share/perl5/site_perl); -#!/usr/local/bin/perl -##---------------------------------------------------------------------------## -## File: -## @(#) man2html 1.2 97/08/12 12:57:30 @(#) -## Author: -## Earl Hood, ehood@medusa.acs.uci.edu -## Description: -## man2html is a Perl program to convert formatted nroff output -## to HTML. -## -## Recommend command-line options based on platform: -## -## Platform Options -## --------------------------------------------------------------------- -## c2mp <None, the defaults should be okay> -## hp9000s700/800 -leftm 1 -topm 8 -## sun4 -sun -## --------------------------------------------------------------------- -## -##---------------------------------------------------------------------------## -## Copyright (C) 1995-1997 Earl Hood, ehood@medusa.acs.uci.edu -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 2 of the License, or -## (at your option) any later version. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with this program; if not, write to the Free Software -## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -## 02111-1307, USA -##---------------------------------------------------------------------------## - -package Man2Html; - -use Getopt::Long; - -($PROG = $0) =~ s/.*\///; -$VERSION = "3.0.1"; - -## Input and outputs filehandles -$InFH = \*STDIN unless $InFH; -$OutFH = \*STDOUT unless $OutFH; - -## Backspace character: Used in overstriking detection -*bs = \"\b"; - -## Hash of section titles and their HTML tag wrapper. -## This list allows customization of what HTML tag is used for -## a given section head. -## -## The section title can be a regular expression. Therefore, one must -## be careful about quoting special characters. -## -%SectionHead = ( - - '\S.*OPTIONS.*' => '<H2>', - 'AUTHORS?' => '<H2>', - 'BUGS' => '<H2>', - 'COMPATIBILITY' => '<H2>', - 'DEPENDENCIES' => '<H2>', - 'DESCRIPTION' => '<H2>', - 'DIAGNOSTICS' => '<H2>', - 'ENVIRONMENT' => '<H2>', - 'ERRORS' => '<H2>', - 'EXAMPLES' => '<H2>', - 'EXTERNAL INFLUENCES' => '<H2>', - 'FILES' => '<H2>', - 'LIMITATIONS' => '<H2>', - 'NAME' => '<H2>', - 'NOTES?' => '<H2>', - 'OPTIONS' => '<H2>', - 'REFERENCES' => '<H2>', - 'RETURN VALUE' => '<H2>', - 'SECTION.*:' => '<H2>', - 'SEE ALSO' => '<H2>', - 'STANDARDS CONFORMANCE' => '<H2>', - 'STYLE CONVENTION' => '<H2>', - 'SYNOPSIS' => '<H2>', - 'SYNTAX' => '<H2>', - 'WARNINGS' => '<H2>', - '\s+Section.*:' => '<H3>', - -); - -## Fallback tag if above is not found -$HeadFallback = '<H2>'; - -## Other gobals - -$Bare = 0; # Skip printing HTML head/foot flag -$BTag = 'B'; # Overstrike tag -$CgiUrl = ''; # CGI URL expression -$Compress = 0; # Do blank line compression flag -$K = 0; # Do keyword search processing flag -$NoDepage = 0; # Do not strip page information -$NoHeads = 0; # Do no header detection flag -$SeeAlso = 0; # Do only SEE ALSO xrefs flag -$Solaris = 0; # Solaris keyword search processing flag -$Sun = 0; # Headers not overstriken flag -$Title = ''; # Title -$UTag = 'I'; # Underline tag -$ftsz = 7; # Bottome margin size -$hdsz = 7; # Top margin size -$leftm = ''; # Left margin pad -$leftmsz = 0; # Left margin size -$pgsz = 66; # Size of page size -$txsz = 52; # Text body length size - -############################################################################# -## Main Block -############################################################################# -{ - if (get_cli_opts()) { - if ($K) { - man_k(); - } else { - do_it(); - } - } else { - usage(); - } -} - -############################################################################# -## Subroutines -############################################################################# - -sub do_it { - - ## Define while loop and then eval it when used. The reason - ## is to avoid the regular expression reevaulation in the - ## section head detection code. - - $doitcode =<<'EndOfDoItCode'; - - my($line, $tmp, $i, $head, $preindent, $see_also, $do); - - $see_also = !$SeeAlso; - print $OutFH "<!-- Manpage converted by man2html $VERSION -->\n"; - LOOP: while(!eof($InFH)) { - $blank = 0; - for ($i=0; $i < $hdsz; $i++) { - last LOOP unless defined($_ = <$InFH>); - } - for ($i=0; $i < $txsz; $i++) { - last LOOP unless defined($_ = <$InFH>); - - ## Check if compress consecutive blank lines - if ($Compress and !/\S/) { - if ($blank) { next; } else { $blank = 1; } - } else { - $blank = 0; - } - - ## Try to check if line space is needed at page boundaries ## - if (!$NoDepage && ($i==0 || $i==($txsz-1)) && !/^\s*$/) { - /^(\s*)/; $tmp = length($1); - if ($do) { - if ($tmp < $preindent) { print $OutFH "\n"; } - } else { - $do = 1; - } - $preindent = $tmp; - } else { - $do = 0; $preindent = 0; - } - - ## Interpret line - $line = $_; - entitize(\$_); # Convert [$<>] to entity references - - ## Check for 'SEE ALSO' link only - if (!$see_also && $CgiUrl && $SeeAlso) { - ($tmp = $line) =~ s/.\010//go; - if ($tmp =~ /^\s*SEE\s+ALSO\s*$/o) { $see_also = 1; } - else { $see_also = 0; } - } - - ## Create anchor links for manpage references - s/((((.\010)+)?[\+_\.\w-])+\(((.\010)+)? - \d((.\010)+)?\w?\)) - /make_xref($1) - /geox if $see_also; - - ## Emphasize underlined words - # s/((_\010[^_])+[\.\(\)_]?(_\010[^_])+\)?)/emphasize($1)/oge; - # s/((_\010[^_])+([\.\(\)_]?(_\010[^_])+)?)/emphasize($1)/oge; - # - # The previous expressions were trying to be clever about - # detecting underlined text which contain non-alphanumeric - # characters. nroff will not underline non-alphanumeric - # characters in an underlined phrase, and the above was trying - # to detect that. It does not work all the time, and it - # screws up other text, so a simplified expression is used. - - s/((_\010[^_])+)/emphasize($1)/oge; - - $secth = 0; - ## Check for strong text and headings - if ($Sun || /.\010./o) { - if (!$NoHeads) { - $line =~ s/.\010//go; - $tmp = $HeadFallback; -EndOfDoItCode - - ## Create switch statement for detecting a heading - ## - $doitcode .= "HEADSW: {\n"; - foreach $head (keys %SectionHead) { - $doitcode .= join("", "\$tmp = '$SectionHead{$head}', ", - "\$secth = 1, last HEADSW ", - "if \$line =~ /^$leftm$head/o;\n"); - } - $doitcode .= "}\n"; - - ## Rest of routine - ## - $doitcode .=<<'EndOfDoItCode'; - if ($secth || $line =~ /^$leftm\S/o) { - chop $line; - $_ = $tmp . $line . $tmp; - s%<([^>]*)>$%</$1>%; - $_ = "\n</PRE>\n" . $_ . "<PRE>\n"; - } else { - s/(((.\010)+.)+)/strongize($1)/oge; - } - } else { - s/(((.\010)+.)+)/strongize($1)/oge; - } - } - print $OutFH $_; - } - - for ($i=0; $i < $ftsz; $i++) { - last LOOP unless defined($_ = <$InFH>); - } - } -EndOfDoItCode - - - ## Perform processing. - - printhead() unless $Bare; - print $OutFH "<PRE>\n"; - eval $doitcode; # $doitcode defined above - print $OutFH "</PRE>\n"; - printtail() unless $Bare; -} - -##--------------------------------------------------------------------------- -## -sub get_cli_opts { - return 0 unless - GetOptions( - "bare", # Leave out HTML, HEAD, BODY tags. - "belem=s", # HTML Element for overstriked text (def: "B") - "botm=i", # Number of lines for bottom margin (def: 7) - "cgiurl=s", # CGI URL for linking to other manpages - "cgiurlexp=s", # CGI URL Perl expr for linking to other manpages - "compress", # Compress consecutive blank lines - "headmap=s", # Filename of user section head map file - "k", # Process input from 'man -k' output. - "leftm=i", # Character width of left margin (def: 0) - "nodepage", # Do not remove pagination lines - "noheads", # Do not detect for section heads - "pgsize=i", # Number of lines in a page (def: 66) - "seealso", # Link to other manpages only in the SEE ALSO section - "solaris", # Parse 'man -k' output from a solaris system - "sun", # Section heads are not overstriked in input - "title=s", # Title of manpage (def: Not defined) - "topm=i", # Number of lines for top margin (def: 7) - "uelem=s", # HTML Element for underlined text (def: "I") - - "help" # Short usage message - ); - return 0 if defined($opt_help); - - $pgsz = $opt_pgsize || $pgsz; - if (defined($opt_nodepage)) { - $hdsz = 0; - $ftsz = 0; - } else { - $hdsz = $opt_topm if defined($opt_topm); - $ftsz = $opt_botm if defined($opt_botm); - } - $txsz = $pgsz - ($hdsz + $ftsz); - $leftmsz = $opt_leftm if defined($opt_leftm); - $leftm = ' ' x $leftmsz; - - $Bare = defined($opt_bare); - $Compress = defined($opt_compress); - $K = defined($opt_k); - $NoDepage = defined($opt_nodepage); - $NoHeads = defined($opt_noheads); - $SeeAlso = defined($opt_seealso); - $Solaris = defined($opt_solaris); - $Sun = defined($opt_sun); - - $Title = $opt_title || $Title; - $CgiUrl = $opt_cgiurlexp || - ($opt_cgiurl ? qq{return "$opt_cgiurl"} : ''); - - $BTag = $opt_belem || $BTag; - $UTag = $opt_uelem || $UTag; - $BTag =~ s/[<>]//g; - $UTag =~ s/[<>]//g; - - if (defined($opt_headmap)) { - require $opt_headmap or warn "Unable to read $opt_headmap\n"; - } - 1; -} - -##--------------------------------------------------------------------------- -sub printhead { - print $OutFH "<HTML>\n"; - print $OutFH "<HEAD>\n", - "<TITLE>$Title</TITLE>\n", - "</HEAD>\n" if $Title; - print $OutFH "<BODY>\n"; - print $OutFH "<H1>$Title</H1>\n", - "<HR>\n" if $Title; -} - -##--------------------------------------------------------------------------- -sub printtail { - print $OutFH <<EndOfRef; -<HR> -<ADDRESS> -Man(1) output converted with -<a href="http://www.oac.uci.edu/indiv/ehood/man2html.html">man2html</a> -</ADDRESS> -</BODY> -</HTML> -EndOfRef -} - -##--------------------------------------------------------------------------- -sub emphasize { - my($txt) = shift; - $txt =~ s/.\010//go; - $txt = "<$UTag>$txt</$UTag>"; - $txt; -} - -##--------------------------------------------------------------------------- -sub strongize { - my($txt) = shift; - $txt =~ s/.\010//go; - $txt = "<$BTag>$txt</$BTag>"; - $txt; -} - -##--------------------------------------------------------------------------- -sub entitize { - my($txt) = shift; - - ## Check for special characters in overstrike text ## - $$txt =~ s/_\010\&/strike('_', '&')/geo; - $$txt =~ s/_\010</strike('_', '<')/geo; - $$txt =~ s/_\010>/strike('_', '>')/geo; - - $$txt =~ s/(\&\010)+\&/strike('&', '&')/geo; - $$txt =~ s/(<\010)+</strike('<', '<')/geo; - $$txt =~ s/(>\010)+>/strike('>', '>')/geo; - - ## Check for special characters in regular text. Must be careful - ## to check before/after character in expression because it might be - ## a special character. - $$txt =~ s/([^\010]\&[^\010])/htmlize2($1)/geo; - $$txt =~ s/([^\010]<[^\010])/htmlize2($1)/geo; - $$txt =~ s/([^\010]>[^\010])/htmlize2($1)/geo; -} - -##--------------------------------------------------------------------------- -## escape special characters in a string, in-place -## -sub htmlize { - my($str) = shift; - $$str =~ s/&/\&/g; - $$str =~ s/</\</g; - $$str =~ s/>/\>/g; - $$str; -} - -##--------------------------------------------------------------------------- -## htmlize2() is used by entitize. -## -sub htmlize2 { - my($str) = shift; - $str =~ s/&/\&/g; - $str =~ s/</\</g; - $str =~ s/>/\>/g; - $str; -} - -##--------------------------------------------------------------------------- -## strike converts HTML special characters in overstriked text -## into entity references. The entities are overstriked so -## strongize() and emphasize() will recognize the entity to be -## wrapped in tags. -## -sub strike { - my($w, $char) = @_; - my($ret); - if ($w eq '_') { - if ($char eq '&') { - $ret = "_$bs\&_${bs}a_${bs}m_${bs}p_${bs};"; - } elsif ($char eq '<') { - $ret = "_$bs\&_${bs}l_${bs}t_${bs};"; - } elsif ($char eq '>') { - $ret = "_$bs\&_${bs}g_${bs}t_${bs};"; - } else { - warn qq|Unrecognized character, "$char", passed to strike()\n|; - } - } else { - if ($char eq '&') { - $ret = "\&$bs\&a${bs}am${bs}mp${bs}p;${bs};"; - } elsif ($char eq '<') { - $ret = "\&$bs\&l${bs}lt${bs}t;${bs};"; - } elsif ($char eq '>') { - $ret = "\&$bs\&g${bs}gt${bs}t;${bs};"; - } else { - warn qq|Unrecognized character, "$char", passed to strike()\n|; - } - } - $ret; -} - -##--------------------------------------------------------------------------- -## make_xref() converts a manpage crossreference into a hyperlink. -## -sub make_xref { - my $str = shift; - $str =~ s/.\010//go; # Remove overstriking - - if ($CgiUrl) { - my($title,$section,$subsection) = - ($str =~ /([\+_\.\w-]+)\((\d)(\w?)\)/); - - $title =~ s/\+/%2B/g; - my($href) = (eval $CgiUrl); - qq|<B><A HREF="$href">$str</A></B>|; - } else { - qq|<B>$str</B>|; - } -} - -##--------------------------------------------------------------------------- -## man_k() process a keyword search. The problem we have is there -## is no standard for keyword search results from man. Solaris -## systems have a different enough format to warrent dealing -## with it as a special case. For other cases, we try our best. -## Unfortunately, there are some lines of results that may be -## skipped. -## -sub man_k { - my($line,$refs,$section,$subsection,$desc,$i, - %Sec1, %Sec1sub, %Sec2, %Sec2sub, %Sec3, %Sec3sub, - %Sec4, %Sec4sub, %Sec5, %Sec5sub, %Sec6, %Sec6sub, - %Sec7, %Sec7sub, %Sec8, %Sec8sub, %Sec9, %Sec9sub, - %SecN, %SecNsub, %SecNsec); - - printhead() unless $Bare; - print $OutFH "<!-- Man keyword results converted by ", - "man2html $VERSION -->\n"; - - while ($line = <$InFH>) { - next if $line !~ /\(\d\w?\)\s+-\s/; # check if line can be handled - ($refs,$section,$subsection,$desc) = - $line =~ /^\s*(.*)\((\d)(\w?)\)\s*-\s*(.*)$/; - - if ($Solaris) { - $refs =~ s/^\s*([\+_\.\w-]+)\s+([\+_\.\w-]+)\s*$/$1/; - # <topic> <manpage> - } else { - $refs =~ s/\s(and|or)\s/,/gi; # Convert and/or to commas - $refs =~ s/^[^:\s]:\s*//; # Remove prefixed whatis path - } - $refs =~ s/\s//g; # Remove all whitespace - $refs =~ s/,/, /g; # Put space after comma - htmlize(\$desc); # Check for special chars in desc - $desc =~ s/^(.)/\U$1/; # Uppercase first letter in desc - - if ($section eq '1') { - $Sec1{$refs} = $desc; $Sec1sub{$refs} = $subsection; - } elsif ($section eq '2') { - $Sec2{$refs} = $desc; $Sec2sub{$refs} = $subsection; - } elsif ($section eq '3') { - $Sec3{$refs} = $desc; $Sec3sub{$refs} = $subsection; - } elsif ($section eq '4') { - $Sec4{$refs} = $desc; $Sec4sub{$refs} = $subsection; - } elsif ($section eq '5') { - $Sec5{$refs} = $desc; $Sec5sub{$refs} = $subsection; - } elsif ($section eq '6') { - $Sec6{$refs} = $desc; $Sec6sub{$refs} = $subsection; - } elsif ($section eq '7') { - $Sec7{$refs} = $desc; $Sec7sub{$refs} = $subsection; - } elsif ($section eq '8') { - $Sec8{$refs} = $desc; $Sec8sub{$refs} = $subsection; - } elsif ($section eq '9') { - $Sec9{$refs} = $desc; $Sec9sub{$refs} = $subsection; - } else { # Catch all - $SecN{$refs} = $desc; $SecNsec{$refs} = $section; - $SecNsub{$refs} = $subsection; - } - } - print_mank_sec(\%Sec1, 1, \%Sec1sub); - print_mank_sec(\%Sec2, 2, \%Sec2sub); - print_mank_sec(\%Sec3, 3, \%Sec3sub); - print_mank_sec(\%Sec4, 4, \%Sec4sub); - print_mank_sec(\%Sec5, 5, \%Sec5sub); - print_mank_sec(\%Sec6, 6, \%Sec6sub); - print_mank_sec(\%Sec7, 7, \%Sec7sub); - print_mank_sec(\%Sec8, 8, \%Sec8sub); - print_mank_sec(\%Sec9, 9, \%Sec9sub); - print_mank_sec(\%SecN, 'N', \%SecNsub, \%SecNsec); - - printtail() unless $Bare; -} -##--------------------------------------------------------------------------- -## print_mank_sec() prints out manpage cross-refs of a specific section. -## -sub print_mank_sec { - my($sec, $sect, $secsub, $secsec) = @_; - my(@array, @refs, $href, $item, $title, $subsection, $i, $section, - $xref); - $section = $sect; - - @array = sort keys %$sec; - if ($#array >= 0) { - print $OutFH "<H2>Section $section</H2>\n", - "<DL COMPACT>\n"; - foreach $item (@array) { - @refs = split(/,/, $item); - $section = $secsec->{$item} if $sect eq 'N'; - $subsection = $secsub->{$item}; - if ($CgiUrl) { - ($title = $refs[0]) =~ s/\(\)//g; # watch out for extra ()'s - $xref = eval $CgiUrl; - } - print $OutFH "<DT>\n"; - $i = 0; - foreach (@refs) { - if ($CgiUrl) { - print $OutFH qq|<B><A HREF="$xref">$_</A></B>|; - } else { - print $OutFH $_; - } - print $OutFH ", " if $i < $#refs; - $i++; - } - print $OutFH " ($section$subsection)\n", - "</DT><DD>\n", - $sec->{$item}, "</DD>\n"; - } - print $OutFH "</DL>\n"; - } -} - -##--------------------------------------------------------------------------- -## -sub usage { - print $OutFH <<EndOfUsage; -Usage: $PROG [ options ] < infile > outfile -Options: - -bare : Do not put in HTML, HEAD, BODY tags - -belem <elem> : HTML Element for overstriked text (def: "B") - -botm <#> : Number of lines for bottom margin (def: 7) - -cgiurl <url> : URL for linking to other manpages - -cgiurlexp <url> : Perl expression URL for linking to other manpages - -compress : Compress consective blank lines - -headmap <file> : Filename of user section head map file - -help : This message - -k : Process a keyword search result - -leftm <#> : Character width of left margin (def: 0) - -nodepage : Do not remove pagination lines - -noheads : Turn off section head detection - -pgsize <#> : Number of lines in a page (def: 66) - -seealso : Link to other manpages only in the SEE ALSO section - -solaris : Process keyword search result in Solaris format - -sun : Section heads are not overstriked in input - -title <string> : Title of manpage (def: Not defined) - -topm <#> : Number of lines for top margin (def: 7) - -uelem <elem> : HTML Element for underlined text (def: "I") - -Description: - $PROG takes formatted manpages from STDIN and converts it to HTML sent - to STDOUT. The -topm and -botm arguments are the number of lines to the - main body text and NOT to the running headers/footers. - -Version: - $VERSION - Copyright (C) 1995-1997 Earl Hood, ehood\@medusa.acs.uci.edu - $PROG comes with ABSOLUTELY NO WARRANTY and $PROG may be copied only - under the terms of the GNU General Public License, which may be found in - the $PROG distribution. - -EndOfUsage - exit 0; -}
D
two/mansearch
@@ -1,301 +0,0 @@
-#!/bin/sh -# vim:ts=4:et -# -# Interface to a glimpse search of the man pages. -# Michael Hamilton <michael@actrix.gen.nz> -# Small changes - aeb, 980109 -# -# $Id: mansearch,v 1.19 2005-10-19 20:56:30 robert Exp $ - - -type search++ > /dev/null 2> /dev/null || { - cat <<EOF -Content-type: text/html; charset=UTF-8 - -<title>Swish++ not installed</title> -<body> -<h1>Swish++ not installed</h1> -Search is only enabled if the <b>Swish++</b> package is installed. -You may <a href="https://packages.debian.org/swish++">download</a> it from -the <a href="https://www.debian.org">Debian</a> site. -</body> -EOF - exit 0 -} - - -# Do we need lynxcgi URLs? For the moment our criterion is -# 1) HTTP_USER_AGENT=Lynx* and 2) HTTP_HOST is unset. -AGENT="${HTTP_USER_AGENT-unknown}" - -case "$AGENT" in - Lynx*|lynx*) - HH="${HTTP_HOST-nohh}" - SED="s/%lynx //" - ;; - *) - HH=nolynx - SED="/%lynx/d" - ;; -esac - -SERVER="${SERVER_NAME-localhost}" -case "$HH" in - nohh) - CG="lynxcgi:/usr/lib/cgi-bin/man" - ;; - *) - CG="/cgi-bin/man" - ;; -esac -QUOTE="'" -export CG QUOTE SED - -exec gawk ' -# Generate pages index -function number_pages( searchfor, skip, maxperpage, resultcnt ) { - if ( resultcnt < maxperpage || skip < 0 ) { - return; - } - if (skip > resultcnt) { - skip = 0; - } - - max = 10; # max returned pages - searchurl= cgipath "/mansearch" urlencode(searchfor, 1); - pagescnt = int (resultcnt / maxperpage) + 1; - pageno = int (skip / maxperpage); - first = int (pageno / max) * max - 1; - last = first + max + 1; - - print "<CENTER>"; - - - i = first; - skip = i * maxperpage; - while (i <= last && i < pagescnt) { - ss = "" - if (i == pageno ) { - ss = ss "[<STRONG>" (i + 1) "</STRONG>]" - } else if (i >= 0) { - ss = ss "[<EM><A HREF=\"" searchurl; - if (skip > 0) { - ss = ss "&skip=" skip; - } - ss = ss "\">"; - if (i == first) { - ss = ss "<<"; - } else if (i == last) { - ss = ss ">>"; - } else { - ss = ss (i + 1); - } - - ss = ss "</A></EM>]"; - } - print ss; - i++; - skip += maxperpage; - } - print "</CENTER>"; -} - -function urldecode(string) { - gsub(/\+/, " ", string); - oldIGNORECASE=IGNORECASE; - IGNORECASE=1; - while(match(string, /%[0-9a-f][0-9a-f]/)) { - a=substr(string, RSTART + 1, RLENGTH - 1); - b=sprintf("%c",strtonum("0x" a)) ; - retstr = retstr substr(string, 0, RSTART - 1) b; - string = substr(string, RSTART + RLENGTH); - } - IGNORECASE=oldIGNORECASE; - return retstr string; -} - -# Encode URL; the force argument forces "query=...." format -function urlencode(string, force) { -# uses global ord table, set up in BEGIN - encoded = force; - retstr = ""; - while(match(string, /[^a-zA-Z0-9_:\/\.\-]/)) { - a=substr(string, RSTART, RLENGTH); - if (a == " ") { - b = "+"; - } else { - b = "%" sprintf("%02X", ord[a]); - } - retstr = retstr substr(string, 0, RSTART - 1) b; - string = substr(string, RSTART + RLENGTH); - encoded = 1; - } - - if (encoded) { - return "?query=" retstr string; - } else { - return retstr string; - } -} - -BEGIN { - # fill ord table, used by urlencode - for (i = 0; i < 255; i++) - ord[sprintf("%c", i)] = i - - - searchdocument = "/usr/share/man2html/mansearch.aux"; - quote = ENVIRON["QUOTE"]; - cgipath = ENVIRON["CG"]; - sedcmd = ENVIRON["SED"]; - maxperpage = 50; # Single page display match limit. - - glimpse_cmd = "search++ --config-file=/usr/share/man2html/swish++.conf " - - - qry_str = ENVIRON["QUERY_STRING"]; - if (match(qry_str, /skip=[0-9]+/)) { - skip = int(substr(qry_str, RSTART + 5, RLENGTH - 5) / maxperpage) * maxperpage; - } else { - skip = 0 - } - - if (match(qry_str, /query=[^&]+/)) { - qry_str = substr(qry_str, RSTART + 6, RLENGTH - 6); - string = urldecode(qry_str); - } - if (!string) { - for (i = 1; i < ARGC; i++) { - string = string " " ARGV[i]; - } - } - - # Have to be careful to single quote this - # string later. - gsub(/[^a-zA-Z0-9\-_+ \t\/@%:;,$*|=]/, " ", string); - - # string = removeopts(string); - - # gsub(/[^a-zA-Z0-9-_+ \t\/@%:,]/, " ", options); - - - if (!string) { - if (system("test -r " searchdocument ) != 0) { - print "<HTML><HEAD>"; - print "<TITLE>mansearch - file not found</TITLE>"; - print "</HEAD>\n<BODY>"; - print "Sorry - cannot read " searchdocument "."; - print "</BODY></HTML>"; - exit; - } - system("sed " quote "s#%cg#" cgipath "#g;" sedcmd quote " " searchdocument ); - exit; - } - - print "Content-type: text/html; charset=UTF-8\n"; - print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"; - print "<HTML>"; - print "<HEAD>"; - print "<TITLE>Manual Pages - Search Results: " string "</TITLE>"; - print "</HEAD>"; - print "<BODY>"; - - print "<H1>Manual Pages - Search Results</H1>"; - print "<H2>Target text: " string "</H2>"; - - print "<A HREF=\"" cgipath "/mansearch\">"; - print "Perform another search"; - print "</A><BR>"; - print "<A HREF=\"" cgipath "/man2html\">"; - print "Return to Main Contents"; - print "</A>"; - - print "<HR>"; - - if ( skip > 0) { - options = options "--skip-results=" skip; - } - if ( maxperpage > 0 ) { - options = options "-m " maxperpage; - } - - # Unless you like being hacked, the single - # forward quotes are most important. - cmd = glimpse_cmd " " options " " quote string quote " 2>/dev/null" ; - while ((cmd | getline matchline) > 0) { - if (split(matchline, part, "__--__") <= 3) { - if ( match( matchline, "^# results: .*$" ) ) { - resultcnt = substr( matchline, RSTART + 11, RLENGTH - 11 ) + 0; - number_pages( string, skip, maxperpage, resultcnt ); - - } - continue; - } - else { - fullname = part[2]; - } - - if (fullname == last_fullname) { - continue; - } - - last_fullname = fullname ; - last_text = ""; - - if (match(fullname, ".*/")) { - dirname = substr(fullname, 1, RLENGTH); - filename = substr(fullname, RLENGTH + 1); - } else { - filename = fullname; - } - - if (match(filename, /\.[^.]+$/)) { - ref = substr(filename, 1, RSTART - 1) "+" substr(filename, RSTART + 1); - } else { - ref = filename; - } - textname = filename; - sub(/\.(gz|Z|z)$/, "", textname); - - # replace last "." with "(". gsub is used to count number of "." - textname = gensub(/\./, "(", gsub(/\./, ".", textname), textname); - textname = textname ")"; - if (mcount == 0) { - print "<DL>"; - } - mcount++; - print "<DT><A HREF=\"" cgipath "/man2html" urlencode(fullname, 0) "\">" textname "</A>" \ - " <EM>(" part[1] "%)</EM></DT>"; - - text = part[4]; - if ( text == filename ) { - text = textname; - } else { - sub(/^ *.[^ ]+[- ]+/, "", text); - sub(/ +$/, "", text); - gsub(/\\f./, "", text); - gsub(/\\&/, "", text); - gsub(/\\/, "", text); - } - print "<DD>" text "</DD>"; - print "<DT><BR></DT>"; - } - close(cmd); - - print "</DL>"; - - number_pages( string, skip, maxperpage, resultcnt ); - if (resultcnt == 0) { - print "No matches found."; - } - else if (resultcnt == 1) { - print "<HR>\n<P>1 match found." - } - else { - print "<HR>\n<P>" resultcnt " matches found." - } - print "</BODY>"; - print "</HTML>"; - exit; -}' "$@" -