Mercurial > ~dholland > hg > ag > index.cgi
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; +}