Make a start on command-line options. Here I introduce --text,
[sgt/halibut] / main.c
CommitLineData
d7482997 1/*
2 * main.c: command line parsing and top level
3 */
4
c8fb54d2 5#include <assert.h>
d7482997 6#include <stdio.h>
7#include <stdlib.h>
8#include "halibut.h"
9
10static void dbg_prtsource(paragraph *sourceform);
11static void dbg_prtwordlist(int level, word *w);
12static void dbg_prtkws(keywordlist *kws);
13
c8fb54d2 14static const struct backend {
15 char *name;
16 void (*func)(paragraph *, keywordlist *, indexdata *);
17 int bitfield;
18} backends[] = {
19 {"text", text_backend, 0x0001},
20 {"xhtml", xhtml_backend, 0x0002},
21 {"html", xhtml_backend, 0x0002},
22 {"hlp", whlp_backend, 0x0004},
23 {"whlp", whlp_backend, 0x0004},
24 {"winhelp", whlp_backend, 0x0004},
25 {"man", man_backend, 0x0008},
26};
27
d7482997 28int main(int argc, char **argv) {
29 char **infiles;
d7482997 30 int nfiles;
31 int nogo;
32 int errs;
33 int reportcols;
34 int debug;
c8fb54d2 35 int backendbits;
36 int k, b;
d7482997 37
38 /*
39 * Set up initial (default) parameters.
40 */
41 infiles = mknewa(char *, argc);
d7482997 42 nfiles = 0;
43 nogo = errs = FALSE;
44 reportcols = 0;
45 debug = 0;
c8fb54d2 46 backendbits = 0;
d7482997 47
48 if (argc == 1) {
49 usage();
50 exit(EXIT_SUCCESS);
51 }
52
53 /*
54 * Parse command line arguments.
55 */
56 while (--argc) {
57 char *p = *++argv;
58 if (*p == '-') {
59 /*
60 * An option.
61 */
62 while (p && *++p) {
63 char c = *p;
64 switch (c) {
65 case '-':
66 /*
67 * Long option.
68 */
69 {
70 char *opt, *val;
71 opt = p++; /* opt will have _one_ leading - */
72 while (*p && *p != '=')
73 p++; /* find end of option */
74 if (*p == '=') {
75 *p++ = '\0';
76 val = p;
77 } else
78 val = NULL;
c8fb54d2 79
80 assert(opt[0] == '-');
81 for (k = 0; k < (int)lenof(backends); k++)
82 if (!strcmp(opt+1, backends[k].name)) {
83 backendbits |= backends[k].bitfield;
84 break;
85 }
86 if (k < (int)lenof(backends)) {
87 /* do nothing */;
88 } else if (!strcmp(opt, "-help")) {
d7482997 89 help();
90 nogo = TRUE;
91 } else if (!strcmp(opt, "-version")) {
92 showversion();
93 nogo = TRUE;
94 } else if (!strcmp(opt, "-licence") ||
95 !strcmp(opt, "-license")) {
96 licence();
97 nogo = TRUE;
d7482997 98 } else if (!strcmp(opt, "-precise")) {
99 reportcols = 1;
100 } else {
101 errs = TRUE, error(err_nosuchopt, opt);
102 }
103 }
104 p = NULL;
105 break;
106 case 'h':
107 case 'V':
108 case 'L':
109 case 'P':
110 case 'd':
111 /*
112 * Option requiring no parameter.
113 */
114 switch (c) {
115 case 'h':
116 help();
117 nogo = TRUE;
118 break;
119 case 'V':
120 showversion();
121 nogo = TRUE;
122 break;
123 case 'L':
124 licence();
125 nogo = TRUE;
126 break;
127 case 'P':
128 reportcols = 1;
129 break;
130 case 'd':
131 debug = TRUE;
132 break;
133 }
134 break;
c8fb54d2 135#if 0
d7482997 136 case 'o':
137 /*
138 * Option requiring parameter.
139 */
140 p++;
141 if (!*p && argc > 1)
142 --argc, p = *++argv;
143 else if (!*p) {
144 char opt[2];
145 opt[0] = c;
146 opt[1] = '\0';
147 errs = TRUE, error(err_optnoarg, opt);
148 }
149 /*
150 * Now c is the option and p is the parameter.
151 */
152 switch (c) {
153 case 'o':
154 outfile = p;
155 break;
156 }
157 p = NULL; /* prevent continued processing */
158 break;
c8fb54d2 159#endif
d7482997 160 default:
161 /*
162 * Unrecognised option.
163 */
164 {
165 char opt[2];
166 opt[0] = c;
167 opt[1] = '\0';
168 errs = TRUE, error(err_nosuchopt, opt);
169 }
170 }
171 }
172 } else {
173 /*
174 * A non-option argument.
175 */
176 infiles[nfiles++] = p;
177 }
178 }
179
180 if (errs)
181 exit(EXIT_FAILURE);
182 if (nogo)
183 exit(EXIT_SUCCESS);
184
185 /*
186 * Do the work.
187 */
188 if (nfiles == 0) {
189 error(err_noinput);
190 usage();
191 exit(EXIT_FAILURE);
192 }
193
194 {
195 input in;
196 paragraph *sourceform, *p;
197 indexdata *idx;
198 keywordlist *keywords;
199
200 in.filenames = infiles;
201 in.nfiles = nfiles;
202 in.currfp = NULL;
203 in.currindex = 0;
204 in.npushback = in.pushbacksize = 0;
205 in.pushback = NULL;
206 in.reportcols = reportcols;
207 in.stack = NULL;
208
209 idx = make_index();
210
211 sourceform = read_input(&in, idx);
212 if (!sourceform)
213 exit(EXIT_FAILURE);
214
215 sfree(in.pushback);
216
217 mark_attr_ends(sourceform);
218
219 sfree(infiles);
220
221 keywords = get_keywords(sourceform);
222 if (!keywords)
223 exit(EXIT_FAILURE);
224 gen_citations(sourceform, keywords);
225 subst_keywords(sourceform, keywords);
226
227 for (p = sourceform; p; p = p->next)
228 if (p->type == para_IM)
229 index_merge(idx, TRUE, p->keyword, p->words);
230
231 build_index(idx);
232
233 if (debug) {
234 index_debug(idx);
235 dbg_prtkws(keywords);
236 dbg_prtsource(sourceform);
237 }
238
c8fb54d2 239 /*
240 * Run the selected set of backends.
241 */
242 for (k = b = 0; k < (int)lenof(backends); k++)
243 if (b != backends[k].bitfield) {
244 b = backends[k].bitfield;
245 if (backendbits == 0 || (backendbits & b))
246 backends[k].func(sourceform, keywords, idx);
247 }
d7482997 248
249 free_para_list(sourceform);
250 free_keywords(keywords);
251 cleanup_index(idx);
252 }
253
254 return 0;
255}
256
257static void dbg_prtsource(paragraph *sourceform) {
258 /*
259 * Output source form in debugging format.
260 */
261
262 paragraph *p;
263 for (p = sourceform; p; p = p->next) {
264 wchar_t *wp;
265 printf("para %d ", p->type);
266 if (p->keyword) {
267 wp = p->keyword;
268 while (*wp) {
269 putchar('\"');
270 for (; *wp; wp++)
271 putchar(*wp);
272 putchar('\"');
273 if (*++wp)
274 printf(", ");
275 }
276 } else
277 printf("(no keyword)");
278 printf(" {\n");
279 dbg_prtwordlist(1, p->words);
280 printf("}\n");
281 }
282}
283
284static void dbg_prtkws(keywordlist *kws) {
285 /*
286 * Output keywords in debugging format.
287 */
288
289 int i;
290 keyword *kw;
291
292 for (i = 0; (kw = index234(kws->keys, i)) != NULL; i++) {
293 wchar_t *wp;
294 printf("keyword ");
295 wp = kw->key;
296 while (*wp) {
297 putchar('\"');
298 for (; *wp; wp++)
299 putchar(*wp);
300 putchar('\"');
301 if (*++wp)
302 printf(", ");
303 }
304 printf(" {\n");
305 dbg_prtwordlist(1, kw->text);
306 printf("}\n");
307 }
308}
309
310static void dbg_prtwordlist(int level, word *w) {
311 for (; w; w = w->next) {
312 wchar_t *wp;
313 printf("%*sword %d ", level*4, "", w->type);
314 if (w->text) {
315 printf("\"");
316 for (wp = w->text; *wp; wp++)
317 putchar(*wp);
318 printf("\"");
319 } else
320 printf("(no text)");
321 if (w->alt) {
322 printf(" alt = {\n");
323 dbg_prtwordlist(level+1, w->alt);
324 printf("%*s}", level*4, "");
325 }
326 printf("\n");
327 }
328}