");
+ out_html("
|
");
+ 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': 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;
+ 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 == '"') {
+ *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, "\n");
+ mip += 6;
+ } else {
+ strcpy(manidx+mip, "\n");
+ mip += 5;
+ }
+ }
+ subs = level;
+
+ scan_troff(item, 1, &c);
+ manidx_need(100 + strlen(c));
+ sprintf(manidx+mip, "- %s
- \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[20];
+ int words;
+ char *sl;
+ STRDEF *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]);
+ 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 *h;
+ de=(STRDEF*) xmalloc(sizeof(STRDEF));
+ de->nr=i;
+ de->slen=0;
+ de->next=strdef;
+ de->st=NULL;
+ strdef=de;
+ h=NULL;
+ c=scan_troff(c, 1, &h);
+ de->st=h;
+ de->slen=curpos;
+ } else {
+ if (mode) { /* .ds */
+ char *h=NULL;
+ c=scan_troff(c, 1, &h);
+ free(de->st); /* segfault XXX */
+ de->slen=curpos;
+ de->st=h;
+ } 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("
- ");
+ else out_html("
\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("\n");
+ while (i && *c) {
+ char *line=NULL;
+ c=scan_troff(c,1, &line);
+ if (line && strncmp(line, "
", 4)) {
+ out_html(line);
+ out_html("
\n");
+ i--;
+ }
+ }
+ out_html(" \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("
\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("\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(""); else {
+ out_html(NEWLINE);
+ NEWLINE[0]='\n';
+ }
+ curpos=0;
+ c=skip_till_newline(c);
+ break;
+ case V('s','o'):
+ {
+ FILE *f;
+ 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] = '/';
+ }
+ 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;
+ l = 0;
+#ifdef _KOLIBRI
+ ksys_bdfe_t bdfe;
+ _ksys_file_get_info(h, &bdfe);
+ l = bdfe.size;
+#else
+ struct stat stbuf;
+ if (stat(h, &stbuf)!=-1) l=stbuf.st_size;
+#endif
+
+ buf = (char*) xmalloc((l+4)*sizeof(char));
+#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("
Manpage of %s \n"
+ "\n"
+ "See the manpage for %s.\n"
+ "\n",
+ s, h, h);
+ } else
+#endif
+ {
+ /* this works alright, except for section 3 */
+ if (!l || !(f = fopen(h,"r"))) {
+ fprintf(stderr,
+ "man2html: unable to open or read file %s\n", h);
+ out_html(""
+ "man2html: unable to open or read file\n");
+ out_html(h);
+ out_html("
\n");
+ } else {
+ i=fread(buf+1,1,l,f);
+ fclose(f);
+ 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("
\n");
+ c=c+j;
+ c=scan_expression(c, &j);
+ for (i=0; ia b ] */
+ 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++;
+ 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");
+ 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("");
+ }
+ 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' and '<' solves it, but creates
+ ** some space. A normal space does not work.
+ */
+ out_html("\">");
+ break;
+ case V('L','P'):
+ case V('P','P'):
+ dl_end();
+ if (fillout) out_html("\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("
");
+ }
+ trans_char(c,'"', '\a');
+ add_to_index(mode, c);
+ out_html(" \n\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("
\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("
"); + 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(""); + 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("
\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("\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("\n");
+ }
+ }
+ if (mandoc_bd_options & BD_INDENT)
+ out_html("\n");
+ curpos=0;
+ fillout=1;
+ c=skip_till_newline(c);
+ break;
+ case V('B','e'): /* BSD mandoc */
+ c=c+j;
+ if (fillout) out_html(""); 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("
\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;
+ 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("
");
+ } else {
+ char *end, t=0 /* just for gcc */;
+ end = strchr(c, '\n');
+ if (end) {
+ t = *end;
+ *end = 0;
+ }
+ if (mandoc_name)
+ free(mandoc_name);
+ mandoc_name = xstrdup(c);
+ if (end)
+ *end = t;
+ }
+ count++;
+ }
+ out_html(change_to_font('B'));
+ while (*c == ' ' || *c == '\t') c++;
+ if (*c == '\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);
+ } 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('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:
+ /* search macro database of self-defined macros */
+ owndef = defdef;
+ while (owndef && owndef->nr!=i) owndef=owndef->next;
+ if (owndef) {
+ char **oldargument;
+ int deflen;
+ int onff;
+ sl=fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n');
+ c=sl+1;
+ *sl=0;
+ for (i=1; i
");
+ 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;
+
+#define BUFSMSG 1024
+#define MSGLEN 2048
+static void
+error_page(char *s, char *t, ...) {
+ va_list p;
+ char msg[MSGLEN];
+ char buf[BUFSMSG];
+
+ sprintf(msg, "'%s\n", s, s);
+ va_start(p, t);
+ vsprintf(buf, t, p);
+ va_end(p);
+#ifdef _KOLIBRI
+ sprintf(msg, "%s%s%s", msg, buf, "' -E");
+ _ksys_exec("/sys/@notify", buf);
+#else
+ sprintf(msg, "%s%s%s", msg, buf, "'");
+ printf("%s", msg);
+#endif
+ exit(0);
+}
+
+char *
+xstrdup(const char *s) {
+ char *p = strdup(s);
+ if (p == NULL)
+ error_page("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("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("Out of memory",
+ "Sorry, out of memory, aborting...\n");
+ return p;
+}
+
+static void
+usage(void) {
+ error_page("man2html: bad invocation",
+ "Usage: man2html in_file [out_file.html]\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;
+#ifdef _KOLIBRI
+ setcwd(s);
+#else
+ chdir(s);
+#endif
+ 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) {
+ FILE *f;
+ int l, c;
+ char *buf, *filename, *fnam = NULL;
+ char *outfilename;
+
+#ifdef _KOLIBRI
+ outfilename = "/tmp0/1/out.html";
+#else
+ outfilename = "./out.html";
+#endif
+
+// printf("Content-type: text/html\n\n");
+
+
+ /* Find filename */
+ if (argc > 2) {
+ outfilename = argv[2];
+ } if (argc > 1) {
+ fnam = argv[1];
+ } else {
+ usage();
+ }
+
+ if ((out = fopen(outfilename, "w")) == NULL) {
+ printf("Cannot open file %s", outfilename);
+ return 0;
+ }
+
+ filename = fnam;
+ directory = 0;
+
+ /* Open input file */
+ goto_dir(fnam, &directory, &fnam);
+
+ f = fopen(fnam, "r");
+ if (f == NULL)
+ error_page("File not found", "Could not open %s\n", filename);
+ fname = fnam;
+
+ /* 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 */
+ int ct;
+
+ l = 0;
+
+#ifdef _KOLIBRI
+ ksys_bdfe_t bdfe;
+ _ksys_file_get_info(filename, &bdfe);
+ l = bdfe.size;
+#else
+ struct stat stbuf;
+ if (stat(filename, &stbuf) != -1) l=stbuf.st_size;
+#endif
+
+ buf = (char *) xmalloc((l+1+XTRA)*sizeof(char));
+ ct = fread(buf+1,1,l,f);
+ if (ct < l)
+ l = ct;
+ fclose(f);
+
+ 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("");
+ }
+ out_html(NEWLINE);
+ if (output_possible) {
+ /* for mosaic users */
+ fprintf(out, "
\n Index
\n\n");
+ manidx[mip]=0;
+ fprintf(out, "%s", manidx);
+ if (subs) printf("
\n");
+ fprintf(out, "\n");
+ print_sig();
+ fprintf(out, "\n\n");
+ } else {
+ if (!filename)
+ filename = fname;
+ if (*filename == '/')
+ error_page("Invalid Manpage",
+ "The requested file %s is not a valid (unformatted) "
+ "man page.\nIf the file is a formatted manpage, "
+ "you could try to load the\n"
+ "plain file.\n",
+ filename, filename);
+ else
+ error_page("Invalid Manpage",
+ "The requested file %s is not a valid (unformatted) "
+ "man page.", filename);
+ }
+ if (idxfile)
+ fclose(idxfile);
+ if (buf)
+ free(buf);
+ return 0;
+}
diff --git a/programs/other/man2html/strdefs.c b/programs/other/man2html/strdefs.c
new file mode 100644
index 000000000..bcbc366b1
--- /dev/null
+++ b/programs/other/man2html/strdefs.c
@@ -0,0 +1,176 @@
+#include "defs.h"
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+int nroff = 1;
+
+#define NROFF (-666)
+#define TROFF (-667)
+
+STRDEF *chardef, *strdef, *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('R',' '), 1, "®", NULL },
+ { V('l','q'), 2, "``", NULL },
+ { V('r','q'), 2, "''", NULL },
+ { 0, 0, NULL, NULL}
+};
+
+
+static STRDEF standardchar[] = {
+ { V('*','*'), 1, "*", NULL }, /* math star */
+ { V('*','A'), 1, "A", NULL },
+ { V('*','B'), 1, "B", NULL },
+ { V('*','C'), 2, "Xi", NULL },
+ { V('*','D'), 5, "Delta", NULL },
+ { V('*','E'), 1, "E", NULL },
+ { V('*','F'), 3, "Phi", NULL },
+ { V('*','G'), 5, "Gamma", NULL },
+ { V('*','H'), 5, "Theta", NULL },
+ { V('*','I'), 1, "I", NULL },
+ { V('*','K'), 1, "K", NULL },
+ { V('*','L'), 6, "Lambda", NULL },
+ { V('*','M'), 1, "M", NULL },
+ { V('*','N'), 1, "N", NULL },
+ { V('*','O'), 1, "O", NULL },
+ { V('*','P'), 2, "Pi", NULL },
+ { V('*','Q'), 3, "Psi", NULL },
+ { V('*','R'), 1, "P", NULL },
+ { V('*','S'), 5, "Sigma", NULL },
+ { V('*','T'), 1, "T", NULL },
+ { V('*','U'), 1, "Y", NULL },
+ { V('*','W'), 5, "Omega", NULL },
+ { V('*','X'), 1, "X", NULL },
+ { V('*','Y'), 1, "H", NULL },
+ { V('*','Z'), 1, "Z", NULL },
+ { V('*','a'), 5, "alpha", NULL },
+ { V('*','b'), 4, "beta", NULL },
+ { V('*','c'), 2, "xi", NULL },
+ { V('*','d'), 5, "delta", NULL },
+ { V('*','e'), 7, "epsilon", NULL },
+ { V('*','f'), 3, "phi", NULL },
+ { V('*','g'), 5, "gamma", NULL },
+ { V('*','h'), 5, "theta", NULL },
+ { V('*','i'), 4, "iota", NULL },
+ { V('*','k'), 5, "kappa", NULL },
+ { V('*','l'), 6, "lambda", NULL },
+ { V('*','m'), 1, "µ", NULL },
+ { V('*','n'), 2, "nu", NULL },
+ { V('*','o'), 1, "o", NULL },
+ { V('*','p'), 2, "pi", NULL },
+ { V('*','q'), 3, "psi", NULL },
+ { V('*','r'), 3, "rho", NULL },
+ { V('*','s'), 5, "sigma", NULL },
+ { V('*','t'), 3, "tau", NULL },
+ { V('*','u'), 7, "upsilon", NULL },
+ { V('*','w'), 5, "omega", NULL },
+ { V('*','x'), 3, "chi", NULL },
+ { V('*','y'), 3, "eta", NULL },
+ { V('*','z'), 4, "zeta", NULL },
+ { V('+','-'), 1, "±", NULL },
+ { V('1','2'), 1, "½", NULL },
+ { V('1','4'), 1, "¼", NULL },
+ { V('3','4'), 1, "¾", NULL },
+ { V('F','i'), 3, "ffi", NULL },
+ { V('F','l'), 3, "ffl", NULL },
+ { V('a','a'), 1, "´", NULL },
+ { V('a','p'), 1, "~", NULL },
+ { V('b','r'), 1, "|", NULL },
+ { V('b','u'), 1, "*", NULL }, /* bullet */
+ { V('b','v'), 1, "|", NULL },
+ { V('c','i'), 1, "o", NULL }, /* circle */
+ { V('c','o'), 1, "©", NULL },
+ { V('c','t'), 1, "¢", NULL },
+ { V('d','e'), 1, "°", NULL },
+ { V('d','g'), 1, "+", NULL }, /* dagger */
+ { V('d','i'), 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('f','f'), 2, "ff", NULL },
+ { V('f','i'), 2, "fi", NULL },
+ { V('f','l'), 2, "fl", NULL },
+ { V('f','m'), 1, "´", NULL },
+ { V('g','a'), 1, "`", NULL },
+ { V('h','y'), 1, "-", NULL },
+ { V('l','c'), 2, "|¯", NULL },
+ { V('i','f'), 8, "Infinity", NULL }, /* infinity sign */
+ { V('i','s'), 8, "Integral", NULL }, /* integral sign */
+ { V('l','f'), 2, "|_", NULL },
+ { V('l','k'), 1, "{", NULL },
+ { V('m','i'), 1, "-", NULL },
+ { V('m','u'), 1, "×", NULL },
+ { V('n','o'), 1, "¬", NULL },
+ { V('o','r'), 1, "|", NULL },
+ { V('p','d'), 1, "d", NULL }, /* partial derivative */
+ { V('p','l'), 1, "+", NULL },
+ { V('r','c'), 2, "¯|", NULL },
+ { V('r','f'), 2, "_|", NULL },
+ { V('r','g'), 1, "®", NULL },
+ { V('r','k'), 1, "}", NULL },
+ { V('r','n'), 1, "¯", NULL },
+ { V('r','u'), 1, "_", NULL },
+ { V('s','c'), 1, "§", NULL },
+ { V('s','l'), 1, "/", NULL },
+ { V('s','q'), 2, "[]", NULL },
+ { V('t','s'), 1, "s", NULL }, /* should be terminal sigma */
+ { V('u','l'), 1, "_", NULL },
+ { V('>','='), 1, ">", NULL },
+ { V('<','='), 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;
+}