%PDF- %PDF-
| Direktori : /backups/router/usr/local/include/syslog-ng/ |
| Current File : //backups/router/usr/local/include/syslog-ng/cfg-lexer.h |
/*
* Copyright (c) 2002-2012 Balabit
* Copyright (c) 1998-2012 Balázs Scheidler
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As an additional exemption you are allowed to compile & link against the
* OpenSSL libraries as published by the OpenSSL project. See the file
* COPYING for details.
*
*/
#ifndef CFG_LEXER_H_INCLUDED
#define CFG_LEXER_H_INCLUDED 1
#include "syslog-ng.h"
#include "cfg-args.h"
#include "cfg-block-generator.h"
#include "messages.h"
#include <stdio.h>
#include <setjmp.h>
/* this module provides a higher level encapsulation for the configuration
* file lexer. */
#define MAX_INCLUDE_DEPTH 256
typedef struct _CfgIncludeLevel CfgIncludeLevel;
typedef struct _CfgTokenBlock CfgTokenBlock;
/*
* YYLTYPE/YYSTYPE naming conventions
*
* We use multiple bison generated grammars (basically one for each plugin)
* with a single lexer and the same location/symbol types. Earlier we could
* easily just define YYLTYPE and YYSTYPE here and all generated grammars
* and the lexer used it properly. With the advent of the `api.prefix'
* option for the grammars (and the deprecation of the old `name-prefix'
* behaviors), we needed to complicate things somewhat.
*
* We have three contexts where we need to use proper type names:
* - in our own code where we might need to use location information (e.g. YYLTYPE)
* - in the generated lexer,
* - in the generated grammars
*
* Our own code
* ============
* Because of the various #define/typedef games that generated code uses, I
* decided that our own code should not use the names YYLTYPE/YYSTYPE
* directly. In those cases we use CFG_LTYPE and CFG_STYPE to indicate that
* these are types related to our configuration language. None of the
* grammars use the "CFG_" prefix (and should not in the future either).
*
* The generated lexer
* ===================
*
* The lexer get these types by us #define-ing YYLTYPE/YYSTYPE to
* CFG_LTYPE/STYPE but only privately, e.g. these definitions should not be
* published to the rest of the codebase. We do this by defining these in
* implementation files and not in the headers. This is because some of the
* code would try to #ifdef based on the existance of these macros.
*
* The generated grammars
* ======================
* The grammars each have an api.location.type and api.value.type options in
* their .y files, which use the names CFG_LTYPE and CFG_STYPE respectively.
* The generated code uses YYLTYPE and YYSTYPE internally (defined as
* macros), but because of the previous points this does not create a
* conflict.
*/
/* the location type to carry location information from the lexer to the grammar */
typedef struct CFG_LTYPE
{
int first_line;
int first_column;
int last_line;
int last_column;
const gchar *name;
} CFG_LTYPE;
/* symbol type that carries token related information to the grammar */
typedef struct CFG_STYPE
{
/* one of LL_ types that indicates which field is being used */
int type;
union
{
gint token;
gint64 num;
double fnum;
char *cptr;
void *ptr;
gpointer node;
};
} CFG_STYPE;
#define KWS_NORMAL 0
#define KWS_OBSOLETE 1
/* used to describe a syslog-ng keyword */
typedef struct _CfgLexerKeyword
{
const gchar *kw_name;
gint kw_token;
gint kw_status;
const gchar *kw_explain;
} CfgLexerKeyword;
#define CFG_KEYWORD_STOP "@!#?"
/* structure that describes a given location in the include stack */
struct _CfgIncludeLevel
{
enum
{
CFGI_NONE,
CFGI_FILE,
CFGI_BUFFER,
} include_type;
union
{
struct
{
GSList *files;
FILE *include_file;
} file;
struct
{
/* the lexer mutates content, so save it for error reporting */
gchar *original_content;
/* buffer for the lexer */
gchar *content;
gsize content_length;
} buffer;
};
/* this value indicates that @line was used which changed lloc relative to
* an actual file */
gboolean lloc_changed_by_at_line;
CFG_LTYPE lloc;
struct yy_buffer_state *yybuf;
};
/* Lexer class that encapsulates a flex generated lexer. This can be
* instantiated multiple times in parallel, e.g. doesn't use any global
* state as we're using the "reentrant" code by flex
*/
struct _CfgLexer
{
/* flex state, not using yyscan_t as it is not defined */
gpointer state;
jmp_buf fatal_error;
CfgIncludeLevel include_stack[MAX_INCLUDE_DEPTH];
GList *context_stack;
gint include_depth;
gchar block_boundary[2];
gint brace_count;
gint tokenize_eol;
GList *token_blocks;
GString *string_buffer;
GString *preprocess_output;
gint preprocess_suppress_tokens;
GString *token_pretext;
GString *token_text;
GlobalConfig *cfg;
guint first_non_pragma_seen:1, ignore_pragma:1;
};
/* pattern buffer */
void cfg_lexer_unput_token(CfgLexer *self, CFG_STYPE *yylval);
void cfg_lexer_start_block_state(CfgLexer *self, const gchar block_boundary[2]);
void cfg_lexer_push_filterx_state(CfgLexer *self);
void cfg_lexer_pop_filterx_state(CfgLexer *self);
void cfg_lexer_start_block_arg_state(CfgLexer *self);
void cfg_lexer_append_string(CfgLexer *self, int length, char *str);
void cfg_lexer_append_char(CfgLexer *self, char c);
/* keyword handling */
void cfg_lexer_set_current_keywords(CfgLexer *self, CfgLexerKeyword *keywords);
char *cfg_lexer_get_keyword_string(CfgLexer *self, int kw);
int cfg_lexer_map_word_to_token(CfgLexer *self, CFG_STYPE *yylval, const CFG_LTYPE *yylloc, const char *token);
/* include files */
gboolean cfg_lexer_start_next_include(CfgLexer *self);
gboolean cfg_lexer_include_file(CfgLexer *self, const gchar *filename);
gboolean cfg_lexer_include_buffer(CfgLexer *self, const gchar *name, const gchar *buffer, gssize length);
gboolean cfg_lexer_include_buffer_without_backtick_substitution(CfgLexer *self,
const gchar *name, const gchar *buffer, gsize length);
const gchar *cfg_lexer_format_location(CfgLexer *self, const CFG_LTYPE *yylloc, gchar *buf, gsize buf_len);
void cfg_lexer_set_file_location(CfgLexer *self, const gchar *filename, gint line, gint column);
EVTTAG *cfg_lexer_format_location_tag(CfgLexer *self, const CFG_LTYPE *yylloc);
/* context tracking */
void cfg_lexer_push_context(CfgLexer *self, gint context, CfgLexerKeyword *keywords, const gchar *desc);
void cfg_lexer_pop_context(CfgLexer *self);
const gchar *cfg_lexer_get_context_description(CfgLexer *self);
gint cfg_lexer_get_context_type(CfgLexer *self);
/* token blocks */
void cfg_lexer_inject_token_block(CfgLexer *self, CfgTokenBlock *block);
int cfg_lexer_lex(CfgLexer *self, CFG_STYPE *yylval, CFG_LTYPE *yylloc);
void cfg_lexer_free_token(CFG_STYPE *token);
CfgLexer *cfg_lexer_new(GlobalConfig *cfg, FILE *file, const gchar *filename, GString *preprocess_output);
CfgLexer *cfg_lexer_new_buffer(GlobalConfig *cfg, const gchar *buffer, gsize length);
void cfg_lexer_free(CfgLexer *self);
gint cfg_lexer_lookup_context_type_by_name(const gchar *name);
const gchar *cfg_lexer_lookup_context_name_by_type(gint id);
/* token block objects */
void cfg_token_block_add_and_consume_token(CfgTokenBlock *self, CFG_STYPE *token);
void cfg_token_block_add_token(CfgTokenBlock *self, CFG_STYPE *token);
CFG_STYPE *cfg_token_block_get_token(CfgTokenBlock *self);
CfgTokenBlock *cfg_token_block_new(void);
void cfg_token_block_free(CfgTokenBlock *self);
void cfg_lexer_register_generator_plugin(PluginContext *context, CfgBlockGenerator *gen);
#define CFG_LEXER_ERROR cfg_lexer_error_quark()
GQuark cfg_lexer_error_quark(void);
enum CfgLexerError
{
CFG_LEXER_MISSING_BACKTICK_PAIR,
CFG_LEXER_CANNOT_REPRESENT_APOSTROPHES_IN_QSTRINGS,
CFG_LEXER_BACKTICKS_CANT_BE_SUBSTITUTED_AFTER_BACKSLASH,
};
#endif