/*
    This file is part of SUPPL - the supplemental library for DOS
    Copyright (C) 1996-2000 Steffen Kaiser

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: CFG.LOC 1.4 1999/07/02 05:16:11 ska Exp ska $
   $Locker: ska $	$Name:  $	$State: Exp $

	Local include file for the cfg.h

*/

#ifndef __CFG_LOC
#define __CFG_LOC

#include <assert.h>
#include <portable.h>
#include "msgs.loc"
#include "cfg.h"
#include "sstr.h"

/* Access members of the option structure */
#ifndef _MICROC_
#define C(m) optstru->opt##m				/* access members */
#define S(m) optstru->opt_stk->C_##m		/* access context members */
#define O(m) ostk->C_##m					/* access ostack members */
#else
#define C(m) optstru->opt/**/m				/* access members */
#define S(m) optstru->opt_stk->C_/**/m		/* access context members */
#define O(m) ostk->C_/**/m					/* access ostack members */
#endif

/*
 * How to probe for if a character is member of a specific class
 *
 *	The form directly corresponses to the types of various classes defined
 *	within the option structure. Mainly three forms are designed (all
 *	forms are guaranteed to evaluate 'ch' exactly once):
 *	+ type: (char*): The member is a string enumerating all possible
 *	characters
 *	--> probe with the Strchr(<class>, ch) function:
 *		++ <class> can be NULL (check fails)
 *		++ 'ch' can be '\0' (check fails, too)
 *		++ strict case-senstive match
 *	+ type: (char): The member consists of the only possible character or
 *	'\0' if none
 *	--> probe with an 'equal' compare "<class> && (<class> == (ch))":
 *		++ strict case-senstive match
 *	+ type: constant: can be either (char*) or (char).
 *	The evaluation is basically the same, however, if "<class> == 0",
 *	the comparison might be transformed into: "((ch), 0)"
 *		++ 'ch' is evaluted once, in case it contains expressions with
 *		side effects, e.g. increment, assignments, function calls
 *		++ the optimizer of the compiler can reduce this expression to
 *		a constant one, if applicable
 *
 *	At least one single quote is required for the proper function of the
 *	getopt() function, because DOS normally doesn't know about such quote
 *	a function _outside_ the normal character set is used. This is, however,
 *	possible only, because the check isSingleQuote() uses the "==" operator
 *	rather than Strchr(). When a single quote is about to be installed,
 *	this special character should be removed and a valid single quote
 *	should be used.
 */

#define CFG_SINGLE_QUOTE	0x200	/* See note above about single quotes! */

/* List of current members and their types and the name of the compare fct:
	_ch			char*	isOpt
	_ioch		char*	isOpt_io
	_iach		char*	isOpt_ia
	_bool		char*	isBoolean
	_arg		char*	isArgument
	_quote		char*	isQuote
	_squote		char	isSingleQuote			SEE NOTES ABOVE
	_stdin		char*	isStdinSgn
	_stop		char*	isStopSgn
	_sourcein	char	isRspnFile
*/
#define isOpt(ch) Strchr(C(_ch), (ch))
#define isOpt_io(ch) Strchr(C(_ioch), (ch))
#define isOpt_ia(ch) Strchr(C(_iach), (ch))
#define isBoolean(ch) Strchr(C(_bool), (ch))
#define isArgSign(ch) Strchr(C(_arg), (ch))
#define isQuote(ch) Strchr(C(_quote), (ch))
//#define isSingleQuote(ch) (C(_squote) && C(_squote) == (ch))
#define isSingleQuote(ch) (CFG_SINGLE_QUOTE == (ch))
#define isStdinSgn(ch) Strchr(C(_stdin), (ch))
#define isStopSgn(ch) Strchr(C(_stop), (ch))
#define isRspnFile(ch) (C(_sourcein) && C(_sourcein) == (ch))

/* The cfg functions might require a normal option sign, this
	function returns it
	As well for a quote
*/
#define optSign *C(_ch)
#define quoteSign *C(_quote)
#define squoteSign CFG_SINGLE_QUOTE

/*******************************************
 ** Structures for context functions *******
 *******************************************/
struct Cfg_ArgDynString {
	const char *cfg_a_string;		/* start of string to be free()'ed */
	const char *cfg_a_p;			/* current pointer within this string */
};

struct Cfg_ArgArgv {
	const char * const *cfg_a_argv;		/* current argv pointer */
	const char *cfg_a_p;			/* current pointer into the current argv */
	FLAG cfg_a_quote;				/* if to issue a quote next time */
};

struct Cfg_ArgFileList {		/* argument list within a file */
	FILE *cfg_a_f;					/* opened file pointer */
	FLAG cfg_a_rmode;				/* if TRUE, file is in readmode */
	fpos_t cfg_a_rpos				/* next read position of seq read */
		, cfg_a_wpos				/* previous last entry (for insert) */
		, cfg_a_fpos;				/* the position of the first not-removed
										entry */
};

#define curOStk	C(_oHead)->C_prv	/* The current ostack item, only
										valid, if C(_oHead) != NULL */

/*************************
 ** Name tables **********
 *************************/
extern const MSGID cfgNamesIncrement[];
extern const MSGID cfgNamesDecrement[];
extern const MSGID cfgNamesOff[];
extern const MSGID cfgNamesOn[];
extern const MSGID cfgNamesToggle[];

/*
 *	Retreive the next character from the input channels
 *
 *	First, return the buffered character.
 *	Second, try the currently opened response file.
 *	Third, fetch the character using the user function.
 *
 *	Return:
 *		EOF: response file empty/no further character
 *		else: character
 */
int cfg_getc(struct Cfg_Getopt *optstru);

/*
 *	Return a new, zero'ed stack item
 *	Terminate on failure
 */
#define cfg_newStackItem() Ecalloc(sizeof(struct Cfg_iStackGetopt))

/*
 *	Overwrite NULL's with default values
 */
void cfg_initGetopt(struct Cfg_Getopt * const optstru);

/*
	Search if the passed option name is a longname option.

	Return:
		NULL: no
		else: yes, pointer to longname option structure
*/
struct Cfg_LongOptions *cfg_isLongnameOption(
	struct Cfg_LongOptions * const options
	, const char * const name);

/*
 *	Return the next option from the initialized structure
 	For input streams that return their source character-by-
 	character rather than have a preformatted one.
 *
 *	Return:
 *		== 0: no further option or non-option argument found
 *		!= 0: shortname option found
 */
int cfg_getStream(struct Cfg_Getopt *optstru);

#endif
