fbmuck-6.01/contrib/jresolver/
fbmuck-6.01/contrib/jresolver/org/
fbmuck-6.01/contrib/jresolver/org/fuzzball/
fbmuck-6.01/docs/devel/
fbmuck-6.01/game/
fbmuck-6.01/game/logs/
fbmuck-6.01/game/muf/
fbmuck-6.01/scripts/
fbmuck-6.01/src_docs/
#include <stdio.h>
#include <string.h>
/* #include <strings.h> */
#include <ctype.h>


#define HRULE_TEXT "----------------------------------------------------------------------------"

#define HTML_PAGE_HEAD     	"<html><head><title>%s</title></head>\n<body><div align=\"center\"><h1>%s</h1>\n<h3>by %s</h3></div>\n<ul><li><a href=\"#AlphaList\">Alphabetical List of Topics</a></li>\n<li><a href=\"#SectList\">List of Topics by Category</a></li></ul>\n"
#define HTML_PAGE_FOOT     	"</body></html>\n"

#define HTML_SECTION     	"<p><hr size=6>\n<h3><a name=\"%s\">%s</a></h3>\n"
#define HTML_SECTLIST_HEAD  "<p><hr size=\"6\"><h3><a name=\"SectList\">List of Topics by Category</a></h3>\n<h4>You can get more help on the following topics:</h4>\n<ul>"
#define HTML_SECTLIST_ENTRY "  <li><a href=\"#%s\">%s</a></li>\n"
#define HTML_SECTLIST_FOOT  "</ul>\n\n"

#define HTML_SECTIDX_BEGIN	"<blockquote><table border=0>\n  <tr>\n"
#define HTML_SECTIDX_ENTRY	"    <td width=\"%d%%\"> &nbsp; <a href=\"#%s\">%s</a> &nbsp; </td>\n"
#define HTML_SECTIDX_NEWROW	"  </tr>\n  <tr>\n"
#define HTML_SECTIDX_END	"  </tr>\n</table></blockquote>\n\n"

#define HTML_INDEX_BEGIN	"<p><hr size=\"6\"><h3><a name=\"AlphaList\">Alphabetical List of Topics</a></h3>\n"
#define HTML_IDXGROUP_BEGIN	"<h4>%s</h4><blockquote><table border=0>\n  <tr>\n"
#define HTML_IDXGROUP_ENTRY	"    <td nowrap> &nbsp; <a href=\"#%s\">%s</a> &nbsp; </td>\n"
#define HTML_IDXGROUP_NEWROW	"  </tr>\n  <tr>\n"
#define HTML_IDXGROUP_END		"  </tr>\n</table></blockquote>\n\n"
#define HTML_INDEX_END		""

#define HTML_TOPICHEAD		"<hr><h4><a name=\"%s\">"
#define HTML_TOPICHEAD_BREAK	"<br>\n"
#define HTML_TOPICBODY		"</a></h4>\n"
#define HTML_TOPICEND		"<p>\n"
#define HTML_PARAGRAPH		"<p>\n"

#define HTML_CODEBEGIN		"<pre>\n"
#define HTML_CODEEND		"</pre>\n"

#define HTML_ALSOSEE_BEGIN      "<p><h5>Also see:\n"
#define HTML_ALSOSEE_ENTRY      "    <a href=\"#%s\">%s</a>"
#define HTML_ALSOSEE_END        "\n</h5>\n"


const char* title = "";
const char* author = "";
const char* doccmd = "";

char *
string_dup(const char *s)
{
	char *p;

	p = (char *) malloc(strlen(s) + 1);
	if (p)
		strcpy(p, s);
	return p;
}


char sect[256] = "";

struct topiclist {
	struct topiclist *next;
	char *topic;
	char *section;
	int printed;
};

struct topiclist *topichead;
struct topiclist *secthead;


void
add_section(const char *str)
{
	struct topiclist *ptr, *top;

	if (!str || !*str)
		return;
	top = (struct topiclist *) malloc(sizeof(struct topiclist));

	top->topic = NULL;
	top->section = (char *) string_dup(sect);
	top->printed = 0;
	top->next = NULL;

	if (!secthead) {
		secthead = top;
		return;
	}
	for (ptr = secthead; ptr->next; ptr = ptr->next) ;
	ptr->next = top;
}

void
add_topic(const char *str)
{
	struct topiclist *ptr, *top;
	char buf[256];
	const char *p;
	char *s;

	if (!str || !*str)
		return;

	p = str;
	s = buf;
	do {
		*s++ = tolower(*p);
	} while (*p++);

	top = (struct topiclist *) malloc(sizeof(struct topiclist));

	top->topic = (char *) string_dup(buf);
	top->section = (char *) string_dup(sect);
	top->printed = 0;

	if (!topichead) {
		topichead = top;
		top->next = NULL;
		return;
	}

	if (strcasecmp(str, topichead->topic) < 0) {
		top->next = topichead;
		topichead = top;
		return;
	}

	ptr = topichead;
	while (ptr->next && strcasecmp(str, ptr->next->topic) > 0) {
		ptr = ptr->next;
	}
	top->next = ptr->next;
	ptr->next = top;
}

char*
escape_html(const char* in, char* buf)
{
	char* out = buf;
	while (*in) {
		if (*in == '<') {
			strcpy(out, "&lt;");
			out += strlen(out);
		} else if (*in == '>') {
			strcpy(out, "&gt;");
			out += strlen(out);
		} else if (*in == '&') {
			strcpy(out, "&amp;");
			out += strlen(out);
		} else if (*in == '"') {
			strcpy(out, "&quot;");
			out += strlen(out);
		} else {
			*out++ = *in;
		}
		in++;
	}
	*out++ = '\0';
	return buf;
}

void
print_section_topics(FILE * f, FILE * hf, const char *whichsect)
{
	struct topiclist *ptr;
	struct topiclist *sptr;
	char sectname[256];
	char *sectptr;
	char *osectptr;
	char *divpos;
	char buf[256];
	char buf2[256];
	char buf3[256];
	int cnt;
	int width;
	int hcol;
	int cols;
	int longest;
	char *currsect;

	longest = 0;
	for (sptr = secthead; sptr; sptr = sptr->next) {
		if (!strncasecmp(whichsect, sptr->section, strlen(whichsect))) {
			currsect = sptr->section;
			for (ptr = topichead; ptr; ptr = ptr->next) {
				if (!strcasecmp(currsect, ptr->section)) {
					divpos = index(ptr->topic, '|');
					if (!divpos) {
						cnt = strlen(ptr->topic);
					} else {
						cnt = divpos - ptr->topic;
					}
					if (cnt > longest) {
						longest = cnt;
					}
				}
			}
		}
	}
	cols = 78 / (longest + 2);
	if (cols < 1) {
		cols = 1;
	}
	width = 78 / cols;
	for (sptr = secthead; sptr; sptr = sptr->next) {
		if (!strncasecmp(whichsect, sptr->section, strlen(whichsect))) {
			currsect = sptr->section;
			cnt = 0;
			hcol = 0;
			buf[0] = '\0';
			strcpy(sectname, currsect);
			sectptr = index(sectname, '|');
			if (sectptr) {
				*sectptr++ = '\0';
				osectptr = sectptr;
				sectptr = rindex(sectptr, '|');
				if (sectptr) {
					sectptr++;
				}
				if (!sectptr) {
					sectptr = osectptr;
				}
			}
			if (!sectptr) {
				sectptr = "";
			}

			fprintf(hf, HTML_SECTION, escape_html(sectptr, buf2), escape_html(sectname, buf3));
			fprintf(f, "~\n~\n%s\n%s\n\n", currsect, sectname);
			fprintf(hf, HTML_SECTIDX_BEGIN);
			for (ptr = topichead; ptr; ptr = ptr->next) {
				if (!strcasecmp(currsect, ptr->section)) {
					ptr->printed++;
					cnt++;
					hcol++;
					if (hcol > cols) {
						fprintf(hf, HTML_SECTIDX_NEWROW);
						hcol = 1;
					}
					escape_html(ptr->topic, buf3);
					fprintf(hf, HTML_SECTIDX_ENTRY, (100 / cols), buf3, buf3);
					if (cnt == cols) {
						snprintf(buf2, sizeof(buf2), "%-0.*s", width - 1, ptr->topic);
					} else {
						snprintf(buf2, sizeof(buf2), "%-*.*s", width, width - 1, ptr->topic);
					}
					strcat(buf, buf2);
					if (cnt >= cols) {
						fprintf(f, "%s\n", buf);
						buf[0] = '\0';
						cnt = 0;
					}
				}
			}
			fprintf(hf, HTML_SECTIDX_END);
			if (cnt)
				fprintf(f, "%s\n", buf);
			fprintf(f, "\n");
		}
	}
}

void
print_all_section_topics(FILE * f, FILE * hf)
{
	struct topiclist *sptr;

	for (sptr = secthead; sptr; sptr = sptr->next) {
		print_section_topics(f, hf, sptr->section);
	}
}

void
print_sections(FILE * f, FILE * hf, int cols)
{
	struct topiclist *ptr;
	struct topiclist *sptr;
	char sectname[256];
	char *osectptr;
	char *sectptr;
	char buf[256];
	char buf2[256];
	char buf3[256];
	char buf4[256];
	int cnt;
	int width;
	int hcol;
	char *currsect;

	fprintf(f, "~\n");
	fprintf(f, "~%s\n", HRULE_TEXT);
	fprintf(f, "~\n");
	fprintf(f, "CATEGORY|CATEGORIES|TOPICS|SECTIONS\n");
	fprintf(f, "                   List of Topics by Category:\n \n");
	fprintf(f, "You can get more help on the following topics:\n \n");
	fprintf(hf, HTML_SECTLIST_HEAD);
	if (cols < 1) {
		cols = 1;
	}
	width = 78 / cols;
	for (sptr = secthead; sptr; sptr = sptr->next) {
		currsect = sptr->section;
		cnt = 0;
		hcol = 0;
		buf[0] = '\0';
		strcpy(sectname, currsect);
		sectptr = index(sectname, '|');
		if (sectptr) {
			*sectptr++ = '\0';
			osectptr = sectptr;
			sectptr = rindex(sectptr, '|');
			if (sectptr) {
				sectptr++;
			}
			if (!sectptr) {
				sectptr = osectptr;
			}
		}
		if (!sectptr) {
			sectptr = "";
		}

		fprintf(hf, HTML_SECTLIST_ENTRY, escape_html(sectptr, buf3), escape_html(sectname, buf4));
		fprintf(f, "  %-40s (%s)\n", sectname, sectptr);
	}
	fprintf(hf, HTML_SECTLIST_FOOT);
	fprintf(f, " \nUse '%s <topicname>' to get more information on a topic.\n", doccmd);
}

void
print_topics(FILE * f, FILE * hf)
{
	struct topiclist *ptr;
	char buf[256];
	char buf2[256];
	char buf3[256];
	char alph;
	char firstletter;
	char *divpos;
	int cnt = 0;
	int width;
	int hcol = 0;
	int cols;
	int len;
	int longest;

	fprintf(hf, HTML_INDEX_BEGIN);
    fprintf(f, "~\n");
	fprintf(f, "~%s\n", HRULE_TEXT);
    fprintf(f, "~\n");
    fprintf(f, "ALPHA|ALPHABETICAL|COMMANDS\n");
    fprintf(f, "                 Alphabetical List of Topics:\n");
    fprintf(f, " \n");
	fprintf(f, "You can get more help on the following topics:\n");
	for (alph = 'A' - 1; alph <= 'Z'; alph++) {
		cnt = 0;
		longest = 0;
		for (ptr = topichead; ptr; ptr = ptr->next) {
			firstletter = toupper(ptr->topic[0]);
			if (firstletter == alph || (!isalpha(alph) && !isalpha(firstletter))) {
				cnt++;
				divpos = index(ptr->topic, '|');
				if (!divpos) {
					len = strlen(ptr->topic);
				} else {
					len = divpos - ptr->topic;
				}
				if (len > longest) {
					longest = len;
				}
			}
		}
		cols = 78 / (longest + 2);
		if (cols < 1) {
			cols = 1;
		}
		width = 78 / cols;

		if (cnt > 0) {
			if (!isalpha(alph)) {
				strcpy(buf, "Symbols");
			} else {
				buf[0] = alph;
				buf[1] = '\'';
				buf[2] = 's';
				buf[3] = '\0';
			}
			fprintf(f, "\n%s\n", buf);
			fprintf(hf, HTML_IDXGROUP_BEGIN, buf);
			buf[0] = '\0';
			cnt = 0;
			hcol = 0;
			for (ptr = topichead; ptr; ptr = ptr->next) {
				firstletter = toupper(ptr->topic[0]);
				if (firstletter == alph || (!isalpha(alph) && !isalpha(firstletter))) {
					cnt++;
					hcol++;
					if (hcol > cols) {
						fprintf(hf, HTML_IDXGROUP_NEWROW);
						hcol = 1;
					}
					escape_html(ptr->topic, buf3);
					fprintf(hf, HTML_IDXGROUP_ENTRY, /*(100 / cols),*/ buf3, buf3);
					if (cnt == cols) {
						snprintf(buf2, sizeof(buf2), "%-0.*s", width - 1, ptr->topic);
					} else {
						snprintf(buf2, sizeof(buf2), "%-*.*s", width, width - 1, ptr->topic);
					}
					strcat(buf, buf2);
					if (cnt >= cols) {
						fprintf(f, "  %s\n", buf);
						buf[0] = '\0';
						cnt = 0;
					}
				}
			}
			if (cnt) {
				fprintf(f, "  %s\n", buf);
			}
			fprintf(hf, HTML_IDXGROUP_END);
		}
	}
	fprintf(hf, HTML_INDEX_END);
	fprintf(f, " \nUse '%s <topicname>' to get more information on a topic.\n", doccmd);
}

int
find_topics(FILE * infile)
{
	char buf[4096];
	char *s, *p;
	int longest, lng;

	longest = 0;
	while (!feof(infile)) {
		do {
			if (!fgets(buf, sizeof(buf), infile)) {
				*buf = '\0';
				break;
			} else {
				if (!strncmp(buf, "~~section ", 10)) {
					buf[strlen(buf) - 1] = '\0';
					strcpy(sect, (buf + 10));
					add_section(sect);
				} else if (!strncmp(buf, "~~title ", 8)) {
					buf[strlen(buf) - 1] = '\0';
					title = string_dup(buf+8);
				} else if (!strncmp(buf, "~~author ", 9)) {
					buf[strlen(buf) - 1] = '\0';
					author = string_dup(buf+9);
				} else if (!strncmp(buf, "~~doccmd ", 9)) {
					buf[strlen(buf) - 1] = '\0';
					doccmd = string_dup(buf+9);
				}
			}
		} while (!feof(infile) &&
				 (*buf != '~' || buf[1] == '@' || buf[1] == '~' || buf[1] == '<' ||
				  buf[1] == '!'));

		do {
			if (!fgets(buf, sizeof(buf), infile)) {
				*buf = '\0';
				break;
			} else {
				if (!strncmp(buf, "~~section ", 10)) {
					buf[strlen(buf) - 1] = '\0';
					strcpy(sect, (buf + 10));
					add_section(sect);
				} else if (!strncmp(buf, "~~title ", 8)) {
					buf[strlen(buf) - 1] = '\0';
					title = string_dup(buf+8);
				} else if (!strncmp(buf, "~~author ", 9)) {
					buf[strlen(buf) - 1] = '\0';
					author = string_dup(buf+9);
				} else if (!strncmp(buf, "~~doccmd ", 9)) {
					buf[strlen(buf) - 1] = '\0';
					doccmd = string_dup(buf+9);
				}
			}
		} while (*buf == '~' && !feof(infile));

		for (s = p = buf; *s; s++) {
			if (*s == '|' || *s == '\n') {
				*s++ = '\0';
				add_topic(p);
				lng = strlen(p);
				if (lng > longest)
					longest = lng;
				p = s;
				break;
			}
		}
	}
	return (longest);
}


void
process_lines(FILE * infile, FILE * outfile, FILE * htmlfile, int cols)
{
	FILE *docsfile;
	char *sectptr;
	char buf[4096];
	char buf2[4096];
	char buf3[4096];
	char buf4[4096];
	int nukenext = 0;
	int topichead = 0;
	int codeblock = 0;
	char *ptr;
	char *ptr2;
	char *ptr3;

	docsfile = stdout;
	escape_html(title, buf);
	escape_html(author, buf2);
	fprintf(htmlfile, HTML_PAGE_HEAD, buf, buf, buf2);

	fprintf(outfile, "%*s%s\n", (36-(strlen(title)/2)), "", title);
	fprintf(outfile, "%*sby %s\n\n", (36-((strlen(author)+3)/2)), "", author);
	fprintf(outfile, "You may get a listing of topics that you can get help on, either sorted\n");
	fprintf(outfile, "Alphabetically or sorted by Category.  To get these lists, type:\n");
	fprintf(outfile, "        %s alpha        or\n", doccmd);
	fprintf(outfile, "        %s category\n\n", doccmd);

	while (!feof(infile)) {
		if (!fgets(buf, sizeof(buf), infile)) {
			break;
		}
		if (buf[0] == '~') {
			if (buf[1] == '~') {
				if (!strncmp(buf, "~~file ", 7)) {
					fclose(docsfile);
					buf[strlen(buf) - 1] = '\0';
					if (!(docsfile = fopen(buf + 7, "w"))) {
						fprintf(stderr, "Error: can't write to %s", buf + 7);
						exit(1);
					}
					fprintf(docsfile,  "%*s%s\n", (36-(strlen(title)/2)), "", title);
					fprintf(docsfile,  "%*sby %s\n\n", (36-((strlen(author)+3)/2)), "", author);
				} else if (!strncmp(buf, "~~section ", 10)) {
					buf[strlen(buf) - 1] = '\0';
					sectptr = index(buf + 10, '|');
					if (sectptr) {
						*sectptr = '\0';
					}
					fprintf(outfile, "~\n~\n~%s\n", HRULE_TEXT);
					fprintf(docsfile, "\n\n%s\n", HRULE_TEXT);
					fprintf(docsfile, "%*s\n", (38 + strlen(buf + 10) / 2), (buf + 10));
					print_section_topics(outfile, htmlfile, (buf + 10));
					fprintf(outfile, "~%s\n~\n~\n", HRULE_TEXT);
					fprintf(docsfile, "%s\n\n\n", HRULE_TEXT);
				} else if (!strncmp(buf, "~~alsosee ", 10)) {
					buf[strlen(buf) - 1] = '\0';
					fprintf(htmlfile, HTML_ALSOSEE_BEGIN);
					fprintf(outfile, "Also see: ");
					ptr = buf + 10;
					while (*ptr && isspace(*ptr))
						ptr++;
					while (ptr && *ptr) {
						ptr2 = ptr;
						ptr = index(ptr, ',');
						if (ptr) {
							*ptr++ = '\0';
							while (*ptr && isspace(*ptr))
								ptr++;
						}
						if (ptr2 > buf + 10) {
							if (!ptr || !*ptr) {
								fprintf(htmlfile, " and\n");
								fprintf(outfile, " and ");
							} else {
								fprintf(htmlfile, ",\n");
								fprintf(outfile, ", ");
							}
						}
						escape_html(ptr2, buf3);
						strcpy(buf4, buf3);
						for (ptr3 = buf4; *ptr3; ptr3++) {
							*ptr3 = tolower(*ptr3);
						}
						fprintf(htmlfile, HTML_ALSOSEE_ENTRY, buf4, buf3);
						fprintf(outfile, "%s", ptr2);
					}
					fprintf(htmlfile, HTML_ALSOSEE_END);
					fprintf(outfile, "\n");
				} else if (!strcmp(buf, "~~code\n")) {
					fprintf(htmlfile, HTML_CODEBEGIN);
					codeblock = 1;
				} else if (!strcmp(buf, "~~endcode\n")) {
					fprintf(htmlfile, HTML_CODEEND);
					codeblock = 0;
				} else if (!strcmp(buf, "~~sectlist\n")) {
					print_sections(outfile, htmlfile, cols);
				} else if (!strcmp(buf, "~~secttopics\n")) {
					/* print_all_section_topics(outfile, htmlfile); */
				} else if (!strcmp(buf, "~~index\n")) {
					print_topics(outfile, htmlfile);
				}
			} else if (buf[1] == '!') {
				fprintf(outfile, "%s", buf + 2);
			} else if (buf[1] == '@') {
				escape_html(buf + 2, buf3);
				fprintf(htmlfile, "%s", buf3);
			} else if (buf[1] == '<') {
				fprintf(outfile, "%s", buf + 2);
				fprintf(docsfile, "%s", buf + 2);
			} else if (buf[1] == '#') {
				fprintf(outfile, "~%s", buf + 2);
				fprintf(docsfile, "%s", buf + 2);
			} else {
				if (!nukenext) {
					fprintf(htmlfile, HTML_TOPICEND);
				}
				nukenext = 1;
				fprintf(outfile, "%s", buf);
				fprintf(docsfile, "%s", buf + 1);
				escape_html(buf + 1, buf3);
				fprintf(htmlfile, "%s", buf3);
			}
		} else if (nukenext) {
			nukenext = 0;
			topichead = 1;
			fprintf(outfile, "%s", buf);
			for (ptr = buf; *ptr && *ptr != '|' && *ptr != '\n'; ptr++) {
				*ptr = tolower(*ptr);
			}
			*ptr = '\0';
			escape_html(buf, buf3);
			fprintf(htmlfile, HTML_TOPICHEAD, buf3);
		} else if (buf[0] == ' ') {
			nukenext = 0;
			if (topichead) {
				topichead = 0;
				fprintf(htmlfile, HTML_TOPICBODY);
			} else if (!codeblock) {
				fprintf(htmlfile, HTML_PARAGRAPH);
			}
			fprintf(outfile, "%s", buf);
			fprintf(docsfile, "%s", buf);
			escape_html(buf, buf3);
			fprintf(htmlfile, "%s", buf3);
		} else {
			fprintf(outfile, "%s", buf);
			fprintf(docsfile, "%s", buf);
			escape_html(buf, buf3);
			fprintf(htmlfile, "%s", buf3);
			if (topichead) {
				fprintf(htmlfile, HTML_TOPICHEAD_BREAK);
			}
		}
	}
	fprintf(htmlfile, HTML_PAGE_FOOT);
	fclose(docsfile);
}


int
main(int argc, char **argv)
{
	FILE *infile, *outfile, *htmlfile;
	int cols;

	if (argc != 4) {
		fprintf(stderr, "Usage: %s inputrawfile outputhelpfile outputhtmlfile\n", argv[0]);
		return 1;
	}

	if (!strcmp(argv[1], argv[2])) {
		fprintf(stderr, "%s: cannot use same file for input rawfile and output helpfile\n");
		return 1;
	}

	if (!strcmp(argv[1], argv[3])) {
		fprintf(stderr, "%s: cannot use same file for input rawfile and output htmlfile\n");
		return 1;
	}

	if (!strcmp(argv[3], argv[2])) {
		fprintf(stderr, "%s: cannot use same file for htmlfile and helpfile\n");
		return 1;
	}

	if (!strcmp(argv[1], "-")) {
		infile = stdin;
	} else {
		if (!(infile = fopen(argv[1], "r"))) {
			fprintf(stderr, "%s: cannot read %s\n", argv[0], argv[1]);
			return 1;
		}
	}

	if (!(outfile = fopen(argv[2], "w"))) {
		fprintf(stderr, "%s: cannot write to %s\n", argv[0], argv[2]);
		return 1;
	}

	if (!(htmlfile = fopen(argv[3], "w"))) {
		fprintf(stderr, "%s: cannot write to %s\n", argv[0], argv[3]);
		return 1;
	}

	cols = 78 / (find_topics(infile) + 1);
	fseek(infile, 0L, 0);

	process_lines(infile, outfile, htmlfile, cols);

	fclose(infile);
	fclose(outfile);
	fclose(htmlfile);
	return 0;
}