comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:13d2b8934445
1 #include <getopt.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include "utils.h"
7 #include "topic.h"
8 #include "helpgen.h"
9
10
11 #define MAXTOPICS 512
12 #define MAXTOTTITLES (MAXTOPICS*4)
13
14 static struct topic *topics[MAXTOPICS];
15 static int ntopics;
16
17 void help_addtopic(struct topic *t) {
18 if (ntopics >= MAXTOPICS) {
19 fprintf(stderr, "Too many help topics (increase MAXTOPICS)\n");
20 exit(1);
21 }
22 topics[ntopics++] = t;
23 }
24
25 ////////////////////////////////////////////////////////////
26
27 static int titlesort(const void *av, const void *bv) {
28 const char *a = *(const char *const *)av;
29 const char *b = *(const char *const *)bv;
30 return strcasecmp(a, b);
31 }
32
33 static int titlefind(const void *av, const void *bv) {
34 const char *a = (const char *)av;
35 const char *b = *(const char *const *)bv;
36 return strcasecmp(a, b);
37 }
38
39 static void checkxrefs(void) {
40 // check for dangling xrefs and duplicate titles
41
42 const char *alltitles[MAXTOTTITLES];
43 int ntitles = 0;
44
45 int i, j, n;
46 int bad = 0;
47
48 for (i=0; i<ntopics; i++) {
49 n = topic_getnumtitles(topics[i]);
50 for (j=0; j<n; j++) {
51 if (ntitles >= MAXTOTTITLES) {
52 fprintf(stderr, "MAXTOTTITLES too small\n");
53 exit(1);
54 }
55 alltitles[ntitles++] = topic_gettitle(topics[i], j);
56 }
57 }
58
59 qsort(alltitles, ntitles, sizeof(alltitles[0]), titlesort);
60
61 // check for dups
62 for (i=1; i<ntitles; i++) {
63 if (!strcasecmp(alltitles[i], alltitles[i-1])) {
64 fprintf(stderr, "Duplicate title %s\n", alltitles[i]);
65 bad = 1;
66 }
67 }
68
69 // check refs
70 for (i=0; i<ntopics; i++) {
71 n = topic_getnumrefs(topics[i]);
72 for (j=0; j<n; j++) {
73 const char *ref;
74 const void *result;
75
76 ref = topic_getref(topics[i], j);
77 result = bsearch(ref, alltitles, ntitles, sizeof(alltitles[0]),
78 titlefind);
79 if (!result) {
80 char *ref2;
81 size_t reflen;
82
83 reflen = strlen(ref);
84 ref2 = dostrdup(ref);
85 if (reflen > 0 && ref2[reflen-1]=='s') {
86 ref2[reflen-1] = 0;
87 result = bsearch(ref2, alltitles, ntitles, sizeof(alltitles[0]),
88 titlefind);
89 }
90 free(ref2);
91 }
92
93 if (!result) {
94 fprintf(stderr, "Dangling crossreference %s from %s\n", ref,
95 topic_gettitle(topics[i], 0));
96 bad = 1;
97 }
98 }
99 }
100
101 if (bad) {
102 exit(1);
103 }
104 }
105
106 ////////////////////////////////////////////////////////////
107
108 static void usage(const char *av0) {
109 fprintf(stderr, "usage: %s [-t type] infile outfile\n", av0);
110 fprintf(stderr, " type may be: c html\n");
111 exit(1);
112 }
113
114 int main(int argc, char *argv[]) {
115 void (*outfunc)(const char *, struct topic **, int);
116 const char *outputtype = "c";
117 int ch;
118
119 while ((ch = getopt(argc, argv, "t:"))!=-1) {
120 switch (ch) {
121 case 't': outputtype = optarg; break;
122 default: usage(argv[0]); break;
123 }
124 }
125 if (optind != argc-2) {
126 usage(argv[0]);
127 }
128
129 const char *infile = argv[optind++];
130 const char *outfile = argv[optind++];
131
132 if (!strcmp(outputtype, "c")) {
133 outfunc = cout;
134 }
135 else if (!strcmp(outputtype, "html")) {
136 outfunc = htmlout;
137 }
138 else {
139 usage(argv[0]);
140 }
141
142 load(infile);
143 checkxrefs();
144 outfunc(outfile, topics, ntopics);
145
146 return 0;
147 }