X-Git-Url: https://git.distorted.org.uk/~mdw/fwd/blobdiff_plain/5835a4a8eb85b9068a8ecefb0826292b6774c071..00e3c0f1bbe99682debd4e34d3d3bd950f8c30cb:/conf.c diff --git a/conf.c b/conf.c index dfc3765..57947ca 100644 --- a/conf.c +++ b/conf.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: conf.c,v 1.6 2000/02/12 18:13:20 mdw Exp $ + * $Id: conf.c,v 1.10 2002/02/22 23:42:56 mdw Exp $ * * Configuration parsing * @@ -29,6 +29,20 @@ /*----- Revision history --------------------------------------------------* * * $Log: conf.c,v $ + * Revision 1.10 2002/02/22 23:42:56 mdw + * `fw'-specific configuration code moved out. This file might become part + * of a library some day. + * + * Revision 1.9 2002/01/13 14:48:16 mdw + * Make delimiters be a property of a scanner. Change the delimiter- + * changing functions' names. + * + * Revision 1.8 2001/02/03 20:33:26 mdw + * Fix flags to be unsigned. + * + * Revision 1.7 2000/08/01 17:58:10 mdw + * Fix subtleties with functions. + * * Revision 1.6 2000/02/12 18:13:20 mdw * Terminate tables of sources and targets. * @@ -52,8 +66,6 @@ /*----- Header files ------------------------------------------------------*/ -#include "config.h" - #include #include #include @@ -67,28 +79,13 @@ #include "conf.h" #include "scan.h" -#include "source.h" -#include "target.h" - -#include "exec.h" -#include "file.h" -#include "socket.h" - -/*----- Source and target tables ------------------------------------------*/ - -static source_ops *sources[] = - { &xsource_ops, &fsource_ops, &ssource_ops, 0 }; -static target_ops *targets[] = - { &xtarget_ops, &ftarget_ops, &starget_ops, 0 }; - -static const char *notword = 0; -static const char *notdelim = 0; /*----- Main code ---------------------------------------------------------*/ -/* --- @undelim@ --- * +/* --- @conf_undelim@ --- * * - * Arguments: @const char *d, dd@ = pointer to characters to escape + * Arguments: @scanner *sc@ = pointer to scanner definition + * @const char *d, *dd@ = pointer to characters to escape * * Returns: --- * @@ -97,7 +94,11 @@ static const char *notdelim = 0; * second list will always be allowed to continue a word. */ -void undelim(const char *d, const char *dd) { notword = d; notdelim = dd; } +void conf_undelim(scanner *sc, const char *d, const char *dd) +{ + sc->wbegin = d; + sc->wcont = dd; +} /* --- @token@ --- * * @@ -128,13 +129,13 @@ int token(scanner *sc) if (sc->head->tok) { dstr_puts(&sc->d, sc->head->tok); - free(sc->head->tok); + xfree(sc->head->tok); sc->head->tok = 0; sc->t = sc->head->t; goto done; } - else if (isspace((unsigned char)ch)) + else if (isspace(ch)) ; else switch (ch) { @@ -153,7 +154,7 @@ int token(scanner *sc) /* --- Various self-delimiting characters --- */ case SELFDELIM: - if (!notword || strchr(notword, ch) == 0) { + if (!sc->wbegin || strchr(sc->wbegin, ch) == 0) { dstr_putc(&sc->d, ch); dstr_putz(&sc->d); sc->t = ch; @@ -183,11 +184,11 @@ int token(scanner *sc) q = !q; break; case SELFDELIM: - if (q || (notdelim && strchr(notdelim, ch))) + if (q || (sc->wcont && strchr(sc->wcont, ch))) goto insert; goto word; default: - if (!q && isspace((unsigned char)(ch))) + if (!q && isspace(ch)) goto word; insert: DPUTC(&sc->d, ch); @@ -218,7 +219,7 @@ done: * to pushing a new scanner source. */ -static void pushback(scanner *sc) +void pushback(scanner *sc) { sc->head->tok = xstrdup(sc->d.buf); sc->head->t = sc->t; @@ -377,16 +378,15 @@ int conf_prefix(scanner *sc, const char *p) void conf_name(scanner *sc, char delim, dstr *d) { unsigned f = 0; - enum { - f_ok = 1, - f_bra = 2 - }; + +#define f_ok 1u +#define f_bra 2u /* --- Read an optional opening bracket --- */ if (sc->t == '[') { token(sc); - f |= f_bra; + f |= f_bra | f_ok; } /* --- Do the main reading sequence --- */ @@ -418,171 +418,9 @@ void conf_name(scanner *sc, char delim, dstr *d) error(sc, "parse error, missing `]'"); } DPUTZ(d); -} - -/* --- @conf_parse@ --- * - * - * Arguments: @scanner *sc@ = pointer to scanner definition - * - * Returns: --- - * - * Use: Parses a configuration file from the scanner. - */ - -void conf_parse(scanner *sc) -{ - token(sc); - - for (;;) { - if (sc->t == CTOK_EOF) - break; - if (sc->t != CTOK_WORD) - error(sc, "parse error, keyword expected"); - - /* --- Handle a forwarding request --- */ - - if (strcmp(sc->d.buf, "forward") == 0 || - strcmp(sc->d.buf, "fw") == 0 || - strcmp(sc->d.buf, "from") == 0) { - source *s; - target *t; - - token(sc); - - /* --- Read a source description --- */ - - { - source_ops **sops; - - /* --- Try to find a source type which understands --- */ - - s = 0; - for (sops = sources; *sops; sops++) { - if ((s = (*sops)->read(sc)) != 0) - goto found_source; - } - error(sc, "unknown source name `%s'", sc->d.buf); - - /* --- Read any source-specific options --- */ - - found_source: - if (sc->t == '{') { - token(sc); - while (sc->t == CTOK_WORD) { - if (!s->ops->option || !s->ops->option(s, sc)) { - error(sc, "unknown %s source option `%s'", - s->ops->name, sc->d.buf); - } - if (sc->t == ';') - token(sc); - } - if (sc->t != '}') - error(sc, "parse error, missing `}'"); - token(sc); - } - } - /* --- Read a destination description --- */ - - if (sc->t == CTOK_WORD && (strcmp(sc->d.buf, "to") == 0 || - strcmp(sc->d.buf, "->") == 0)) - token(sc); - - { - target_ops **tops; - - /* --- Try to find a target which understands --- */ - - t = 0; - for (tops = targets; *tops; tops++) { - if ((t = (*tops)->read(sc)) != 0) - goto found_target; - } - error(sc, "unknown target name `%s'", sc->d.buf); - - /* --- Read any target-specific options --- */ - - found_target: - if (sc->t == '{') { - token(sc); - while (sc->t == CTOK_WORD) { - if (!t->ops->option || !t->ops->option(t, sc)) { - error(sc, "unknown %s target option `%s'", - t->ops->name, sc->d.buf); - } - if (sc->t == ';') - token(sc); - } - if (sc->t != '}') - error(sc, "parse error, `}' expected"); - token(sc); - } - } - - /* --- Combine the source and target --- */ - - s->ops->attach(s, sc, t); - } - - /* --- Include configuration from a file --- * - * - * Slightly tricky. Scan the optional semicolon from the including - * stream, not the included one. - */ - - else if (strcmp(sc->d.buf, "include") == 0) { - FILE *fp; - dstr d = DSTR_INIT; - - token(sc); - conf_name(sc, '/', &d); - if ((fp = fopen(d.buf, "r")) == 0) - error(sc, "can't include `%s': %s", d.buf, strerror(errno)); - if (sc->t == ';') - token(sc); - pushback(sc); - scan_push(sc, scan_file(fp, xstrdup(d.buf), SCF_FREENAME)); - token(sc); - dstr_destroy(&d); - continue; /* Don't parse a trailing `;' */ - } - - /* --- Other configuration is handled elsewhere --- */ - - else { - - /* --- First try among the sources --- */ - - { - source_ops **sops; - - for (sops = sources; *sops; sops++) { - if ((*sops)->option && (*sops)->option(0, sc)) - goto found_option; - } - } - - /* --- Then try among the targets --- */ - - { - target_ops **tops; - - for (tops = targets; *tops; tops++) { - if ((*tops)->option && (*tops)->option(0, sc)) - goto found_option; - } - } - - /* --- Nobody wants the option --- */ - - error(sc, "unknown global option or prefix `%s'", sc->d.buf); - - found_option:; - } - - if (sc->t == ';') - token(sc); - } +#undef f_ok +#undef f_bra } /*----- That's all, folks -------------------------------------------------*/