Show makedoc.c syntax highlighted
/*
* This is a little hack I wrote to simplify producing the documentation
* in various formats (ASCII, HTML, TexInfo, and RTF). It converts from
* a weird layout that is basically a kind of stripped down HTML with a
* few extra markers (the _tx files), and automates a few things like
* constructing indexes and splitting HTML files into multiple parts.
* It's not pretty, elegant, or well written, and is liable to get upset
* if it doesn't like the input data. If you change the _tx files, run
* 'make docs' to rebuild everything.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <limits.h>
#include <stdarg.h>
#define TEXT_FLAG 0x00000001
#define HTML_FLAG 0x00000002
#define HTML_CMD_FLAG 0x00000004
#define TEXINFO_FLAG 0x00000008
#define TEXINFO_CMD_FLAG 0x00000010
#define RTF_FLAG 0x00000020
#define MAN_FLAG 0x00000040
#define HEADING_FLAG 0x00000080
#define DEFINITION_FLAG 0x00000100
#define CONTINUE_FLAG 0x00000200
#define TOC_FLAG 0x00000400
#define INDEX_FLAG 0x00000800
#define NO_EOL_FLAG 0x00001000
#define MULTIFILE_FLAG 0x00002000
#define NOCONTENT_FLAG 0x00004000
#define NO_INDENT_FLAG 0x00008000
#define NODE_FLAG 0x00010000
#define NONODE_FLAG 0x00020000
#define STARTOUTPUT_FLAG 0x00040000
#define ENDOUTPUT_FLAG 0x00080000
#define TALLBULLET_FLAG 0x00100000
#define SHORT_TOC_FLAG 0x00200000
#define XREF_FLAG 0x00400000
#define HEADER_FLAG 0x00800000
#define START_TITLE_FLAG 0x01000000
#define AL_END_TITLE_FLAG 0x02000000
#define TOC_SIZE 8192
typedef struct LINE
{
char *text;
struct LINE *next;
int flags;
} LINE;
LINE *head = NULL;
LINE *tail = NULL;
typedef struct TOC
{
char *text;
char *alt;
struct TOC *next;
int root;
int texinfoable;
int htmlable;
int otherfile;
} TOC;
TOC *tochead = NULL;
TOC *toctail = NULL;
int flags = TEXT_FLAG | HTML_FLAG | TEXINFO_FLAG | RTF_FLAG | MAN_FLAG;
int nostrip = 0;
int strip_indent = -1;
int last_toc_line = INT_MIN;
int last_toc_line2 = INT_MIN;
int multiwordheaders = 0;
int warn_on_long_lines = 0;
char locale[256] = "";
int dos_codepage = 1;
char fileheader[256] = "";
char filefooter[256] = "";
char rtfheader[256] = "";
char manheader[256] = "";
char mansynopsis[256] = "";
char *html_extension = "html";
char *texinfo_extension = "txi";
int mpreformat = 0;
int mpreindent = 0;
int mytolower(int c)
{
if ((c >= 'A') && (c <= 'Z'))
c -= ('A' - 'a');
return c;
}
int myisspace(int c)
{
return ((c == ' ') || (c == '\t') || (c == '\r') ||
(c == '\n') || (c == '\f') || (c == '\v'));
}
int myisalnum(int c)
{
return (((c >= '0') && (c <= '9')) ||
((c >= 'A') && (c <= 'Z')) ||
((c >= 'a') && (c <= 'z')) ||
(c >= 0x80) || (c < 0));
}
char *mystrlwr(char *string)
{
char *p;
for (p=string; *p; p++)
*p = mytolower(*p);
return string;
}
int mystricmp(const char *s1, const char *s2)
{
int c1, c2;
do {
c1 = mytolower(*(s1++));
c2 = mytolower(*(s2++));
} while ((c1) && (c1 == c2));
return c1 - c2;
}
void set_locale(char *l)
{
strcpy(locale, l);
if (mystricmp(l, "china") == 0)
dos_codepage = 0;
else if (mystricmp(l, "korea") == 0)
dos_codepage = 0;
}
char *extension(char *filename)
{
int pos, end;
for (end=0; filename[end]; end++)
; /* do nothing */
pos = end;
while ((pos>0) && (filename[pos-1] != '.') &&
(filename[pos-1] != '\\') && (filename[pos-1] != '/'))
pos--;
if (filename[pos-1] == '.')
return filename+pos;
return filename+end;
}
char *get_filename(char *path)
{
int pos;
for (pos=0; path[pos]; pos++)
; /* do nothing */
while ((pos>0) && (path[pos-1] != '\\') && (path[pos-1] != '/'))
pos--;
return path+pos;
}
int is_empty(char *s)
{
while (*s) {
if (*s != ' ')
return 0;
s++;
}
return 1;
}
void free_data(void)
{
LINE *al_draw_line = head;
LINE *prev;
TOC *tocline = tochead;
TOC *tocprev;
while (al_draw_line) {
prev = al_draw_line;
al_draw_line = al_draw_line->next;
free(prev->text);
free(prev);
}
while (tocline) {
tocprev = tocline;
tocline = tocline->next;
free(tocprev->text);
if (tocprev->alt)
free(tocprev->alt);
free(tocprev);
}
}
void add_line(char *buf, int flags)
{
int len;
LINE *al_draw_line;
len = strlen(buf);
al_draw_line = malloc(sizeof(LINE));
al_draw_line->text = malloc(len+1);
strcpy(al_draw_line->text, buf);
al_draw_line->next = NULL;
al_draw_line->flags = flags;
if (tail)
tail->next = al_draw_line;
else
head = al_draw_line;
tail = al_draw_line;
}
void add_toc_line(char *buf, char *alt, int root, int num, int texinfoable, int htmlable, int otherfile)
{
TOC *toc;
toc = malloc(sizeof(TOC));
toc->text = malloc(strlen(buf)+1);
strcpy(toc->text, buf);
if (alt) {
toc->alt = malloc(strlen(alt)+1);
strcpy(toc->alt , alt);
}
else
toc->alt = NULL;
toc->next = NULL;
toc->root = root;
toc->texinfoable = ((texinfoable) && (num > last_toc_line+1));
toc->htmlable = htmlable;
toc->otherfile = otherfile;
last_toc_line = num;
if (toctail)
toctail->next = toc;
else
tochead = toc;
toctail = toc;
}
void add_toc(char *buf, int root, int num, int texinfoable, int htmlable)
{
char b[256], b2[256];
int c, d;
int done;
int got;
if (root) {
add_toc_line(buf, NULL, 1, num, texinfoable, htmlable, 0);
strcpy(b, buf);
sprintf(buf, "<a name=\"%s\">%s</a>", b, b);
}
else {
got = 0;
do {
done = 1;
for (c=0; buf[c]; c++) {
if (buf[c] == '@') {
for (d=0; myisalnum(buf[c+d+1]) || (buf[c+d+1] == '_') || (buf[c+d+1] == '/') || (buf[c+d+1] == '*'); d++)
b[d] = buf[c+d+1];
b[d] = 0;
add_toc_line(b, NULL, 0, num, texinfoable, htmlable, 0);
strcpy(b2, buf+c+d+1);
sprintf(buf+c, "<a name=\"%s\">%s</a>%s", b, b, b2);
done = 0;
got = 1;
break;
}
}
} while (!done);
if ((!got) && (num > last_toc_line2+1)) {
strcpy(b, buf);
c = d = 0;
while ((b[c]) && (myisspace(b[c])))
c++;
while (b[c]) {
if (myisalnum(b[c]))
b2[d] = b[c];
else
b2[d] = '_';
c++;
d++;
}
b2[d] = 0;
add_toc_line(b2, b, 0, num, texinfoable, htmlable, 0);
sprintf(buf, "<a name=\"%s\">%s</a>", b2, b);
}
}
last_toc_line2 = num;
}
char *my_fgets(char *p, int max, FILE *f)
{
int c, ch;
if (feof(f)) {
p[0] = 0;
return NULL;
}
for (c=0; c<max-1; c++) {
ch = getc(f);
if (ch == EOF)
break;
p[c] = ch;
if (p[c] == '\r')
c--;
else if (p[c] == '\n')
break;
else if (p[c] == '\t') {
p[c] = ' ';
while ((c+1) & 7) {
c++;
p[c] = ' ';
}
}
}
p[c] = 0;
return p;
}
int strincmp(char *s1, char *s2)
{
while (*s2) {
if (mytolower(*s1) != mytolower(*s2))
return 1;
s1++;
s2++;
}
return 0;
}
int read_file(char *filename, char *htmlname)
{
char buf[1024];
char *p;
FILE *f;
int al_draw_line = 0;
printf("reading %s\n", filename);
f = fopen(filename, "r");
if (!f)
return 1;
while (my_fgets(buf, 1023, f)) {
al_draw_line++;
/* strip EOL */
p = buf+strlen(buf)-1;
while ((p >= buf) && ((*p == '\r') || (*p == '\n'))) {
*p = 0;
p--;
}
if (buf[0] == '@') {
/* a marker al_draw_line */
if (mystricmp(buf+1, "text") == 0)
flags |= TEXT_FLAG;
else if (mystricmp(buf+1, "!text") == 0)
flags &= ~TEXT_FLAG;
else if (mystricmp(buf+1, "html") == 0)
flags |= HTML_FLAG;
else if (mystricmp(buf+1, "!html") == 0)
flags &= ~HTML_FLAG;
else if (mystricmp(buf+1, "texinfo") == 0)
flags |= TEXINFO_FLAG;
else if (mystricmp(buf+1, "!texinfo") == 0)
flags &= ~TEXINFO_FLAG;
else if (mystricmp(buf+1, "rtf") == 0)
flags |= RTF_FLAG;
else if (mystricmp(buf+1, "!rtf") == 0)
flags &= ~RTF_FLAG;
else if (mystricmp(buf+1, "man") == 0)
flags |= MAN_FLAG;
else if (mystricmp(buf+1, "!man") == 0)
flags &= ~MAN_FLAG;
else if (mystricmp(buf+1, "indent") == 0)
flags &= ~NO_INDENT_FLAG;
else if (mystricmp(buf+1, "!indent") == 0)
flags |= NO_INDENT_FLAG;
else if (mystricmp(buf+1, "multiplefiles") == 0)
flags |= MULTIFILE_FLAG;
else if (mystricmp(buf+1, "headingnocontent") == 0)
flags |= (HEADING_FLAG | NOCONTENT_FLAG);
else if (mystricmp(buf+1, "heading") == 0)
flags |= HEADING_FLAG;
else if (strincmp(buf+1, "titlepage") == 0)
add_line("", START_TITLE_FLAG);
else if (strincmp(buf+1, "!titlepage") == 0)
add_line("", AL_END_TITLE_FLAG);
else if (mystricmp(buf+1, "contents") == 0)
add_line("", TOC_FLAG);
else if (mystricmp(buf+1, "shortcontents") == 0)
add_line("", TOC_FLAG | SHORT_TOC_FLAG);
else if (mystricmp(buf+1, "index") == 0)
add_line("", INDEX_FLAG);
else if (strincmp(buf+1, "node ") == 0) {
add_toc_line(buf+6, NULL, 0, al_draw_line, 1, 0, 0);
add_line(buf+6, NODE_FLAG);
}
else if (strincmp(buf+1, "hnode ") == 0) {
add_toc_line(buf+7, NULL, 0, al_draw_line, 1, 0, 0);
add_line(buf+7, NODE_FLAG | HTML_FLAG);
}
else if (strincmp(buf+1, "nonode") == 0)
flags |= NONODE_FLAG;
else if (strincmp(buf+1, "xref ") == 0) {
add_line(buf+6, XREF_FLAG);
if (last_toc_line == al_draw_line-1)
last_toc_line = al_draw_line;
}
else if (strincmp(buf+1, "header ") == 0)
add_line(buf+8, HEADER_FLAG);
else if (strincmp(buf+1, "startoutput ") == 0)
add_line(buf+13, STARTOUTPUT_FLAG);
else if (strincmp(buf+1, "endoutput ") == 0)
add_line(buf+11, ENDOUTPUT_FLAG);
else if (strincmp(buf+1, "tallbullet") == 0)
add_line("", TALLBULLET_FLAG);
else if ((mytolower(buf[1]=='h')) && (buf[2]=='='))
strcpy(fileheader, buf+3);
else if ((mytolower(buf[1]=='f')) && (buf[2]=='='))
strcpy(filefooter, buf+3);
else if ((mytolower(buf[1]=='f')) && (buf[2]=='1') && (buf[3]=='='))
sprintf(filefooter, "%s%s", buf+4, get_filename(htmlname));
else if ((mytolower(buf[1]=='f')) && (buf[2]=='2') && (buf[3]=='='))
strcat(filefooter, buf+4);
else if (strincmp(buf+1, "rtfh=") == 0)
strcpy(rtfheader, buf+6);
else if (strincmp(buf+1, "manh=") == 0)
strcpy(manheader, buf+6);
else if (strincmp(buf+1, "mans=") == 0)
strcpy(mansynopsis, buf+6);
else if (strincmp(buf+1, "locale=") == 0)
set_locale(buf+8);
else if (strincmp(buf+1, "htmlindex") == 0)
add_toc_line(buf+11, NULL, 1, al_draw_line, 0, 1, 1);
else if (strincmp(buf+1, "multiwordheaders") == 0)
multiwordheaders = 1;
else if (buf[1] == '<')
add_line(buf+1, (flags | HTML_FLAG | HTML_CMD_FLAG | NO_EOL_FLAG ) & (~TEXT_FLAG));
else if (buf[1] == '$')
add_line(buf+2, TEXINFO_FLAG | TEXINFO_CMD_FLAG);
else if (buf[1] == '@') {
add_toc(buf+2, 0, al_draw_line, !(flags & NONODE_FLAG), 1);
add_line(buf+2, flags | DEFINITION_FLAG);
flags &= ~NONODE_FLAG;
}
else if (buf[1] == '\\') {
add_toc(buf+2, 0, al_draw_line, !(flags & NONODE_FLAG), 1);
add_line(buf+2, flags | DEFINITION_FLAG | CONTINUE_FLAG);
flags &= ~NONODE_FLAG;
}
else if (buf[1] == '#') {
/* comment */
}
else {
fclose(f);
fprintf(stderr, "Unknown token '%s'\n", buf);
return 1;
}
}
else {
/* some actual text */
if (flags & HEADING_FLAG)
add_toc(buf, 1, al_draw_line, !(flags & NONODE_FLAG), (flags & HTML_FLAG));
add_line(buf, flags);
if (warn_on_long_lines) {
int len = strlen (buf);
if (len > 77)
printf("Warning: al_draw_line %d exceded in %d caracters '...%s'\n",
al_draw_line, len - 77, buf + 77);
}
flags &= ~(HEADING_FLAG | NOCONTENT_FLAG | NONODE_FLAG);
}
}
fclose(f);
return 0;
}
char *strip_html(char *p)
{
static char buf[256];
int c;
c = 0;
while (*p) {
if (*p == '<') {
while ((*p) && (*p != '>'))
p++;
if (*p)
p++;
}
else {
buf[c] = *p;
c++;
p++;
}
}
buf[c] = 0;
return buf;
}
unsigned char dos_latin_mapping[] =
{
0x20, 0xAD, 0xBD, 0x9C, 0xCF, 0xBE, 0xDD, 0xF5,
0xF9, 0xB8, 0xA6, 0xAE, 0xAA, 0xF0, 0xA9, 0xEE,
0xF8, 0xF1, 0xFD, 0xFC, 0xEF, 0xE6, 0xF4, 0xFA,
0xF7, 0xFB, 0xA7, 0xAF, 0xAC, 0xAB, 0xF3, 0xA8,
0xB7, 0xB5, 0xB6, 0xC7, 0x8E, 0x8F, 0x92, 0x80,
0xD4, 0x90, 0xD2, 0xD3, 0xDE, 0xD6, 0xD7, 0xD8,
0xD1, 0xA5, 0xE3, 0xE0, 0xE2, 0xE5, 0x99, 0x9E,
0x9D, 0xEB, 0xE9, 0xEA, 0x9A, 0xED, 0xE8, 0xE1,
0x85, 0xA0, 0x83, 0xC6, 0x84, 0x86, 0x91, 0x87,
0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B,
0xD0, 0xA4, 0x95, 0xA2, 0x93, 0xE4, 0x94, 0xF6,
0x9B, 0x97, 0xA3, 0x96, 0x81, 0xEC, 0xE7, 0x98
};
void afputc(unsigned char c, FILE *file)
{
if (dos_codepage) {
if (c >= 0xA0)
c = dos_latin_mapping[c-0xA0];
}
fputc(c, file);
}
void afputs(char *string, FILE *file)
{
while (*string) {
afputc((unsigned char)*string, file);
string++;
}
}
void hfputs(char *string, FILE *file)
{
while (*string) {
if ((string[0] == '&') &&
((string[1] == 'l') || (string[1] == 'g')) &&
(string[2] == 't')) {
fputc('&', file);
fputc(string[1], file);
fputc('t', file);
fputc(';', file);
string += 3;
}
else {
fputc(*string, file);
string++;
}
}
}
void hfprintf(FILE *file, char *format, ...)
{
char buf[1024];
va_list ap;
va_start(ap, format);
vsprintf(buf, format, ap);
va_end(ap);
hfputs(buf, file);
}
void tfputc(unsigned char c, FILE *file)
{
afputc(c, file);
}
void tfputs(char *string, FILE *file)
{
while (*string) {
tfputc((unsigned char)*string, file);
string++;
}
}
void tfprintf(FILE *file, char *format, ...)
{
char buf[1024];
va_list ap;
va_start(ap, format);
vsprintf(buf, format, ap);
va_end(ap);
tfputs(buf, file);
}
void rfputc(unsigned char c, FILE *file)
{
fputc(c, file);
}
void rfputs(char *string, FILE *file)
{
while (*string) {
rfputc((unsigned char)*string, file);
string++;
}
}
int toc_size(int part)
{
TOC *toc = tochead;
int section_number = 0;
int count = 0;
if (toc)
toc = toc->next;
while ((toc) && (section_number <= part)) {
if ((toc->root) && (!toc->otherfile))
section_number++;
toc = toc->next;
}
while ((toc) && (!toc->root)) {
if (toc->htmlable)
count++;
toc = toc->next;
}
return count;
}
int toc_scmp(const void *e1, const void *e2)
{
TOC *t1 = *((TOC **)e1);
TOC *t2 = *((TOC **)e2);
return mystricmp(t1->text, t2->text);
}
void output_toc(FILE *f, char *filename, int root, int body, int part)
{
char name[256];
char *s;
TOC *toc;
int nested = 0;
int section_number = 0;
#define ALT_TEXT(toc) ((toc->alt) ? toc->alt : toc->text)
if (root) {
toc = tochead;
if (toc)
toc = toc->next;
fprintf(f, "<ul><h4>\n");
while (toc) {
if ((toc->root) && (toc->htmlable)) {
if (toc->otherfile) {
sprintf(name, "%s.%s", toc->text, html_extension);
mystrlwr(name);
hfprintf(f, "<li><a href=\"%s\">%s</a>\n", name, ALT_TEXT(toc));
}
else if (body) {
hfprintf(f, "<li><a href=\"#%s\">%s</a>\n", toc->text, ALT_TEXT(toc));
section_number++;
}
else {
strcpy(name, filename);
s = extension(name)-1;
if ((int)s - (int)get_filename(name) > 5)
s = get_filename(name)+5;
sprintf(s, "%03d.%s", section_number, html_extension);
hfprintf(f, "<li><a href=\"%s\">%s</a>\n", get_filename(name), ALT_TEXT(toc));
section_number++;
}
}
toc = toc->next;
}
fprintf(f, "</h4></ul><p>\n");
}
if (body) {
toc = tochead;
if (toc)
toc = toc->next;
if (part <= 0) {
TOC *ptr[TOC_SIZE];
int j, i = 0;
if (root)
fprintf(f, "<ul><h2>\n");
else
fprintf(f, "<ul><h4>\n");
while (toc) {
if ((toc->htmlable) && (!toc->otherfile)) {
if (!toc->root) {
if (!nested) {
fprintf(f, "<ul><h4>\n");
nested = 1;
}
}
else {
if (nested) {
if (i > 1)
qsort(ptr, i, sizeof(TOC *), toc_scmp);
for (j = 0; j < i; j++)
hfprintf(f, "<li><a href=\"#%s\">%s</a>\n", ptr[j]->text, ALT_TEXT(ptr[j]));
fprintf(f, "</h4></ul><p>\n");
nested = i = 0;
}
}
if (nested) {
if(i < TOC_SIZE)
ptr[i++] = toc;
}
else
hfprintf(f, "<li><a href=\"#%s\">%s</a>\n", toc->text, ALT_TEXT(toc));
}
toc = toc->next;
}
if (nested)
fprintf(f, "</h4></ul>\n");
if (root)
fprintf(f, "</h2></ul>\n");
else
fprintf(f, "</h4></ul>\n");
}
else {
TOC *ptr[TOC_SIZE];
int j, i = 0;
section_number = 0;
fprintf(f, "<p>\n<ul><h4>\n");
while ((toc) && (section_number < part)) {
if ((toc->root) && (!toc->otherfile))
section_number++;
toc = toc->next;
}
while ((toc) && (!toc->root) && (i < TOC_SIZE)) {
if (toc->htmlable)
ptr[i++] = toc;
toc = toc->next;
}
if (i > 1)
qsort(ptr, i, sizeof(TOC *), toc_scmp);
for (j = 0; j < i; j++)
hfprintf(f, "<li><a href=\"#%s\">%s</a>\n", ptr[j]->text, ALT_TEXT(ptr[j]));
fprintf(f, "</h4></ul>\n<p><br><br>\n");
}
}
}
char *first_word(char *s)
{
static char buf[256];
int i;
if (multiwordheaders)
return strncpy(buf, s, 255);
for (i=0; s[i] && s[i] != ' '; i++)
buf[i] = s[i];
buf[i] = 0;
return buf;
}
int scmp(const void *e1, const void *e2)
{
char *s1 = *((char **)e1);
char *s2 = *((char **)e2);
return mystricmp(s1, s2);
}
void output_texinfo_toc(FILE *f, int root, int body, int part)
{
TOC *toc;
int section_number;
char **ptr;
char *s;
int i, j;
fprintf(f, "@menu\n");
if (root) {
toc = tochead;
if (toc)
toc = toc->next;
while (toc) {
if ((toc->root) && (toc->texinfoable)) {
s = first_word(toc->text);
tfprintf(f, "* %s::", s);
for (i=strlen(s); i<24; i++)
fputc(' ', f);
tfprintf(f, "%s\n", toc->text);
}
toc = toc->next;
}
}
if (body) {
toc = tochead;
if (toc)
toc = toc->next;
if (part <= 0) {
ptr = malloc(TOC_SIZE * sizeof(char *));
i = 0;
while (toc) {
if ((!toc->root) && (toc->texinfoable) && (i < TOC_SIZE))
ptr[i++] = toc->text;
toc = toc->next;
}
if (i > 1)
qsort(ptr, i, sizeof(char *), scmp);
for (j=0; j<i; j++)
tfprintf(f, "* %s::\n", ptr[j]);
free(ptr);
}
else {
section_number = 0;
while ((toc) && (section_number < part)) {
if ((toc->root) && (!toc->otherfile))
section_number++;
toc = toc->next;
}
while ((toc) && (!toc->root)) {
if (toc->texinfoable)
tfprintf(f, "* %s::\n", toc->text);
toc = toc->next;
}
}
}
fprintf(f, "@end menu\n");
}
int valid_texinfo_node(char *s, char **next, char **prev)
{
TOC *toc = tochead;
*next = *prev = "";
while (toc) {
if ((!toc->root) && (toc->texinfoable)) {
if (mystricmp(toc->text, s) == 0) {
do {
toc = toc->next;
} while ((toc) && ((!toc->texinfoable) || (toc->root)));
if (toc)
*next = toc->text;
return 1;
}
*prev = toc->text;
}
toc = toc->next;
}
return 0;
}
char *node_name(int i)
{
TOC *toc = tochead;
if (toc)
toc = toc->next;
while (toc) {
if ((toc->root) && (toc->texinfoable)) {
i--;
if (!i)
return first_word(toc->text);
}
toc = toc->next;
}
return "";
}
int write_txt(char *filename, int partial)
{
LINE *al_draw_line = head;
char *p;
int c, len;
FILE *f;
int outputting = !partial;
printf("writing %s\n", filename);
f = fopen(filename, "w");
if (!f)
return 1;
while (al_draw_line) {
if (al_draw_line->flags & (STARTOUTPUT_FLAG | ENDOUTPUT_FLAG)) {
if (mystricmp(al_draw_line->text, get_filename(filename)) == 0) {
if (al_draw_line->flags & STARTOUTPUT_FLAG)
outputting = 1;
else
outputting = 0;
}
}
else if ((al_draw_line->flags & TEXT_FLAG) && (outputting)) {
p = al_draw_line->text;
if (al_draw_line->flags & HEADING_FLAG) {
/* output a section heading */
p = strip_html(p);
len = strlen(p);
for (c=0; c<len+26; c++)
fputc('=', f);
afputs("\n============ ", f);
afputs(p, f);
afputs(" ============\n", f);
for (c=0; c<len+26; c++)
fputc('=', f);
fputs("\n", f);
}
else {
while (*p) {
/* less-than HTML tokens */
if ((p[0] == '&') &&
(mytolower(p[1]) == 'l') &&
(mytolower(p[2]) == 't')) {
fputc('<', f);
p += 3;
}
/* greater-than HTML tokens */
else if ((p[0] == '&') &&
(mytolower(p[1]) == 'g') &&
(mytolower(p[2]) == 't')) {
fputc('>', f);
p += 3;
}
/* strip other HTML tokens */
else if (p[0] == '<') {
while ((*p) && (*p != '>'))
p++;
if (*p)
p++;
}
/* output other characters */
else {
afputc(*p, f);
p++;
}
}
fputs("\n", f);
}
}
al_draw_line = al_draw_line->next;
}
fclose(f);
return 0;
}
void output_headfooter(FILE *f, char *s, char *t)
{
char buf[256];
int i, n;
strcpy(buf, s);
if (buf[0]) {
for (i=0; buf[i]; i++) {
if (strincmp(buf+i, ".html") == 0) {
i++;
n = strlen(html_extension);
memcpy(buf+i, html_extension, n);
if (n < 4)
memmove(buf+i+n, buf+i+4, strlen(buf+4)+1);
i += n;
}
}
for (i=0; buf[i]; i++) {
if (buf[i] == '#')
fputs(strip_html(t), f);
else
fputc(buf[i], f);
}
fputs("\n", f);
}
}
int write_html(char *filename)
{
char buf[256];
int empty_count = 0;
int section_number = 0;
LINE *al_draw_line = head;
FILE *f;
char *s, *s2, *s3;
int i;
printf("writing %s\n", filename);
f = fopen(filename, "w");
if (!f)
return 1;
while (al_draw_line) {
if (al_draw_line->flags & HTML_FLAG) {
if (al_draw_line->flags & HEADING_FLAG) {
/* output a section heading, switching file as required */
if ((flags & MULTIFILE_FLAG) && (section_number > 0)) {
if (section_number > 1)
output_headfooter(f, filefooter, "");
fclose(f);
strcpy(buf, filename);
s = extension(buf)-1;
if ((int)s - (int)get_filename(buf) > 5)
s = get_filename(buf)+5;
sprintf(s, "%03d.%s", section_number-1, html_extension);
printf("writing %s\n", buf);
f = fopen(buf, "w");
if (!f)
return 1;
output_headfooter(f, fileheader, al_draw_line->text);
}
hfprintf(f, "<h1>%s</h1>\n", al_draw_line->text);
empty_count = 0;
if ((flags & MULTIFILE_FLAG) &&
(!(al_draw_line->flags & NOCONTENT_FLAG)) &&
(section_number > 0)) {
output_toc(f, filename, 0, 1, section_number);
}
section_number++;
}
else if (al_draw_line->flags & NODE_FLAG) {
/* output a node marker */
fprintf(f, "<p><hr><p>\n");
}
else if (al_draw_line->flags & DEFINITION_FLAG) {
/* output a function definition */
hfprintf(f, "<b>%s</b>", al_draw_line->text);
if (!(al_draw_line->flags & CONTINUE_FLAG))
fputs("<br>", f);
fputs("\n", f);
empty_count = 0;
}
else if ((!(al_draw_line->flags & NO_EOL_FLAG)) &&
(is_empty(strip_html(al_draw_line->text)))) {
/* output an empty al_draw_line */
if (empty_count)
hfprintf(f, "<br>%s\n", al_draw_line->text);
else
hfprintf(f, "<p>%s\n", al_draw_line->text);
empty_count++;
}
else if (strstr(al_draw_line->text, "<email>") || strstr(al_draw_line->text, "<link>")) {
/* special munging for links */
s = al_draw_line->text;
do {
s2 = strstr(s, "<email>");
s3 = strstr(s, "<link>");
if ((s2) || (s3)) {
if ((s3) && ((!s2) || (s3 < s2)))
s2 = s3;
i = 0;
while (s < s2)
buf[i++] = *(s++);
buf[i] = 0;
hfputs(buf, f);
while (*s != '>')
s++;
s++;
i = 0;
while ((*s) && (*s != '<'))
buf[i++] = *(s++);
buf[i] = 0;
if (s2[1] == 'e')
hfprintf(f, "<a href=\"mailto:%s\">%s", buf, buf);
else
hfprintf(f, "<a href=\"%s\">%s", buf, buf);
}
} while (s2);
hfputs(s, f);
fputs("\n", f);
empty_count = 0;
}
else {
/* output a normal al_draw_line */
hfputs(al_draw_line->text, f);
fputs("\n", f);
empty_count = 0;
}
}
else if (al_draw_line->flags & TOC_FLAG) {
if (flags & MULTIFILE_FLAG)
output_toc(f, filename, 1, 0, -1);
else if (al_draw_line->flags & SHORT_TOC_FLAG)
output_toc(f, filename, 0, 1, -1);
else
output_toc(f, filename, 1, 1, -1);
}
al_draw_line = al_draw_line->next;
}
if ((flags & MULTIFILE_FLAG) && (section_number > 1))
output_headfooter(f, filefooter, "");
fclose(f);
return 0;
}
void html2texinfo(FILE *f, char *p)
{
char buf[256];
int i = 0;
while ((*p) && (*p != '>'))
buf[i++] = *(p++);
buf[i] = 0;
if (mystricmp(buf, "pre") == 0) {
fputs("@example\n", f);
nostrip = 1;
strip_indent = -1;
}
else if (mystricmp(buf, "/pre") == 0) {
fputs("@end example\n", f);
nostrip = 0;
strip_indent = -1;
}
else if (mystricmp(buf, "br") == 0) {
fputs("@*", f);
}
else if (mystricmp(buf, "hr") == 0) {
fputs("----------------------------------------------------------------------", f);
}
else if (mystricmp(buf, "p") == 0) {
fputs("\n", f);
}
else if (mystricmp(buf, "ul") == 0) {
fputs("\n@itemize @bullet\n", f);
}
else if (mystricmp(buf, "/ul") == 0) {
fputs("@end itemize\n", f);
}
else if (mystricmp(buf, "li") == 0) {
fputs("@item ", f);
}
}
void write_textinfo_xref(FILE *f, char *xref)
{
char *tok;
tok = strtok(xref, ",;");
while (tok) {
while ((*tok) && (myisspace(*tok)))
tok++;
tfprintf(f, "@xref{%s}.@*\n", tok);
tok = strtok(NULL, ",;");
}
}
int write_texinfo(char *filename)
{
char buf[256];
LINE *al_draw_line = head, *title_line = 0;
char *p, *str, *next, *prev;
char *xref[256];
int xrefs = 0;
int in_item = 0;
int section_number = 0;
int toc_waiting = 0;
int continue_def = 0;
int title_pass = 0;
int i;
FILE *f;
printf("writing %s\n", filename);
f = fopen(filename, "w");
if (!f)
return 1;
while (al_draw_line) {
if (al_draw_line->flags & TEXINFO_FLAG) {
p = al_draw_line->text;
/* end of an ftable? */
if (in_item) {
if ((*p) && (*p != ' ') && (*p != '<')) {
fputs("@end ftable\n", f);
in_item = 0;
}
}
if (!in_item) {
/* start a new node? */
str = strstr(p, "<a name=\"");
if (str > p) {
str += strlen("<a name=\"");
for (i=0; str[i] && str[i] != '"'; i++)
buf[i] = str[i];
buf[i] = 0;
if (!(al_draw_line->flags & NONODE_FLAG) &&
(valid_texinfo_node(buf, &next, &prev))) {
if (toc_waiting) {
output_texinfo_toc(f, 0, 1, section_number-1);
toc_waiting = 0;
}
if (xrefs > 0) {
fputs("See also:@*\n", f);
for (i=0; i<xrefs; i++)
write_textinfo_xref(f, xref[i]);
xrefs = 0;
}
tfprintf(f, "@node %s, %s, %s, %s\n", buf, next, prev, node_name(section_number-1));
tfprintf(f, "@section %s\n", buf);
}
fputs("@ftable @asis\n", f);
in_item = 1;
}
}
/* munge the indentation to make it look nicer */
if (!(al_draw_line->flags & NO_INDENT_FLAG)) {
if (nostrip) {
if (strip_indent >= 0) {
for (i=0; (i<strip_indent) && (*p) && (myisspace(*p)); i++)
p++;
}
else {
if (!is_empty(p)) {
strip_indent = 0;
while ((*p) && (myisspace(*p))) {
strip_indent++;
p++;
}
}
}
}
else {
while ((*p) && (myisspace(*p)))
p++;
}
}
if (al_draw_line->flags & TEXINFO_CMD_FLAG) {
/* raw output of texinfo commands */
tfputs(p, f);
fputs("\n", f);
}
else if (al_draw_line->flags & HTML_CMD_FLAG) {
/* process HTML commands */
while (*p) {
if (p[0] == '<') {
html2texinfo(f, p+1);
while ((*p) && (*p != '>'))
p++;
if (*p)
p++;
}
else
p++;
}
}
else if (al_draw_line->flags & HEADING_FLAG) {
/* output a section heading */
if (section_number > 0) {
if (in_item) {
fputs("@end ftable\n", f);
in_item = 0;
}
if (xrefs > 0) {
fputs("See also:@*\n", f);
for (i=0; i<xrefs; i++)
write_textinfo_xref(f, xref[i]);
xrefs = 0;
}
p = strip_html(p);
tfprintf(f, "@node %s, ", node_name(section_number));
tfprintf(f, "%s, ", node_name(section_number+1));
tfprintf(f, "%s, Top\n", node_name(section_number-1));
tfprintf(f, "@chapter %s\n", p);
if (!(al_draw_line->flags & NOCONTENT_FLAG))
toc_waiting = 1;
}
section_number++;
}
else {
if ((al_draw_line->flags & DEFINITION_FLAG) && (!continue_def))
fputs("@item @t{", f);
while (*p) {
/* less-than HTML tokens */
if ((p[0] == '&') &&
(mytolower(p[1]) == 'l') &&
(mytolower(p[2]) == 't')) {
fputc('<', f);
p += 3;
}
/* greater-than HTML tokens */
else if ((p[0] == '&') &&
(mytolower(p[1]) == 'g') &&
(mytolower(p[2]) == 't')) {
fputc('>', f);
p += 3;
}
/* process other HTML tokens */
else if (p[0] == '<') {
html2texinfo(f, p+1);
while ((*p) && (*p != '>'))
p++;
if (*p)
p++;
}
/* output other characters */
else {
if ((*p == '{') || (*p == '}') || (*p == '@'))
fputc('@', f);
tfputc((unsigned char)*p, f);
p++;
}
}
if (al_draw_line->flags & CONTINUE_FLAG)
fputs(" ", f);
else {
if (al_draw_line->flags & DEFINITION_FLAG)
fputs("}", f);
fputs("\n", f);
}
}
}
else if (al_draw_line->flags & NODE_FLAG) {
if (in_item) {
fputs("@end ftable\n", f);
if (toc_waiting) {
output_texinfo_toc(f, 0, 1, section_number-1);
toc_waiting = 0;
}
}
if (valid_texinfo_node(al_draw_line->text, &next, &prev)) {
if (xrefs > 0) {
fputs("See also:@*\n", f);
for (i=0; i<xrefs; i++)
write_textinfo_xref(f, xref[i]);
xrefs = 0;
}
tfprintf(f, "@node %s, %s, %s, %s\n", al_draw_line->text, next, prev, node_name(section_number-1));
tfprintf(f, "@section %s\n", al_draw_line->text);
}
fputs("@ftable @asis\n", f);
in_item = 1;
}
else if (al_draw_line->flags & TOC_FLAG) {
output_texinfo_toc(f, 1, 0, 0);
}
else if (al_draw_line->flags & INDEX_FLAG) {
output_texinfo_toc(f, 0, 1, 0);
}
else if (al_draw_line->flags & XREF_FLAG) {
xref[xrefs++] = al_draw_line->text;
}
else if (al_draw_line->flags & START_TITLE_FLAG) {
/* remember where the title starts */
title_line = al_draw_line;
if (!title_pass)
fputs("@titlepage\n", f);
}
else if (al_draw_line->flags & AL_END_TITLE_FLAG) {
if (!title_pass)
{
title_pass++;
fputs("@end titlepage\n@ifinfo\n", f);
al_draw_line = title_line;
}
else
fputs("@end ifinfo\n", f);
}
continue_def = (al_draw_line->flags & CONTINUE_FLAG);
al_draw_line = al_draw_line->next;
}
fclose(f);
return 0;
}
int write_rtf(char *filename)
{
LINE *al_draw_line = head;
LINE *l;
char *p, *last = 0;
FILE *f;
int preformat = 0;
int prevhead = 0;
int prevdef = 0;
int multidef = 0;
int pardebt = 0;
int parloan = 0;
int indent = 0;
int indef = 0;
int weakdef = 0;
int bullet = 0;
int inbullet = 0;
int tallbullets = 0;
#define PAR() \
{ \
if (pardebt > 0) \
pardebt--; \
else \
fputs("\\par ", f); \
\
while (inbullet > 0) { \
fputs("\\pard ", f); \
fprintf(f, "\\li%d ", indent*INDENT_SIZE); \
inbullet--; \
} \
}
printf("writing %s\n", filename);
f = fopen(filename, "w");
if (!f)
return 1;
/* Fonts:
* 0 - Times New Roman
* 1 - Courier New
* 2 - Symbol
*
* Colors:
* 1 - Black
* 2 - Red
* 3 - Green
* 4 - Blue
*
* Styles:
* 0 - Normal
* 1 - Quotation
* 2 - Heading 1
* 3 - Heading 2
* 4 - Header
* 5 - TOC 1
* 6 - Index 1
*/
#define NORMAL_STYLE "\\f0\\fs20 "
#define QUOTATION_STYLE "\\f1\\fs18 "
#define HEADING_STYLE "\\f0\\fs48\\sa600\\pagebb\\keepn\\ul "
#define DEFINITION_STYLE "\\f0\\fs24\\sb200\\keepn\\sa200\\b "
#define HEADER_STYLE "\\f0\\fs20\\tqc\\tx4153\\tqr\\tx8306 "
#define TOC_STYLE "\\f0\\fs24\\tqr\\tldot\\tx8640 "
#define INDEX_STYLE "\\f0\\fs20\\tqr\\tldot\\tx8640 "
#define INDENT_SIZE 400
#define BULLET_INDENT 250
fputs("{\\rtf\\ansi\\deff0\\widowctrl " NORMAL_STYLE "\n", f);
fputs("{\\colortbl;\\red0\\green0\\blue0;\\red255\\green0\\blue0;\\red0\\green255\\blue0;\\red0\\green0\\blue255;}\n", f);
if (mystricmp(locale, "china") == 0) {
fputs("{\\fonttbl{\\f0\\froman\\fcharset134\\fprq2 _GB2312;}\n", f);
fputs("{\\f1\\fmodern\\fcharset134\\fprq1 ;}\n", f);
fputs("{\\f2\\froman\\fcharset134\\fprq2 ;}}\n", f);
}
else if (mystricmp(locale, "korea") == 0) {
fputs("{\\fonttbl{\\f0\\froman\\fcharset129\\fprq2 ±¼¸²;}\n", f);
fputs("{\\f1\\fmodern\\fcharset129\\fprq1 ;}\n", f);
fputs("{\\f2\\froman\\fcharset129\\fprq2 ;}}\n", f);
}
else {
fputs("{\\fonttbl{\\f0\\froman\\fcharset0\\fprq2 Times New Roman;}\n", f);
fputs("{\\f1\\fmodern\\fcharset0\\fprq1 Courier New;}\n", f);
fputs("{\\f2\\froman\\fcharset2\\fprq2 Symbol;}}\n", f);
}
fputs("{\\stylesheet {\\widctlpar " NORMAL_STYLE "\\snext0 Normal;}\n", f);
fputs("{\\s1\\widctlpar " QUOTATION_STYLE "\\sbasedon0\\snext1 Quotation;}\n", f);
fputs("{\\s2\\widctlpar " HEADING_STYLE "\\sbasedon0\\snext2 Heading 1;}\n", f);
fputs("{\\s3\\widctlpar " DEFINITION_STYLE "\\sbasedon0\\snext3 Heading 2;}\n", f);
fputs("{\\s4\\widctlpar " HEADER_STYLE "\\sbasedon0\\snext4 Header;}\n", f);
fputs("{\\s5\\widctlpar " TOC_STYLE "\\sbasedon0\\snext0 TOC 1;}\n", f);
fputs("{\\s6\\widctlpar " INDEX_STYLE "\\sbasedon0\\snext0 Index 1;}}\n", f);
if (rtfheader[0]) {
fputs("{\\header \\pard\\plain \\s4 " HEADER_STYLE "\\pvpara\\phmrg\\posxr\\posy0 page {\\field{\\*\\fldinst PAGE}{\\fldrslt 2}}\n", f);
fputs("\\par \\pard \\s4\\ri360 " HEADER_STYLE "{\\i ", f);
fputs(rtfheader, f);
fputs("} \\pard}\n", f);
}
while (al_draw_line) {
if (al_draw_line->flags & RTF_FLAG) {
p = al_draw_line->text;
if (indef) {
/* end the indentation from the previous definition? */
if (weakdef) {
if (is_empty(strip_html(al_draw_line->text))) {
fputs("\\par}", f);
pardebt++;
indent--;
indef = 0;
weakdef = 0;
}
}
else {
l = al_draw_line;
while ((l->next) && (is_empty(strip_html(l->text))))
l = l->next;
if (l->flags & (HEADING_FLAG | DEFINITION_FLAG | NODE_FLAG)) {
fputs("\\par}", f);
pardebt++;
indent--;
indef = 0;
}
}
}
if (al_draw_line->flags & HEADING_FLAG) {
/* start a section heading */
fputs("{\\s2 " HEADING_STYLE, f);
}
else if (al_draw_line->flags & DEFINITION_FLAG) {
/* start a function definition */
if (prevdef) {
if (multidef) {
/* continued from previous al_draw_line */
while ((p[1]) && (myisspace(p[1])))
p++;
}
else {
/* new definition, but flush with previous one */
fputs("{\\s3 " DEFINITION_STYLE "\\sb0 ", f);
}
}
else {
/* new function definition */
fputs("{\\s3 " DEFINITION_STYLE, f);
}
if (al_draw_line->flags & CONTINUE_FLAG) {
/* this definition continues onto the next al_draw_line */
multidef = 1;
}
else {
/* this paragraph should be flush with the next */
multidef = 0;
if ((al_draw_line->next) && (al_draw_line->next->flags & DEFINITION_FLAG))
fputs("\\sa0 ", f);
}
prevdef = 1;
}
else {
prevdef = 0;
multidef = 0;
if (!preformat) {
/* skip leading spaces */
while ((*p) && (myisspace(*p)))
p++;
}
}
while (*p) {
last = 0;
if (strincmp(p, "<p>") == 0) {
/* paragraph breaks */
PAR();
p += 3;
}
else if (strincmp(p, "<br>") == 0) {
/* al_draw_line breaks */
PAR();
p += 4;
}
else if (strincmp(p, "<pre>") == 0) {
/* start preformatted text */
fputs("\\par {\\s1 " QUOTATION_STYLE, f);
while (inbullet > 0) {
fputs("\\pard ", f);
fprintf(f, "\\li%d ", indent*INDENT_SIZE);
inbullet--;
}
preformat = 1;
p += 5;
}
else if (strincmp(p, "</pre>") == 0) {
/* end preformatted text */
if (strincmp(al_draw_line->text, "</pre>") == 0) {
fputs("}", f);
if (indent > (indef ? 1 : 0)) {
fputs("\\pard ", f);
fprintf(f, "\\li%d ", indent*INDENT_SIZE);
}
}
else {
fputs("\\par}", f);
pardebt++;
if (indent > (indef ? 1 : 0))
inbullet++;
}
preformat = 0;
p += 6;
}
else if (strincmp(p, "<title>") == 0) {
/* start document title */
fputs("{\\info{\\title ", f);
p += 7;
}
else if (strincmp(p, "</title>") == 0) {
/* end document title */
fputs("}{\\author Allegro makedoc utility}}\n", f);
p += 8;
}
else if (strincmp(p, "<hr>") == 0) {
/* section division */
if (strincmp(al_draw_line->text, "</pre>"))
PAR();
fputs("\\brdrb\\brdrs\\brdrw15\\brsp20 \\par \\pard \\par ", f);
p += 4;
}
else if (strincmp(p, "<b>") == 0) {
/* start bold text */
fputs("{\\b ", f);
p += 3;
}
else if (strincmp(p, "</b>") == 0) {
/* end bold text */
fputs("\\par}", f);
pardebt++;
p += 4;
}
else if (strincmp(p, "<i>") == 0) {
/* start italic text */
fputs("{\\i ", f);
p += 3;
}
else if (strincmp(p, "</i>") == 0) {
/* end italic text */
fputs("\\par}", f);
pardebt++;
p += 4;
}
else if (strincmp(p, "<h1>") == 0) {
/* start heading text */
fputs("{\\f0\\fs48 ", f);
p += 4;
}
else if (strincmp(p, "</h1>") == 0) {
/* end heading text */
fputs("\\par}", f);
pardebt++;
p += 5;
}
else if (strincmp(p, "<h4>") == 0) {
/* start subheading text */
fputs("{\\f0\\fs24\\b ", f);
p += 4;
}
else if (strincmp(p, "</h4>") == 0) {
/* end subheading text */
fputs("\\par}", f);
pardebt++;
p += 5;
}
else if (strincmp(p, "<center>") == 0) {
/* start centered text */
fputs("\\par {\\qc ", f);
pardebt++;
p += 8;
}
else if (strincmp(p, "</center>") == 0) {
/* end centered text */
fputs("\\par}", f);
pardebt++;
p += 9;
}
else if (strincmp(p, "<a name=\"") == 0) {
/* begin index entry */
fputs("{\\xe\\v ", f);
p += 9;
while ((*p) && (*p != '"')) {
rfputc((unsigned char)*p, f);
p++;
}
fputs("}", f);
p += 2;
}
else if (strincmp(p, "<ul>") == 0) {
/* start bullet list */
indent++;
fprintf(f, "\\par {\\li%d ", indent*INDENT_SIZE);
pardebt++;
p += 4;
}
else if (strincmp(p, "</ul>") == 0) {
/* end bullet list */
indent--;
if (indent == (indef ? 1 : 0))
tallbullets = 0;
else
inbullet++;
fputs("\\par}", f);
pardebt++;
p += 5;
}
else if (strincmp(p, "<li>") == 0) {
/* bullet item */
bullet = 1;
p += 4;
}
else if (*p == '<') {
/* skip unknown HTML tokens */
while ((*p) && (*p != '>'))
p++;
p++;
}
else if (strincmp(p, "<") == 0) {
/* less-than HTML tokens */
fputs("<", f);
p += 3;
}
else if (strincmp(p, ">") == 0) {
/* greater-than HTML tokens */
fputs(">", f);
p += 3;
}
else if (*p == '\\') {
/* backslash escape */
fputs("\\\\", f);
p++;
}
else if (*p == '{') {
/* open brace escape */
fputs("\\{", f);
p++;
}
else if (*p == '}') {
/* close brace escape */
fputs("\\}", f);
p++;
}
else {
while (pardebt > 0) {
fputs("\\par ", f);
pardebt--;
}
if (bullet) {
/* precede this paragraph with a bullet symbol */
fputs("{\\pntext\\f2\\fs16 \\'b7\\tab}\n", f);
fprintf(f, "{\\*\\pn \\pnlvlblt\\pnf2\\pnfs16\\pnindent%d{\\pntxtb \\'b7}}\n", BULLET_INDENT);
fprintf(f, "\\fi%d\\li%d ", -BULLET_INDENT, indent*INDENT_SIZE);
if (tallbullets)
fputs("\\sa80 ", f);
bullet = 0;
inbullet++;
}
/* normal character */
rfputc((unsigned char)*p, f);
last = p++;
}
}
if (al_draw_line->flags & HEADING_FLAG) {
/* end a section heading */
fputs("\\par }\n", f);
}
else if (prevdef) {
/* end a function definition */
if (!multidef) {
fputs("\\par }\n", f);
if ((!indef) && (al_draw_line->next) && (!(al_draw_line->next->flags & DEFINITION_FLAG))) {
/* indent the definition body text */
indent++;
fprintf(f, "{\\li%d ", indent*INDENT_SIZE);
indef = 1;
if (al_draw_line->flags & NONODE_FLAG)
weakdef = 1;
}
}
}
else if (preformat) {
/* hard CR for preformatted blocks */
fputs("\n", f);
parloan++;
}
else if (!(al_draw_line->flags & NO_EOL_FLAG)) {
if ((is_empty(strip_html(al_draw_line->text))) &&
(!strstr(al_draw_line->text, "<hr>"))) {
/* output an empty al_draw_line */
if (!prevhead) {
parloan++;
if (!strstr(al_draw_line->text, "</pre>"))
parloan++;
}
}
else {
if (last && *last != 32)
fputs(" ", f); /* add artificial space */
fputs("\n", f); /* normal EOL */
}
}
}
else if (al_draw_line->flags & NODE_FLAG) {
/* index node */
if (al_draw_line->flags & HTML_FLAG) {
fputs("\\brdrb\\brdrs\\brdrw15\\brsp20 \\par \\pard \\par \\par ", f);
}
fputs("{\\xe\\v ", f);
rfputs(al_draw_line->text, f);
fputs("}\n", f);
}
else if (al_draw_line->flags & TOC_FLAG) {
/* table of contents */
PAR();
fputs("\n{\\field{\\*\\fldinst TOC \\\\t \"Heading 1\" }{\\fldrslt {\\b\\i\\ul\\fs24\\cf2 Update this field to generate the table of contents.}}}\n", f);
}
else if (al_draw_line->flags & INDEX_FLAG) {
/* index */
PAR();
fputs("\n{\\field{\\*\\fldinst INDEX \\\\e \"\\tab \" \\c \"1\" }{\\fldrslt {\\b\\i\\ul\\fs24\\cf2 Update this field to generate the document index.}}}\n", f);
}
else if (al_draw_line->flags & TALLBULLET_FLAG) {
/* larger spacing after bulleted paragraphs */
tallbullets = 1;
}
prevhead = (al_draw_line->flags & HEADING_FLAG);
/* advance to the next al_draw_line */
l = al_draw_line->next;
if (l) {
while ((l->next) && (is_empty(l->text)) && (l->next->flags == l->flags)) {
l = l->next;
}
if ((l->next) && (l->next->flags & HEADING_FLAG)) {
if (indef) {
fputs("\\par}", f);
pardebt++;
indent--;
indef = 0;
}
PAR();
al_draw_line = l->next;
parloan = 0;
pardebt = 0;
}
else
al_draw_line = al_draw_line->next;
}
else
al_draw_line = NULL;
while (parloan > 0) {
PAR();
parloan--;
}
}
fputs("}\n", f);
fclose(f);
return 0;
}
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;
}
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;
}
/* al_draw_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 == '\'') || (*p == '\\'))
fputc('\\', f);
fputc(*p, f);
p++;
state = 1;
}
}
if (state >= 0)
fputc('\n', f);
}
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, ",;");
}
}
int write_man(char *filename)
{
char buf[256], buf2[256];
char *xref[256];
int xrefs = 0;
LINE *al_draw_line = head;
LINE *l2;
FILE *f = NULL;
FILE *f2;
char *p;
int i;
while (al_draw_line) {
if (al_draw_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; i<xrefs; i++)
write_man_xref(f, xref[i], extension(filename), i);
fprintf(f, "\n");
xrefs = 0;
}
fclose(f);
f = NULL;
}
}
if (al_draw_line->flags & MAN_FLAG) {
if (al_draw_line->flags & DEFINITION_FLAG) {
/* start a manpage */
p = man_name(al_draw_line->text);
if (p) {
strcpy(buf, filename);
strcpy(get_filename(buf), p);
strcat(buf, ".");
strcat(buf, 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, extension(filename), manheader);
fprintf(f, ".SH NAME\n");
fprintf(f, "%s", p);
if (!(al_draw_line->flags & CONTINUE_FLAG)) {
l2 = al_draw_line->next;
while ((l2) && (l2->flags & DEFINITION_FLAG)) {
p = man_name(l2->text);
if (p)
fprintf(f, ", %s", p);
l2 = l2->next;
}
}
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 = al_draw_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(al_draw_line->text, f);
i = (al_draw_line->flags & CONTINUE_FLAG);
while ((al_draw_line->next) && (al_draw_line->next->flags & DEFINITION_FLAG)) {
al_draw_line = al_draw_line->next;
if (!i) {
/* multiple entries require a crosslink file */
p = man_name(al_draw_line->text);
if (p) {
strcpy(buf2, filename);
strcpy(get_filename(buf2), p);
strcat(buf2, ".");
strcat(buf2, extension(filename));
printf("writing %s\n", buf2);
f2 = fopen(buf2, "w");
if (!f2)
return 1;
fprintf(f2, ".so man%s/%s\n", extension(filename), get_filename(buf));
fclose(f2);
}
fputc('\n', f);
}
fputs(".B ", f);
mfputs(al_draw_line->text, f);
}
fprintf(f, ".SH DESCRIPTION\n");
mpreformat = 0;
}
xrefs = 0;
}
else {
/* normal output mode */
if (f)
mfputs(al_draw_line->text, f);
}
}
else if (al_draw_line->flags & XREF_FLAG) {
xref[xrefs++] = al_draw_line->text;
}
al_draw_line = al_draw_line->next;
}
return 0;
}
int main(int argc, char *argv[])
{
char filename[256] = "";
char txtname[256] = "";
char htmlname[256] = "";
char texinfoname[256] = "";
char rtfname[256] = "";
char manname[256] = "";
int err = 0;
int partial = 0;
int i;
for (i=1; i<argc; i++) {
if ((mystricmp(argv[i], "-ascii") == 0) && (i<argc-1)) {
strcpy(txtname, argv[++i]);
}
else if ((mystricmp(argv[i], "-html") == 0) && (i<argc-1)) {
strcpy(htmlname, argv[++i]);
html_extension = "html";
}
else if ((mystricmp(argv[i], "-htm") == 0) && (i<argc-1)) {
strcpy(htmlname, argv[++i]);
html_extension = "htm";
}
else if ((mystricmp(argv[i], "-texi") == 0) && (i<argc-1)) {
strcpy(texinfoname, argv[++i]);
texinfo_extension = "texi";
}
else if ((mystricmp(argv[i], "-txi") == 0) && (i<argc-1)) {
strcpy(texinfoname, argv[++i]);
texinfo_extension = "txi";
}
else if ((mystricmp(argv[i], "-rtf") == 0) && (i<argc-1)) {
strcpy(rtfname, argv[++i]);
}
else if ((mystricmp(argv[i], "-man") == 0) && (i<argc-1)) {
strcpy(manname, argv[++i]);
}
else if (mystricmp(argv[i], "-part") == 0) {
partial = 1;
}
else if (mystricmp(argv[i], "-warn") == 0) {
warn_on_long_lines = 1;
}
else if (argv[i][0] == '-') {
fprintf(stderr, "Unknown option '%s'\n", argv[i]);
return 1;
}
else {
strcpy(filename, argv[i]);
}
}
if (!filename[0]) {
printf("Usage: makedoc [outputs] [-part] [-warn] filename._tx\n\n");
printf("Output formats:\n");
printf("\t-ascii filename.txt\n");
printf("\t-htm[l] filename.htm[l]\n");
printf("\t-rtf filename.rtf\n");
printf("\t-t[e]xi filename.t[e]xi\n");
printf("\t-man filename.3\n");
return 1;
}
if ((!txtname[0]) && (!htmlname[0]) && (!texinfoname[0]) && (!rtfname[0]) && (!manname[0])) {
strcpy(txtname, filename);
strcpy(extension(txtname), "txt");
strcpy(htmlname, filename);
strcpy(extension(htmlname), html_extension);
strcpy(texinfoname, filename);
strcpy(extension(texinfoname), texinfo_extension);
strcpy(rtfname, filename);
strcpy(extension(rtfname), "rtf");
}
if (read_file(filename, htmlname) != 0) {
fprintf(stderr, "Error reading input file\n");
err = 1;
goto getout;
}
if (txtname[0]) {
if (write_txt(txtname, partial) != 0) {
fprintf(stderr, "Error writing ASCII output file\n");
err = 1;
goto getout;
}
}
if (htmlname[0]) {
if (write_html(htmlname) != 0) {
fprintf(stderr, "Error writing HTML output file\n");
err = 1;
goto getout;
}
}
if (texinfoname[0]) {
if (write_texinfo(texinfoname) != 0) {
fprintf(stderr, "Error writing TexInfo output file\n");
err = 1;
goto getout;
}
}
if (rtfname[0]) {
if (write_rtf(rtfname) != 0) {
fprintf(stderr, "Error writing RTF output file\n");
err = 1;
goto getout;
}
}
if (manname[0]) {
if (write_man(manname) != 0) {
fprintf(stderr, "Error writing MAN output file\n");
err = 1;
goto getout;
}
}
getout:
free_data();
return err;
}
See more files for this project here