diff helpgen/helpgen.c @ 0:13d2b8934445

Import AnaGram (near-)release tree into Mercurial.
author David A. Holland
date Sat, 22 Dec 2007 17:52:45 -0500
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/helpgen/helpgen.c	Sat Dec 22 17:52:45 2007 -0500
@@ -0,0 +1,147 @@
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils.h"
+#include "topic.h"
+#include "helpgen.h"
+
+
+#define MAXTOPICS 512
+#define MAXTOTTITLES (MAXTOPICS*4)
+
+static struct topic *topics[MAXTOPICS];
+static int ntopics;
+
+void help_addtopic(struct topic *t) {
+  if (ntopics >= MAXTOPICS) {
+    fprintf(stderr, "Too many help topics (increase MAXTOPICS)\n");
+    exit(1);
+  }
+  topics[ntopics++] = t;
+}
+
+////////////////////////////////////////////////////////////
+
+static int titlesort(const void *av, const void *bv) {
+  const char *a = *(const char *const *)av;
+  const char *b = *(const char *const *)bv;
+  return strcasecmp(a, b);
+}
+
+static int titlefind(const void *av, const void *bv) {
+  const char *a = (const char *)av;
+  const char *b = *(const char *const *)bv;
+  return strcasecmp(a, b);
+}
+
+static void checkxrefs(void) {
+  // check for dangling xrefs and duplicate titles
+
+  const char *alltitles[MAXTOTTITLES];
+  int ntitles = 0;
+
+  int i, j, n;
+  int bad = 0;
+
+  for (i=0; i<ntopics; i++) {
+    n = topic_getnumtitles(topics[i]);
+    for (j=0; j<n; j++) {
+      if (ntitles >= MAXTOTTITLES) {
+	fprintf(stderr, "MAXTOTTITLES too small\n");
+	exit(1);
+      }
+      alltitles[ntitles++] = topic_gettitle(topics[i], j);
+    }
+  }
+
+  qsort(alltitles, ntitles, sizeof(alltitles[0]), titlesort);
+
+  // check for dups
+  for (i=1; i<ntitles; i++) {
+    if (!strcasecmp(alltitles[i], alltitles[i-1])) {
+      fprintf(stderr, "Duplicate title %s\n", alltitles[i]);
+      bad = 1;
+    }
+  }
+
+  // check refs
+  for (i=0; i<ntopics; i++) {
+    n = topic_getnumrefs(topics[i]);
+    for (j=0; j<n; j++) {
+      const char *ref;
+      const void *result;
+
+      ref = topic_getref(topics[i], j);
+      result = bsearch(ref, alltitles, ntitles, sizeof(alltitles[0]),
+		       titlefind);
+      if (!result) {
+	char *ref2;
+	size_t reflen;
+
+	reflen = strlen(ref);
+	ref2 = dostrdup(ref);
+	if (reflen > 0 && ref2[reflen-1]=='s') {
+	  ref2[reflen-1] = 0;
+	  result = bsearch(ref2, alltitles, ntitles, sizeof(alltitles[0]),
+			   titlefind);
+	}
+	free(ref2);
+      }
+
+      if (!result) {
+	fprintf(stderr, "Dangling crossreference %s from %s\n", ref,
+		topic_gettitle(topics[i], 0));
+	bad = 1;
+      }
+    }
+  }
+
+  if (bad) {
+    exit(1);
+  }
+}
+
+////////////////////////////////////////////////////////////
+
+static void usage(const char *av0) {
+  fprintf(stderr, "usage: %s [-t type] infile outfile\n", av0);
+  fprintf(stderr, "   type may be: c html\n");
+  exit(1);
+}
+
+int main(int argc, char *argv[]) {
+  void (*outfunc)(const char *, struct topic **, int);
+  const char *outputtype = "c";
+  int ch;
+
+  while ((ch = getopt(argc, argv, "t:"))!=-1) {
+    switch (ch) {
+      case 't': outputtype = optarg; break;
+      default: usage(argv[0]); break;
+    }
+  }
+  if (optind != argc-2) {
+    usage(argv[0]);
+  }
+
+  const char *infile = argv[optind++];
+  const char *outfile = argv[optind++];
+
+  if (!strcmp(outputtype, "c")) {
+    outfunc = cout;
+  }
+  else if (!strcmp(outputtype, "html")) {
+    outfunc = htmlout;
+  }
+  else {
+    usage(argv[0]);
+  }
+
+  load(infile);
+  checkxrefs();
+  outfunc(outfile, topics, ntopics);
+
+  return 0;
+}