X-Git-Url: https://git.distorted.org.uk/~mdw/fwd/blobdiff_plain/61e3dbdf67c571ec4973ab19475ced6a438ab8df..096c89c34505cadba1fc6e7a5367273d5c5bea47:/conf.c diff --git a/conf.c b/conf.c index 020df7a..70b6506 100644 --- a/conf.c +++ b/conf.c @@ -1,72 +1,50 @@ /* -*-c-*- * - * $Id: conf.c,v 1.2 1999/07/26 23:28:39 mdw Exp $ - * * Configuration parsing * * (c) 1999 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * - * This file is part of the `fw' port forwarder. + * This file is part of the `fwd' port forwarder. * - * `fw' is free software; you can redistribute it and/or modify + * `fwd' is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * - * `fw' is distributed in the hope that it will be useful, + * + * `fwd' is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with `fw'; if not, write to the Free Software Foundation, + * along with `fwd'; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* +#include "fwd.h" + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @conf_undelim@ --- * * - * $Log: conf.c,v $ - * Revision 1.2 1999/07/26 23:28:39 mdw - * Major reconstruction work for new design. + * Arguments: @scanner *sc@ = pointer to scanner definition + * @const char *d, *dd@ = pointer to characters to escape * - * Revision 1.1.1.1 1999/07/01 08:56:23 mdw - * Initial revision. + * Returns: --- * + * Use: Modifies the tokenizer. Characters in the first list will + * always be considered to begin a word. Characters in the + * second list will always be allowed to continue a word. */ -/*----- Header files ------------------------------------------------------*/ - -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#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 }; -static target_ops *targets[] = { &xtarget_ops, &ftarget_ops, &starget_ops }; - -/*----- Main code ---------------------------------------------------------*/ +void conf_undelim(scanner *sc, const char *d, const char *dd) +{ + sc->wbegin = d; + sc->wcont = dd; +} /* --- @token@ --- * * @@ -97,13 +75,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) { @@ -122,10 +100,12 @@ int token(scanner *sc) /* --- Various self-delimiting characters --- */ case SELFDELIM: - dstr_putc(&sc->d, ch); - dstr_putz(&sc->d); - sc->t = ch; - goto done; + if (!sc->wbegin || strchr(sc->wbegin, ch) == 0) { + dstr_putc(&sc->d, ch); + dstr_putz(&sc->d); + sc->t = ch; + goto done; + } /* --- Bare words --- * * @@ -150,11 +130,11 @@ int token(scanner *sc) q = !q; break; case SELFDELIM: - if (q) + 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); @@ -172,7 +152,6 @@ int token(scanner *sc) } done: -/* printf("token `%s'\n", sc->d.buf); */ return (sc->t); } @@ -186,7 +165,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; @@ -223,9 +202,15 @@ void error(scanner *sc, const char *msg, ...) * Returns: Index into list, zero-based, or @-1@. * * Use: Checks whether the current token is a string which matches - * one of the comma-separated items given. If not, an error is - * reported; otherwise the index of the matched item is - * returned. + * one of the comma-separated items given. The return value is + * the index (zero-based) of the matched string in the list. + * + * The flags control the behaviour if no exact match is found. + * If @ENUM_ABBREV@ is set, and the current token is a left + * substring of exactly one of the possibilities, then that one + * is chosen. If @ENUM_NONE@ is set, the value @-1@ is + * returned; otherwise an error is reported and the program is + * terminated. */ int conf_enum(scanner *sc, const char *list, unsigned f, const char *err) @@ -339,16 +324,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 --- */ @@ -380,171 +364,27 @@ void conf_name(scanner *sc, char delim, dstr *d) error(sc, "parse error, missing `]'"); } DPUTZ(d); + +#undef f_ok +#undef f_bra } -/* --- @conf_parse@ --- * +/* --- @conf_fname@ --- * * - * Arguments: @scanner *sc@ = pointer to scanner definition + * Arguments: @scanner *sc@ = pointer to scanner + * @dstr *d@ = pointer to dynamic string for output * * Returns: --- * - * Use: Parses a configuration file from the scanner. + * Use: Reads a file name from the input and stores it in @d@. */ -void conf_parse(scanner *sc) +void conf_fname(scanner *sc, dstr *d) { - 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); - } + const char fnchars[] = ".-+"; + conf_undelim(sc, fnchars, fnchars); + conf_name(sc, '/', d); + conf_undelim(sc, 0, 0); } /*----- That's all, folks -------------------------------------------------*/