syslog-ng source
cfg-lexer.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2002-2012 Balabit
3  * Copyright (c) 1998-2012 Balázs Scheidler
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  *
19  * As an additional exemption you are allowed to compile & link against the
20  * OpenSSL libraries as published by the OpenSSL project. See the file
21  * COPYING for details.
22  *
23  */
24 
25 #ifndef CFG_LEXER_H_INCLUDED
26 #define CFG_LEXER_H_INCLUDED 1
27 
28 #include "syslog-ng.h"
29 #include "cfg-args.h"
30 #include "cfg-block-generator.h"
31 #include "messages.h"
32 
33 #include <stdio.h>
34 #include <setjmp.h>
35 
36 /* this module provides a higher level encapsulation for the configuration
37  * file lexer. */
38 
39 #define MAX_INCLUDE_DEPTH 256
40 
41 typedef struct _CfgIncludeLevel CfgIncludeLevel;
42 typedef struct _CfgTokenBlock CfgTokenBlock;
43 
44 /*
45  * YYLTYPE/YYSTYPE naming conventions
46  *
47  * We use multiple bison generated grammars (basically one for each plugin)
48  * with a single lexer and the same location/symbol types. Earlier we could
49  * easily just define YYLTYPE and YYSTYPE here and all generated grammars
50  * and the lexer used it properly. With the advent of the `api.prefix'
51  * option for the grammars (and the deprecation of the old `name-prefix'
52  * behaviors), we needed to complicate things somewhat.
53  *
54  * We have three contexts where we need to use proper type names:
55  * - in our own code where we might need to use location information (e.g. YYLTYPE)
56  * - in the generated lexer,
57  * - in the generated grammars
58  *
59  * Our own code
60  * ============
61  * Because of the various #define/typedef games that generated code uses, I
62  * decided that our own code should not use the names YYLTYPE/YYSTYPE
63  * directly. In those cases we use CFG_LTYPE and CFG_STYPE to indicate that
64  * these are types related to our configuration language. None of the
65  * grammars use the "CFG_" prefix (and should not in the future either).
66  *
67  * The generated lexer
68  * ===================
69  *
70  * The lexer get these types by us #define-ing YYLTYPE/YYSTYPE to
71  * CFG_LTYPE/STYPE but only privately, e.g. these definitions should not be
72  * published to the rest of the codebase. We do this by defining these in
73  * implementation files and not in the headers. This is because some of the
74  * code would try to #ifdef based on the existance of these macros.
75  *
76  * The generated grammars
77  * ======================
78  * The grammars each have an api.location.type and api.value.type options in
79  * their .y files, which use the names CFG_LTYPE and CFG_STYPE respectively.
80  * The generated code uses YYLTYPE and YYSTYPE internally (defined as
81  * macros), but because of the previous points this does not create a
82  * conflict.
83  */
84 
85 /* the location type to carry location information from the lexer to the grammar */
86 
87 typedef struct CFG_LTYPE
88 {
91  int last_line;
93 
94  const gchar *name;
95 } CFG_LTYPE;
96 
97 /* symbol type that carries token related information to the grammar */
98 typedef struct CFG_STYPE
99 {
100  /* one of LL_ types that indicates which field is being used */
101  int type;
102  union
103  {
104  gint token;
105  gint64 num;
106  double fnum;
107  char *cptr;
108  void *ptr;
109  gpointer node;
110  };
111 } CFG_STYPE;
112 
113 #define KWS_NORMAL 0
114 #define KWS_OBSOLETE 1
115 
116 /* used to describe a syslog-ng keyword */
117 typedef struct _CfgLexerKeyword
118 {
119  const gchar *kw_name;
120  gint kw_token;
121  gint kw_status;
122  const gchar *kw_explain;
124 
125 #define CFG_KEYWORD_STOP "@!#?"
126 
127 
128 
129 /* structure that describes a given location in the include stack */
131 {
132  enum
133  {
138  union
139  {
140  struct
141  {
142  GSList *files;
144  } file;
145  struct
146  {
147  /* the lexer mutates content, so save it for error reporting */
149  /* buffer for the lexer */
150  gchar *content;
153  };
154 
155  /* this value indicates that @line was used which changed lloc relative to
156  * an actual file */
159  struct yy_buffer_state *yybuf;
160 };
161 
162 /* Lexer class that encapsulates a flex generated lexer. This can be
163  * instantiated multiple times in parallel, e.g. doesn't use any global
164  * state as we're using the "reentrant" code by flex
165  */
166 struct _CfgLexer
167 {
168  /* flex state, not using yyscan_t as it is not defined */
169  gpointer state;
170  jmp_buf fatal_error;
174  gchar block_boundary[2];
177  GList *token_blocks;
178  GString *string_buffer;
181  GString *token_pretext;
182  GString *token_text;
183  GlobalConfig *cfg;
185 };
186 
187 /* pattern buffer */
188 void cfg_lexer_unput_token(CfgLexer *self, CFG_STYPE *yylval);
189 
190 void cfg_lexer_start_block_state(CfgLexer *self, const gchar block_boundary[2]);
191 void cfg_lexer_start_block_arg_state(CfgLexer *self);
192 
193 void cfg_lexer_append_string(CfgLexer *self, int length, char *str);
194 void cfg_lexer_append_char(CfgLexer *self, char c);
195 
196 /* keyword handling */
197 void cfg_lexer_set_current_keywords(CfgLexer *self, CfgLexerKeyword *keywords);
198 char *cfg_lexer_get_keyword_string(CfgLexer *self, int kw);
199 int cfg_lexer_map_word_to_token(CfgLexer *self, CFG_STYPE *yylval, const CFG_LTYPE *yylloc, const char *token);
200 
201 /* include files */
202 gboolean cfg_lexer_start_next_include(CfgLexer *self);
203 gboolean cfg_lexer_include_file(CfgLexer *self, const gchar *filename);
204 gboolean cfg_lexer_include_buffer(CfgLexer *self, const gchar *name, const gchar *buffer, gssize length);
206  const gchar *name, const gchar *buffer, gsize length);
207 const gchar *cfg_lexer_format_location(CfgLexer *self, const CFG_LTYPE *yylloc, gchar *buf, gsize buf_len);
208 void cfg_lexer_set_file_location(CfgLexer *self, const gchar *filename, gint line, gint column);
209 EVTTAG *cfg_lexer_format_location_tag(CfgLexer *self, const CFG_LTYPE *yylloc);
210 
211 /* context tracking */
212 void cfg_lexer_push_context(CfgLexer *self, gint context, CfgLexerKeyword *keywords, const gchar *desc);
213 void cfg_lexer_pop_context(CfgLexer *self);
214 const gchar *cfg_lexer_get_context_description(CfgLexer *self);
215 gint cfg_lexer_get_context_type(CfgLexer *self);
216 
217 /* token blocks */
218 void cfg_lexer_inject_token_block(CfgLexer *self, CfgTokenBlock *block);
219 
220 int cfg_lexer_lex(CfgLexer *self, CFG_STYPE *yylval, CFG_LTYPE *yylloc);
221 void cfg_lexer_free_token(CFG_STYPE *token);
222 
223 CfgLexer *cfg_lexer_new(GlobalConfig *cfg, FILE *file, const gchar *filename, GString *preprocess_output);
224 CfgLexer *cfg_lexer_new_buffer(GlobalConfig *cfg, const gchar *buffer, gsize length);
225 void cfg_lexer_free(CfgLexer *self);
226 
228 const gchar *cfg_lexer_lookup_context_name_by_type(gint id);
229 
230 /* token block objects */
231 
232 void cfg_token_block_add_and_consume_token(CfgTokenBlock *self, CFG_STYPE *token);
233 void cfg_token_block_add_token(CfgTokenBlock *self, CFG_STYPE *token);
234 CFG_STYPE *cfg_token_block_get_token(CfgTokenBlock *self);
235 
236 CfgTokenBlock *cfg_token_block_new(void);
237 void cfg_token_block_free(CfgTokenBlock *self);
238 
239 void cfg_lexer_register_generator_plugin(PluginContext *context, CfgBlockGenerator *gen);
240 
241 #define CFG_LEXER_ERROR cfg_lexer_error_quark()
242 
243 GQuark cfg_lexer_error_quark(void);
244 
246 {
250 };
251 
252 #endif
gboolean cfg_lexer_include_buffer_without_backtick_substitution(CfgLexer *self, const gchar *name, const gchar *buffer, gsize length)
Definition: cfg-lexer.c:745
void cfg_lexer_set_file_location(CfgLexer *self, const gchar *filename, gint line, gint column)
Definition: cfg-lexer.c:165
int cfg_lexer_map_word_to_token(CfgLexer *self, CFG_STYPE *yylval, const CFG_LTYPE *yylloc, const char *token)
Definition: cfg-lexer.c:238
void cfg_token_block_free(CfgTokenBlock *self)
Definition: cfg-lexer.c:1351
gboolean cfg_lexer_include_buffer(CfgLexer *self, const gchar *name, const gchar *buffer, gssize length)
Definition: cfg-lexer.c:763
void cfg_lexer_pop_context(CfgLexer *self)
Definition: cfg-lexer.c:108
void cfg_lexer_start_block_state(CfgLexer *self, const gchar block_boundary[2])
gboolean cfg_lexer_include_file(CfgLexer *self, const gchar *filename)
Definition: cfg-lexer.c:716
int cfg_lexer_lex(CfgLexer *self, CFG_STYPE *yylval, CFG_LTYPE *yylloc)
Definition: cfg-lexer.c:1122
CfgLexer * cfg_lexer_new_buffer(GlobalConfig *cfg, const gchar *buffer, gsize length)
Definition: cfg-lexer.c:1224
void cfg_lexer_append_char(CfgLexer *self, char c)
char * cfg_lexer_get_keyword_string(CfgLexer *self, int kw)
void cfg_token_block_add_token(CfgTokenBlock *self, CFG_STYPE *token)
Definition: cfg-lexer.c:1321
gboolean cfg_lexer_start_next_include(CfgLexer *self)
Definition: cfg-lexer.c:425
void cfg_lexer_set_current_keywords(CfgLexer *self, CfgLexerKeyword *keywords)
gint cfg_lexer_get_context_type(CfgLexer *self)
Definition: cfg-lexer.c:123
CfgLexerError
Definition: cfg-lexer.h:246
@ CFG_LEXER_CANNOT_REPRESENT_APOSTROPHES_IN_QSTRINGS
Definition: cfg-lexer.h:248
@ CFG_LEXER_MISSING_BACKTICK_PAIR
Definition: cfg-lexer.h:247
@ CFG_LEXER_BACKTICKS_CANT_BE_SUBSTITUTED_AFTER_BACKSLASH
Definition: cfg-lexer.h:249
#define MAX_INCLUDE_DEPTH
Definition: cfg-lexer.h:39
GQuark cfg_lexer_error_quark(void)
Definition: cfg-lexer.c:1368
void cfg_lexer_register_generator_plugin(PluginContext *context, CfgBlockGenerator *gen)
Definition: cfg-lexer.c:818
void cfg_lexer_free(CfgLexer *self)
Definition: cfg-lexer.c:1242
void cfg_lexer_free_token(CFG_STYPE *token)
Definition: cfg-lexer.c:895
EVTTAG * cfg_lexer_format_location_tag(CfgLexer *self, const CFG_LTYPE *yylloc)
Definition: cfg-lexer.c:157
void cfg_lexer_append_string(CfgLexer *self, int length, char *str)
const gchar * cfg_lexer_lookup_context_name_by_type(gint id)
Definition: cfg-lexer.c:1304
gint cfg_lexer_lookup_context_type_by_name(const gchar *name)
Definition: cfg-lexer.c:1291
CFG_STYPE * cfg_token_block_get_token(CfgTokenBlock *self)
Definition: cfg-lexer.c:1328
void cfg_lexer_start_block_arg_state(CfgLexer *self)
CfgTokenBlock * cfg_token_block_new(void)
Definition: cfg-lexer.c:1342
const gchar * cfg_lexer_get_context_description(CfgLexer *self)
Definition: cfg-lexer.c:139
void cfg_lexer_push_context(CfgLexer *self, gint context, CfgLexerKeyword *keywords, const gchar *desc)
Definition: cfg-lexer.c:91
const gchar * cfg_lexer_format_location(CfgLexer *self, const CFG_LTYPE *yylloc, gchar *buf, gsize buf_len)
Definition: cfg-lexer.c:150
void cfg_token_block_add_and_consume_token(CfgTokenBlock *self, CFG_STYPE *token)
Definition: cfg-lexer.c:1314
void cfg_lexer_inject_token_block(CfgLexer *self, CfgTokenBlock *block)
Definition: cfg-lexer.c:787
CfgLexer * cfg_lexer_new(GlobalConfig *cfg, FILE *file, const gchar *filename, GString *preprocess_output)
Definition: cfg-lexer.c:1205
void cfg_lexer_unput_token(CfgLexer *self, CFG_STYPE *yylval)
Definition: cfg-lexer.c:880
const gchar * name
Definition: debugger.c:265
Definition: cfg-lexer.h:88
int last_line
Definition: cfg-lexer.h:91
const gchar * name
Definition: cfg-lexer.h:94
int first_line
Definition: cfg-lexer.h:89
int last_column
Definition: cfg-lexer.h:92
int first_column
Definition: cfg-lexer.h:90
Definition: cfg-lexer.h:99
double fnum
Definition: cfg-lexer.h:106
gint token
Definition: cfg-lexer.h:104
gpointer node
Definition: cfg-lexer.h:109
void * ptr
Definition: cfg-lexer.h:108
gint64 num
Definition: cfg-lexer.h:105
char * cptr
Definition: cfg-lexer.h:107
int type
Definition: cfg-lexer.h:101
Definition: cfg-lexer.h:118
gint kw_token
Definition: cfg-lexer.h:120
gint kw_status
Definition: cfg-lexer.h:121
const gchar * kw_explain
Definition: cfg-lexer.h:122
const gchar * kw_name
Definition: cfg-lexer.h:119
Definition: cfg-lexer.h:131
struct _CfgIncludeLevel::@6::@9 buffer
GSList * files
Definition: cfg-lexer.h:142
enum _CfgIncludeLevel::@5 include_type
CFG_LTYPE lloc
Definition: cfg-lexer.h:158
gsize content_length
Definition: cfg-lexer.h:151
gchar * original_content
Definition: cfg-lexer.h:148
struct _CfgIncludeLevel::@6::@8 file
gboolean lloc_changed_by_at_line
Definition: cfg-lexer.h:157
gchar * content
Definition: cfg-lexer.h:150
@ CFGI_NONE
Definition: cfg-lexer.h:134
@ CFGI_FILE
Definition: cfg-lexer.h:135
@ CFGI_BUFFER
Definition: cfg-lexer.h:136
FILE * include_file
Definition: cfg-lexer.h:143
struct yy_buffer_state * yybuf
Definition: cfg-lexer.h:159
Definition: cfg-lexer.h:167
gint tokenize_eol
Definition: cfg-lexer.h:176
CfgIncludeLevel include_stack[MAX_INCLUDE_DEPTH]
Definition: cfg-lexer.h:171
guint ignore_pragma
Definition: cfg-lexer.h:184
GList * context_stack
Definition: cfg-lexer.h:172
gchar block_boundary[2]
Definition: cfg-lexer.h:174
gint preprocess_suppress_tokens
Definition: cfg-lexer.h:180
GlobalConfig * cfg
Definition: cfg-lexer.h:183
guint first_non_pragma_seen
Definition: cfg-lexer.h:184
GString * string_buffer
Definition: cfg-lexer.h:178
gpointer state
Definition: cfg-lexer.h:169
jmp_buf fatal_error
Definition: cfg-lexer.h:170
GString * token_text
Definition: cfg-lexer.h:182
gint include_depth
Definition: cfg-lexer.h:173
GString * token_pretext
Definition: cfg-lexer.h:181
gint brace_count
Definition: cfg-lexer.h:175
GList * token_blocks
Definition: cfg-lexer.h:177
GString * preprocess_output
Definition: cfg-lexer.h:179
Definition: cfg-lexer.c:54
GlobalConfig * cfg
Definition: test_batched_ack_tracker.c:34
GString * buffer
Definition: test_smart_multi_line.c:69