-/* -*-c-*-
- *
- * Configuration parsing
- *
- * (c) 1999 Straylight/Edgeware
- */
-
-/*----- Licensing notice --------------------------------------------------*
- *
- * This file is part of the `fwd' port forwarder.
- *
- * `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.
- *
- * `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 `fwd'; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef CONF_H
-#define CONF_H
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-/*----- Header files ------------------------------------------------------*/
-
-#include <mLib/dstr.h>
-
-#ifndef SCAN_H
-# include "scan.h"
-#endif
-
-/*----- Magic numbers -----------------------------------------------------*/
-
-#define CTOK_EOF (-1)
-#define CTOK_WORD 256
-
-/*----- Functions provided ------------------------------------------------*/
-
-/* --- @conf_undelim@ --- *
- *
- * Arguments: @scanner *sc@ = pointer to scanner definition
- * @const char *d, *dd@ = pointer to characters to escape
- *
- * 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.
- */
-
-extern void conf_undelim(scanner */*sc*/,
- const char */*d*/, const char */*dd*/);
-
-/* --- @token@ --- *
- *
- * Arguments: @scanner *sc@ = pointer to scanner definition
- *
- * Returns: Type of token scanned.
- *
- * Use: Reads the next token from the character scanner.
- */
-
-extern int token(scanner */*sc*/);
-
-/* --- @error@ --- *
- *
- * Arguments: @scanner *sc@ = pointer to scanner definition
- * @const char *msg@ = message skeleton string
- * @...@ = extra arguments for the skeleton
- *
- * Returns: Doesn't
- *
- * Use: Reports an error at the current scanner location.
- */
-
-extern void error(scanner */*sc*/, const char */*msg*/, ...);
-
-/* --- @pushback@ --- *
- *
- * Arguments: @scanner *sc@ = pointer to scanner definition
- *
- * Returns: ---
- *
- * Use: Pushes the current token back. This is normally a precursor
- * to pushing a new scanner source.
- */
-
-extern void pushback(scanner */*sc*/);
-
-/* --- @conf_enum@ --- *
- *
- * Arguments: @scanner *sc@ = pointer to a scanner object
- * @const char *list@ = comma-separated things to allow
- * @unsigned @f = flags for the search
- * @const char *err@ = error message if not found
- *
- * 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. 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.
- */
-
-#define ENUM_ABBREV 1u
-#define ENUM_NONE 2u
-
-extern int conf_enum(scanner */*sc*/, const char */*list*/,
- unsigned /*flags*/, const char */*err*/);
-
-/* --- @conf_prefix@ --- *
- *
- * Arguments: @scanner *sc@ = pointer to a scanner object
- * @const char *p@ = pointer to prefix string to check
- *
- * Returns: Nonzero if the prefix matches.
- *
- * Use: If the current token is a word matching the given prefix
- * string, then it and an optional `.' character are removed and
- * a nonzero result is returned. Otherwise the current token is
- * left as it is, and zero is returned.
- *
- * Typical options parsing code would remove an expected prefix,
- * scan an option anyway (since qualifying prefixes are
- * optional) and if a match is found, claim the option. If no
- * match is found, and a prefix was stripped, then an error
- * should be reported.
- */
-
-extern int conf_prefix(scanner */*sc*/, const char */*p*/);
-
-/* --- @CONF_BEGIN@, @CONF_END@ --- *
- *
- * Arguments: @sc@ = scanner to read from
- * @prefix@ = prefix to scan for
- * @desc@ = description of what we're parsing
- *
- * Use: Bracket an options parsing routine. The current token is
- * checked to see whether it matches the prefix. If so, it is
- * removed and the following token examined. If that's a `.'
- * then it's removed. If it's a `{' then the enclosed
- * option-parsing code is executed in a loop until a matching
- * '}' is found. If the options parser doesn't accept an
- * option, the behaviour is dependent on whether a prefix was
- * seen: if so, an error is reported; otherwse a zero return is
- * made.
- */
-
-#define CS_PLAIN 0
-#define CS_PREFIX 1
-#define CS_BRACE 2
-#define CS_UNKNOWN 3
-
-#define CONF_BEGIN(sc, prefix, desc) do { \
- scanner *_conf_sc = (sc); \
- const char *_conf_desc = (desc); \
- int _conf_state = CS_PLAIN; \
- \
- /* --- Read the initial prefix --- */ \
- \
- if (_conf_sc->t == CTOK_WORD && \
- strcmp(_conf_sc->d.buf, (prefix)) == 0) { \
- token(_conf_sc); \
- _conf_state = CS_PREFIX; \
- if (_conf_sc->t == '.') \
- token(_conf_sc); \
- else if (_conf_sc->t == '{') { \
- token(_conf_sc); \
- _conf_state = CS_BRACE; \
- } \
- } \
- \
- /* --- Ensure the next token is a word --- */ \
- \
- if (_conf_sc->t != CTOK_WORD) \
- error(_conf_sc, "parse error, expected option keyword"); \
- do {
-
-#define CONF_END \
- \
- /* --- Reject an option --- * \
- * \
- * We could get here as a result of an explicit @CONF_REJECT@ or \
- * because the option wasn't accepted. \
- */ \
- \
- goto _conf_reject; \
- _conf_reject: \
- if (_conf_state == CS_PLAIN) \
- _conf_state = CS_UNKNOWN; \
- else { \
- error(_conf_sc, "unknown %s option `%s'", \
- _conf_desc, _conf_sc->d.buf); \
- } \
- \
- /* --- Accept an option --- * \
- * \
- * It's safe to drop through from above. Either an error will have \
- * been reported, or the state is not @CS_BRACE@. \
- */ \
- \
- _conf_accept: \
- if (_conf_state == CS_BRACE && _conf_sc->t == ';') \
- token(_conf_sc); \
- } while (_conf_state == CS_BRACE && _conf_sc->t == CTOK_WORD); \
- \
- /* --- Check for a closing brace --- */ \
- \
- if (_conf_state == CS_BRACE) { \
- if (_conf_sc->t == '}') \
- token(_conf_sc); \
- else \
- error(_conf_sc, "parse error, expected `}'"); \
- } \
- \
- /* --- Return an appropriate value --- */ \
- \
- return (_conf_state != CS_UNKNOWN); \
-} while (0)
-
-/* --- @CONF_ACCEPT@, @CONF_REJECT@ --- *
- *
- * Arguments: ---
- *
- * Use: Within an options parser (between @CONF_BEGIN@ and
- * @CONF_END@), accept or reject an option.
- */
-
-#define CONF_ACCEPT goto _conf_accept
-#define CONF_REJECT goto _conf_reject
-
-/* --- @CONF_QUAL@ --- *
- *
- * Arguments: ---
- *
- * Use: Evaluates to a nonzero value if the current option is
- * qualified. This can be used to decide whether abbreviations
- * for options should be accepted.
- */
-
-#define CONF_QUAL (_conf_state != CS_PLAIN)
-
-/* --- @conf_name@ --- *
- *
- * Arguments: @scanner *sc@ = pointer to scanner
- * @char delim@ = delimiter character to look for
- * @dstr *d@ = pointer to dynamic string for output
- *
- * Returns: ---
- *
- * Use: Reads in a compound name consisting of words separated by
- * delimiters. Leading and trailing delimiters are permitted,
- * although they'll probably cause confusion if used. The name
- * may be enclosed in square brackets if that helps at all.
- *
- * Examples of compound names are filenames (delimited by `/')
- * and IP addresses (delimited by `.').
- */
-
-extern void conf_name(scanner */*sc*/, char /*delim*/, dstr */*d*/);
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif