#ifndef V_PARSE_H
#define V_PARSE_H

#ifdef  CONFIG_SCANNER

/*
 * Bitfields for state and position saving / restoration
 */
#define	LEX_STATE_BIT		1
#define	LEX_POSITION_BIT	2

/*
 * pnames for lexEnable() / lexDisable() / lexIsEnabled().
 * These are indices in state array; if changed, the macro
 * LEX_DEFAULT_STATE must be changed also.
 */
#define	LEX_DEFAULT_DELIMITERS	0
#define	LEX_LINE_MODE			1
#define	LEX_LINE_ADVANCING		2
#define	LEX_ONE_CHAR_COMMENTS	3
#define	LEX_QUOTES_RETURNING	4
#define	LEX_QUOTES_PROCESSING	5
#define	LEX_ESCAPES_PROCESSING	6
#define	LEX_ALIAS_TRANSLATION	7
#define	LEX_MAX_STATE_FLAG		8

/*
 * pnames for lex[G,S]et[Integer,String,Boolean]().
 */

#define	LEX_CURRENT_LINE	0x8001	/* read-write */
#define	LEX_LAST_LINE		0x8002	/* read-only */
#define	LEX_COMMENT_CHAR	0x8003	/* read-write */
#define	LEX_QUOTE_CHAR		0x8004	/* read-write */
#define	LEX_ESCAPE_CHAR		0x8005	/* read-write */
#define	LEX_INSIDE_QUOTES	0x8006	/* read-only */
#define	LEX_DELIMITER_STRING	0x8007	/* read-write */
#define	LEX_SOURCE_NAME		0x8008	/* read-only */
#define	LEX_SOURCE_STRING	0x8009	/* read-write */

#ifdef  __cplusplus
extern  "C" {
#endif  /* __cplusplus */
    /*
     * Different constructors
     */
    /* Create scanner for in-memory buffer; 'buffer' must be valid while scanning */
    vhandle_t V_GLOBAL  lexParseBuffer(char *buffer,u32_t buffer_len,char *delim);
    /* Same as above, buffer_len determined as strlen(buffer) */
    vhandle_t V_GLOBAL  lexParseString(char *buffer,char *delim);
    /* File scanners */
    vhandle_t V_GLOBAL  lexParseFile(char *filename,char *delim);
	vhandle_t V_GLOBAL	lexParseStream(vhandle_t infile,char *delim);
    /* Saving/restoring scanner's state and/or position */
    vboolean    V_GLOBAL	lexPush(vhandle_t lexer,u32_t bitfields);
    vboolean    V_GLOBAL    lexPop(vhandle_t lexer,u32_t bitfields);
	void    	V_GLOBAL	lexClearStacks(vhandle_t handle,u32_t bitfields);
	s32_t		V_GLOBAL	lexGetInteger(vhandle_t handle,u32_t pname);
	vboolean	V_GLOBAL	lexSetInteger(vhandle_t handle,u32_t pname,s32_t param);
	char_p		V_GLOBAL	lexGetString(vhandle_t handle,u32_t pname);
	vboolean	V_GLOBAL	lexSetString(vhandle_t handle,u32_t pname,char_p param);
	vboolean	V_GLOBAL	lexGetBoolean(vhandle_t handle,u32_t pname);
	vboolean	V_GLOBAL	lexSetBoolean(vhandle_t handle,u32_t pname,vboolean param);
	vboolean	V_GLOBAL	lexEnable(vhandle_t lexer,u32_t pname);
	vboolean	V_GLOBAL	lexDisable(vhandle_t lexer,u32_t pname);
	vboolean	V_GLOBAL	lexIsEnabled(vhandle_t lexer,u32_t pname);
    /* Sets replacement for given value; 'replacement' can be NULL */
	vboolean	V_GLOBAL	lexDefineAlias(vhandle_t handle,char *value,char *replacement);
    /*
     * Returns next token or NULL if no more tokens
     */
    char_p      V_GLOBAL    lexNext(vhandle_t lexer);
    /*
     *  Returns last result of tok[Next | Strict | String], or
     *  NULL if:
     *      - was no previous call to mentioned functions;
     *      - no more chars (or something else wrong).
     */
    char_p      V_GLOBAL    lexLast(vhandle_t lexer);
    /*
     * if lexNext() returns non-NULL, copies token to 'buf'.
     * Returns number of copied chars.
     */
	u32_t V_GLOBAL lexCopyNextToken(vhandle_t scanner,char *buf,u32_t buf_len);
    /*
     * if lexLast() returns non-NULL, copies token to 'buf'.
     * Returns number of copied chars.
     */
	u32_t V_GLOBAL lexCopyLastToken(vhandle_t scanner,char *buf,u32_t buf_len);

	/*
	 * Reads words while the pair to 'skip_from' not reached.
	 * Currently, 'skip_form' have to be one of "{}[]()" (either opening
	 * or closing). Handles nested blocks.
	 */
	vboolean V_GLOBAL	lexSkipBlock(vhandle_t scanner,char skip_from);
	/*	Reads words while 'token' not reached */
	vboolean V_GLOBAL	lexSkipTo(vhandle_t scanner,char *token);
	vboolean V_GLOBAL	lexSkipToEx(vhandle_t scanner,char *token,
		int (LIBC_CALL *str_comp)(const char *s1,const char *s2));
	/*	Returns true if lexNext() returns 'expected_token' */
	vboolean V_GLOBAL	lexNextIs(vhandle_t scanner,char *expected_token);
	/*	Returns true if lexLast() returns 'expected_token' */
	vboolean V_GLOBAL	lexLastWas(vhandle_t scanner,char *expected_token);
	/*	Returns true if lexNext() returns 'expected_token' */
	vboolean V_GLOBAL	lexNextIsEx(vhandle_t scanner,char *expected_token,
		int (LIBC_CALL *str_comp)(const char *s1,const char *s2));
	/*	Returns true if lexLast() returns 'expected_token' */
	vboolean V_GLOBAL	lexLastWasEx(vhandle_t scanner,char *expected_token,
		int (LIBC_CALL *str_comp)(const char *s1,const char *s2));
	/*	Return true (and set 'idx_ret') if token listed in 'token_table' */
	vboolean V_GLOBAL	lexNextMatches(vhandle_t scanner,
		char *table[],u32_t table_size,u32_p idx_ret);
	vboolean V_GLOBAL	lexLastMatches(vhandle_t scanner,
		char *table[],u32_t table_size,u32_p idx_ret);
	vboolean V_GLOBAL	lexNextMatchesEx(vhandle_t scanner,
		char *table[],u32_t table_size,u32_p idx_ret,
		int (LIBC_CALL *str_comp)(const char *s1,const char *s2));
	vboolean V_GLOBAL	lexLastMatchesEx(vhandle_t scanner,
		char *table[],u32_t table_size,u32_p idx_ret,
		int (LIBC_CALL *str_comp)(const char *s1,const char *s2));
	/*	Reads integer */
	vboolean V_GLOBAL	lexNextInteger(vhandle_t scanner,s32_t *ret_val);
	/*	Returns last read integer */
	vboolean V_GLOBAL	lexLastInteger(vhandle_t scanner,s32_t *ret_val);
	/*	Reads float */
	vboolean V_GLOBAL	lexNextFloat(vhandle_t scanner,vec_t *ret_val);
	/*	Returns last read float */
	vboolean V_GLOBAL	lexLastFloat(vhandle_t scanner,vec_t *ret_val);
    /*  Destroys scanner */
    void        V_GLOBAL    lexDestroy(vhandle_t lexer);
#ifdef __cplusplus
}
#endif /* __cplusplus */

/* there macros emulate obsolete API calls */

#define	lexCurrentLine(handle) \
	lexGetInteger(handle,LEX_CURRENT_LINE)

#define	lexLastLine(handle) \
	lexGetInteger(handle,LEX_LAST_LINE)

#define	lexGetCommentChar(handle) \
	((char)lexGetInteger(handle,LEX_COMMENT_CHAR))

#define	lexSetCommentChar(handle,ch) \
	lexSetInteger(handle,LEX_COMMENT_CHAR,(u32_t)(ch))

#define	lexSourceName(handle) \
	lexGetString(handle,LEX_SOURCE_NAME)

#define	lexSourceName(handle) \
	lexGetString(handle,LEX_SOURCE_NAME)

#define	lexRestart(handle) \
	lexSetInteger(handle,LEX_CURRENT_LINE,1)

#define	lexChangeDelimiter(handle,delim) \
	lexSetString(handle,LEX_DELIMITER_STRING,delim)

#endif /* CONFIG_SCANNER */

#endif /* V_PARSE_H */
