* main.c: command line parsing and top level
*/
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "halibut.h"
static void dbg_prtwordlist(int level, word *w);
static void dbg_prtkws(keywordlist *kws);
+static const struct pre_backend {
+ void *(*func)(paragraph *, keywordlist *, indexdata *);
+ int bitfield;
+} pre_backends[] = {
+ {paper_pre_backend, 0x0001}
+};
+
+static const struct backend {
+ char *name;
+ void (*func)(paragraph *, keywordlist *, indexdata *, void *);
+ paragraph *(*filename)(char *filename);
+ int bitfield, prebackend_bitfield;
+} backends[] = {
+ {"text", text_backend, text_config_filename, 0x0001, 0},
+ {"xhtml", xhtml_backend, xhtml_config_filename, 0x0002, 0},
+ {"html", xhtml_backend, xhtml_config_filename, 0x0002, 0},
+ {"hlp", whlp_backend, whlp_config_filename, 0x0004, 0},
+ {"whlp", whlp_backend, whlp_config_filename, 0x0004, 0},
+ {"winhelp", whlp_backend, whlp_config_filename, 0x0004, 0},
+ {"man", man_backend, man_config_filename, 0x0008, 0},
+ {"info", info_backend, info_config_filename, 0x0010, 0},
+ {"ps", ps_backend, ps_config_filename, 0x0020, 0x0001},
+ {"pdf", pdf_backend, pdf_config_filename, 0x0040, 0x0001},
+};
+
int main(int argc, char **argv) {
char **infiles;
- char *outfile;
int nfiles;
int nogo;
int errs;
int reportcols;
int debug;
+ int backendbits, prebackbits;
+ int k, b;
+ paragraph *cfg, *cfg_tail;
+ void *pre_backend_data[16];
/*
* Set up initial (default) parameters.
*/
infiles = mknewa(char *, argc);
- outfile = NULL;
nfiles = 0;
nogo = errs = FALSE;
reportcols = 0;
debug = 0;
+ backendbits = 0;
+ cfg = cfg_tail = NULL;
if (argc == 1) {
usage();
val = p;
} else
val = NULL;
- if (!strcmp(opt, "-help")) {
+
+ assert(opt[0] == '-');
+ for (k = 0; k < (int)lenof(backends); k++)
+ if (!strcmp(opt+1, backends[k].name)) {
+ backendbits |= backends[k].bitfield;
+ if (val) {
+ paragraph *p = backends[k].filename(val);
+ assert(p);
+ if (cfg_tail)
+ cfg_tail->next = p;
+ else
+ cfg = p;
+ while (p->next)
+ p = p->next;
+ cfg_tail = p;
+ }
+ break;
+ }
+ if (k < (int)lenof(backends)) {
+ /* do nothing */;
+ } else if (!strcmp(opt, "-help")) {
help();
nogo = TRUE;
} else if (!strcmp(opt, "-version")) {
!strcmp(opt, "-license")) {
licence();
nogo = TRUE;
- } else if (!strcmp(opt, "-output")) {
- if (!val)
- errs = TRUE, error(err_optnoarg, opt);
- else
- outfile = val;
} else if (!strcmp(opt, "-precise")) {
reportcols = 1;
} else {
break;
}
break;
- case 'o':
+ case 'C':
/*
* Option requiring parameter.
*/
* Now c is the option and p is the parameter.
*/
switch (c) {
- case 'o':
- outfile = p;
+ case 'C':
+ /*
+ * -C means we split our argument up into
+ * colon-separated chunks and assemble them
+ * into a config paragraph.
+ */
+ {
+ wchar_t *keywords;
+ char *q;
+ wchar_t *u;
+ paragraph *para;
+
+ keywords = mknewa(wchar_t, 2+strlen(p));
+
+ u = keywords;
+ q = p;
+
+ while (*q) {
+ if (*q == ':') {
+ *u++ = L'\0';
+ } else {
+ if (*q == '\\' && q[1])
+ q++;
+ /* FIXME: lacks charset flexibility */
+ *u++ = *q;
+ }
+ q++;
+ }
+ *u = L'\0';
+
+ para = mknew(paragraph);
+ memset(para, 0, sizeof(*para));
+ para->type = para_Config;
+ para->keyword = keywords;
+ para->next = NULL;
+ para->fpos.filename = "<command line>";
+ para->fpos.line = para->fpos.col = -1;
+
+ if (cfg_tail)
+ cfg_tail->next = para;
+ else
+ cfg = para;
+ cfg_tail = para;
+ }
break;
}
p = NULL; /* prevent continued processing */
in.pushback = NULL;
in.reportcols = reportcols;
in.stack = NULL;
+ in.defcharset = CS_ASCII;
idx = make_index();
if (!sourceform)
exit(EXIT_FAILURE);
+ /*
+ * Append the config directives acquired from the command
+ * line.
+ */
+ {
+ paragraph *end;
+
+ end = sourceform;
+ while (end && end->next)
+ end = end->next;
+ assert(end);
+
+ end->next = cfg;
+ }
+
sfree(in.pushback);
mark_attr_ends(sourceform);
for (p = sourceform; p; p = p->next)
if (p->type == para_IM)
- index_merge(idx, TRUE, p->keyword, p->words);
+ index_merge(idx, TRUE, p->keyword, p->words, &p->fpos);
build_index(idx);
dbg_prtsource(sourceform);
}
- text_backend(sourceform, keywords, idx);
- xhtml_backend(sourceform, keywords, idx);
- whlp_backend(sourceform, keywords, idx);
- man_backend(sourceform, keywords, idx);
+ /*
+ * Select and run the pre-backends.
+ */
+ prebackbits = 0;
+ for (k = 0; k < (int)lenof(backends); k++)
+ if (backendbits == 0 || (backendbits & backends[k].bitfield))
+ prebackbits |= backends[k].prebackend_bitfield;
+ for (k = 0; k < (int)lenof(pre_backends); k++)
+ if (prebackbits & pre_backends[k].bitfield) {
+ assert(k < (int)lenof(pre_backend_data));
+ pre_backend_data[k] =
+ pre_backends[k].func(sourceform, keywords, idx);
+ }
+
+ /*
+ * Run the selected set of backends.
+ */
+ for (k = b = 0; k < (int)lenof(backends); k++)
+ if (b != backends[k].bitfield) {
+ b = backends[k].bitfield;
+ if (backendbits == 0 || (backendbits & b)) {
+ void *pbd = NULL;
+ int pbb = backends[k].prebackend_bitfield;
+ int m;
+
+ for (m = 0; m < (int)lenof(pre_backends); m++)
+ if (pbb & pre_backends[m].bitfield) {
+ assert(m < (int)lenof(pre_backend_data));
+ pbd = pre_backend_data[m];
+ break;
+ }
+
+ backends[k].func(sourceform, keywords, idx, pbd);
+ }
+ }
free_para_list(sourceform);
free_keywords(keywords);