/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Makedoc's man output routines. * * By Shawn Hargreaves. * * See readme.txt for copyright information. * * See allegro/docs/src/makedoc/format.txt for a brief description of * the source of _tx files. */ #include #include #include #include #include "makeman.h" #include "makedoc.h" #include "makemisc.h" char manheader[256] = ""; char mansynopsis[256] = ""; char *man_shortdesc_force1; char *man_shortdesc_force2; static int _mpreformat = 0; static int _mpreindent = 0; static void _write_man_xref(FILE *f, char *xref, char *ext, int notfirst); static char *_man_name(char *p); static void _mfputs(char *p, FILE *f); static void _write_short_desc(FILE *f, LINE *line); /* write_man: * Entry point of man page generation function. */ int write_man(char *filename) { char buf[256], buf2[256]; char *xref[256]; int xrefs = 0; LINE *line = head; LINE *l2; FILE *f = NULL; FILE *f2; char *p; int i; /* Free strings if not both of them where specified. */ if (!(man_shortdesc_force1 && man_shortdesc_force2)) { if (man_shortdesc_force1) free(man_shortdesc_force1); if (man_shortdesc_force2) free(man_shortdesc_force2); man_shortdesc_force1 = man_shortdesc_force2 = 0; } while (line) { if (line->flags & (HEADING_FLAG | DEFINITION_FLAG | NODE_FLAG)) { /* close off any previous manpage */ if (f) { if (xrefs > 0) { fprintf(f, ".SH SEE ALSO\n"); for (i=0; iflags & MAN_FLAG) { if (line->flags & RETURN_VALUE_FLAG) { fprintf(f, ".SH \"RETURN VALUE\"\n"); } else if (line->flags & DEFINITION_FLAG) { /* start a manpage */ p = _man_name(line->text); if (p) { strcpy(buf, filename); strcpy(get_filename(buf), p); strcat(buf, "."); strcat(buf, get_extension(filename)); /*printf("writing %s\n", buf);*/ f = fopen(buf, "w"); if (!f) return 1; fprintf(f, ".\\\" Generated by the Allegro makedoc utility\n"); fprintf(f, ".TH %s %s %s\n", p, get_extension(filename), manheader); fprintf(f, ".SH NAME\n"); fprintf(f, "%s", p); if (!(line->flags & CONTINUE_FLAG)) { l2 = line->next; while ((l2) && (l2->flags & DEFINITION_FLAG)) { p = _man_name(l2->text); if (p) fprintf(f, ", %s", p); l2 = l2->next; } } _write_short_desc(f, line); fprintf(f, "\n.SH SYNOPSIS\n"); if (mansynopsis[0]) fprintf(f, ".B %s\n\n", mansynopsis); /* go ahead and find all the header lines */ l2 = line; while (l2 && l2->flags & CONTINUE_FLAG) l2=l2->next; if (l2) { l2 = l2->next; while (l2 && (l2->flags & HEADER_FLAG)) { fprintf(f, ".B %s\n", l2->text); l2 = l2->next; if (l2 && (l2->flags & HEADER_FLAG)) { fprintf(f, ".br\n"); } } } fprintf(f, ".sp\n"); fputs(".B ", f); _mfputs(line->text, f); i = (line->flags & CONTINUE_FLAG); while ((line->next) && (line->next->flags & DEFINITION_FLAG)) { line = line->next; if (!i) { /* multiple entries require a crosslink file */ p = _man_name(line->text); if (p) { strcpy(buf2, filename); strcpy(get_filename(buf2), p); strcat(buf2, "."); strcat(buf2, get_extension(filename)); /*printf("writing %s\n", buf2);*/ f2 = fopen(buf2, "w"); if (!f2) return 1; fprintf(f2, ".so man%s/%s\n", get_extension(filename), get_filename(buf)); fclose(f2); } fputc('\n', f); } fputs(".B ", f); _mfputs(line->text, f); } fprintf(f, ".SH DESCRIPTION\n"); _mpreformat = 0; } xrefs = 0; } else { /* normal output mode */ if (f) _mfputs(line->text, f); } } else if (line->flags & XREF_FLAG) { xref[xrefs++] = line->text; } line = line->next; } return 0; } /* _write_man_xref: */ static void _write_man_xref(FILE *f, char *xref, char *ext, int notfirst) { char *tok, *p; tok = strtok(xref, ",;"); while (tok) { while ((*tok) && (myisspace(*tok))) tok++; p = tok; while (*p) { if ((!myisalnum(*p)) && (*p != '_')) break; p++; } if (!*p) { if (notfirst) fprintf(f, ",\n"); fprintf(f, ".BR %s (%s)", tok, ext); notfirst = 1; } tok = strtok(NULL, ",;"); } } /* _man_name: */ static char *_man_name(char *p) { static char buf[256]; int i = 0; while ((*p) && (*p != '"')) p++; if (*p == '"') { p++; while ((*p) && (*p != '"')) { if ((!myisalnum(*p)) && (*p != '_')) return NULL; buf[i++] = *(p++); } if (i) { buf[i] = 0; return buf; } } return NULL; } /* _mfputs: */ static void _mfputs(char *p, FILE *f) { int state = 0; int i; if (_mpreformat) { if (_mpreindent < 0) { _mpreindent = 0; while ((*p) && (myisspace(*p))) { _mpreindent++; p++; } } else { for (i=0; i<_mpreindent; i++) { if ((!*p) || (!myisspace(*p))) break; p++; } } fputs(" ", f); } else { while ((*p) && (myisspace(*p))) p++; } while (*p) { /* less-than HTML tokens */ if ((p[0] == '&') && (mytolower(p[1]) == 'l') && (mytolower(p[2]) == 't')) { fputc('<', f); p += 3; state = 1; } /* greater-than HTML tokens */ else if ((p[0] == '&') && (mytolower(p[1]) == 'g') && (mytolower(p[2]) == 't')) { fputc('>', f); p += 3; state = 1; } /* bold HTML tokens */ else if ((p[0] == '<') && (mytolower(p[1]) == 'b') && (p[2] == '>')) { if (state) putc('\n', f); fputs(".B ", f); p += 3; } /* end bold HTML tokens */ else if ((p[0] == '<') && (mytolower(p[1]) == '/') && (mytolower(p[2]) == 'b') && (p[3] == '>')) { if (state) fputc('\n', f); state = -1; p += 4; } /* line break HTML tokens */ else if ((p[0] == '<') && (mytolower(p[1]) == 'b') && (mytolower(p[2]) == 'r') && (p[3] == '>')) { if (state >= 0) { fputc('\n', f); state = 0; } p += 4; } /* enter preformatted mode */ else if ((p[0] == '<') && (mytolower(p[1]) == 'p') && (mytolower(p[2]) == 'r') && (mytolower(p[3]) == 'e') && (p[4] == '>')) { fputs("\n.nf\n", f); state = -1; _mpreformat = 1; _mpreindent = -1; p += 5; } /* leave preformatted mode */ else if ((p[0] == '<') && (mytolower(p[1]) == '/') && (mytolower(p[2]) == 'p') && (mytolower(p[3]) == 'r') && (mytolower(p[4]) == 'e') && (p[5] == '>')) { fputs("\n.fi\n", f); state = -1; _mpreformat = 0; p += 6; } /* strip other HTML tokens */ else if (p[0] == '<') { while ((*p) && (*p != '>')) p++; if (*p) p++; } /* output other characters */ else { if (*p == '\\') fputc('\\', f); fputc(*p, f); p++; state = 1; } } if (state >= 0) fputc('\n', f); } /* _write_short_desc: * Advances the line pointer until the next man page definition * looking for a short description, which would be printed to * the currently open file. */ static void _write_short_desc(FILE *f, LINE *line) { assert(f); assert(line); assert(line->flags & (MAN_FLAG | DEFINITION_FLAG)); /* Jump current definition. */ while (line && line->flags & DEFINITION_FLAG) line = line->next; while (1) { if (!line) goto empty_title; if (line->flags & (MAN_FLAG | DEFINITION_FLAG)) goto empty_title; if (line->flags & (HEADING_FLAG | DEFINITION_FLAG | NODE_FLAG)) goto empty_title; if (line->flags & SHORT_DESC_FLAG) { /* Do we need to add the forced text to the title? */ if (man_shortdesc_force1 && !mystristr(line->text, man_shortdesc_force1)) fprintf(f, " \\- %s %s\\&", line->text, man_shortdesc_force2); else fprintf(f, " \\- %s\\&", line->text); return ; } line = line->next; } empty_title: /* If we reach here, we didn't find a short description. Force one? */ if (man_shortdesc_force1) fprintf(f, " \\- %s\\&", man_shortdesc_force2); }