modules/rpsl/syntax.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- syntax_init
- yywrap
- yyerror
- syntax_error
- min
- yy_input
- syntax_check_by_offset
- syntax_check_by_name
- main
1 /******************
2 Copyright (c) 2002 RIPE NCC
3
4 All Rights Reserved
5
6 Permission to use, copy, modify, and distribute this software and its
7 documentation for any purpose and without fee is hereby granted,
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in
10 supporting documentation, and that the name of the author not be
11 used in advertising or publicity pertaining to distribution of the
12 software without specific, written prior permission.
13
14 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
16 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
17 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
18 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 ***************************************/
21
22 /* could use per-lexer locks for speed, but it's probably unnecessary */
23
24 #include <string.h>
25 #include <sys/types.h>
26 #include <regex.h>
27 #include <stdlib.h>
28 #include <pthread.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <glib.h>
32 #include <assert.h>
33 #include "syntax.h"
34 #include "syntax_tab.h"
35
36 #define SYNTAX_TAB_LEN (sizeof(syntax_tab)/sizeof(syntax_tab[0]))
37
38 static void
39 syntax_init()
/* [<][>][^][v][top][bottom][index][help] */
40 {
41 int i;
42 int regcomp_ret;
43
44 for (i=0; i<SYNTAX_TAB_LEN; i++) {
45 if (syntax_tab[i].core_regex_pattern != NULL) {
46 syntax_tab[i].core_regex = g_new(regex_t, 1);
47 regcomp_ret = regcomp(syntax_tab[i].core_regex,
48 syntax_tab[i].core_regex_pattern,
49 REG_EXTENDED | REG_ICASE | REG_NOSUB);
50 assert(regcomp_ret == 0);
51 }
52 if (syntax_tab[i].core_reserved_regex_pattern != NULL) {
53 syntax_tab[i].core_reserved_regex = g_new(regex_t, 1);
54 regcomp_ret = regcomp(syntax_tab[i].core_reserved_regex,
55 syntax_tab[i].core_reserved_regex_pattern,
56 REG_EXTENDED | REG_ICASE | REG_NOSUB);
57 assert(regcomp_ret == 0);
58 }
59 if (syntax_tab[i].front_end_regex_pattern != NULL) {
60 syntax_tab[i].front_end_regex = g_new(regex_t, 1);
61 regcomp_ret = regcomp(syntax_tab[i].front_end_regex,
62 syntax_tab[i].front_end_regex_pattern,
63 REG_EXTENDED | REG_ICASE | REG_NOSUB);
64 assert(regcomp_ret == 0);
65 }
66 if (syntax_tab[i].front_end_reserved_regex_pattern != NULL) {
67 syntax_tab[i].front_end_reserved_regex = g_new(regex_t, 1);
68 regcomp_ret = regcomp(syntax_tab[i].front_end_reserved_regex,
69 syntax_tab[i].front_end_reserved_regex_pattern,
70 REG_EXTENDED | REG_ICASE | REG_NOSUB);
71 assert(regcomp_ret == 0);
72 }
73 }
74 }
75
76 int
77 yywrap()
/* [<][>][^][v][top][bottom][index][help] */
78 {
79 return 1;
80 }
81
82 /* array of errors (initialize before parsing) */
83 GPtrArray *parse_errors;
84
85 /* parse error */
86 void
87 yyerror(const char *s)
/* [<][>][^][v][top][bottom][index][help] */
88 {
89 gchar *copy;
90
91 copy = g_strdup(s);
92 g_ptr_array_add(parse_errors, copy);
93 }
94
95 /* syntax error (formatted parse error) */
96 void
97 syntax_error(const char *fmt, ...)
/* [<][>][^][v][top][bottom][index][help] */
98 {
99 va_list args;
100 guint len;
101 gchar *buf;
102
103 va_start(args, fmt);
104 len = g_printf_string_upper_bound(fmt, args);
105 buf = g_new(char, len+1);
106 vsnprintf(buf, len+1, fmt, args);
107 va_end(args);
108 yyerror(buf);
109 g_free(buf);
110 }
111
112 /* taken from _lex & yacc_ p.157, by Levine, Mason, & Brown (corrected) */
113 static const char *syntax_inputptr;
114 static const char *syntax_inputlim;
115
116 #undef min
117 #define min(a, b) (((a) < (b)) ? (a) : (b))
/* [<][>][^][v][top][bottom][index][help] */
118
119 void
120 yy_input (char *buf, int *result, int max_size)
/* [<][>][^][v][top][bottom][index][help] */
121 {
122 int n = min(max_size, syntax_inputlim - syntax_inputptr);
123
124 if (n > 0) {
125 memcpy(buf, syntax_inputptr, n);
126 syntax_inputptr += n;
127 }
128 *result = n;
129 }
130
131 static pthread_once_t init_control = PTHREAD_ONCE_INIT;
132
133 /* returns an array of strings with error descriptions (may be empty) */
134 GPtrArray *
135 syntax_check_by_offset (int offset, syntax_check_t type, const char *s)
/* [<][>][^][v][top][bottom][index][help] */
136 {
137 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
138 GPtrArray *errors;
139 GString *tmp;
140
141 pthread_once(&init_control, syntax_init);
142
143 errors = g_ptr_array_new();
144 tmp = g_string_new("");
145
146 if (type == SYNTAX_CHECK_CORE) {
147 if (syntax_tab[offset].core_regex_pattern != NULL) {
148 if (regexec(syntax_tab[offset].core_regex, s, 0, NULL, 0) != 0) {
149 g_string_sprintf(tmp, "Syntax error in \"%s\"", s);
150 g_ptr_array_add(errors, g_strdup(tmp->str));
151 goto syntax_check_by_offset_exit;
152 }
153 }
154 if (syntax_tab[offset].core_reserved_regex_pattern != NULL) {
155 if (regexec(syntax_tab[offset].core_reserved_regex, s,
156 0, NULL, 0) == 0)
157 {
158 g_string_sprintf(tmp, "\"%s\" is a reserved word", s);
159 g_ptr_array_add(errors, g_strdup(tmp->str));
160 goto syntax_check_by_offset_exit;
161 }
162 }
163 if (syntax_tab[offset].core_parser != NULL) {
164 pthread_mutex_lock(&mutex);
165 (syntax_tab[offset].core_parser_reset)();
166 syntax_inputptr = s;
167 syntax_inputlim = s + strlen(s);
168 parse_errors = errors;
169 (syntax_tab[offset].core_parser)();
170 pthread_mutex_unlock(&mutex);
171 if (errors->len > 0) {
172 goto syntax_check_by_offset_exit;
173 }
174 }
175 } else {
176 if (syntax_tab[offset].front_end_regex_pattern != NULL) {
177 if (regexec(syntax_tab[offset].front_end_regex, s, 0, NULL, 0)!=0) {
178 g_string_sprintf(tmp, "Syntax error in \"%s\"", s);
179 g_ptr_array_add(errors, g_strdup(tmp->str));
180 goto syntax_check_by_offset_exit;
181 }
182 }
183 if (syntax_tab[offset].front_end_reserved_regex_pattern != NULL) {
184 if (regexec(syntax_tab[offset].front_end_reserved_regex, s,
185 0, NULL, 0) == 0)
186 {
187 g_string_sprintf(tmp, "\"%s\" is a reserved word", s);
188 g_ptr_array_add(errors, g_strdup(tmp->str));
189 goto syntax_check_by_offset_exit;
190 }
191 }
192 if (syntax_tab[offset].front_end_parser != NULL) {
193 pthread_mutex_lock(&mutex);
194 (syntax_tab[offset].front_end_parser_reset)();
195 syntax_inputptr = s;
196 syntax_inputlim = s + strlen(s);
197 parse_errors = errors;
198 (syntax_tab[offset].front_end_parser)();
199 pthread_mutex_unlock(&mutex);
200 if (errors->len > 0) {
201 goto syntax_check_by_offset_exit;
202 }
203 }
204 }
205
206 syntax_check_by_offset_exit:
207 g_string_free(tmp, TRUE);
208 return errors;
209 }
210
211 GPtrArray *
212 syntax_check_by_name (const char *name, syntax_check_t type, const char *s)
/* [<][>][^][v][top][bottom][index][help] */
213 {
214 int i;
215 GPtrArray *errors;
216
217 for (i=0; i<SYNTAX_TAB_LEN; i++) {
218 if (strcasecmp(syntax_tab[i].name, name) == 0) {
219 return syntax_check_by_offset(i, type, s);
220 }
221 }
222 errors = g_ptr_array_new();
223 g_ptr_array_add(errors,
224 "Internal error: check of unknown syntax requested");
225 return errors;
226 }
227
228 #ifdef UNIT_TEST
229 int main()
/* [<][>][^][v][top][bottom][index][help] */
230 {
231 int i, j;
232 GPtrArray *errors;
233
234 /* call all syntax checks */
235 for (i=0; i<SYNTAX_TAB_LEN; i++) {
236 errors = syntax_check_by_offset(i, SYNTAX_CHECK_CORE, "");
237 for (j=0; j<errors->len; j++) {
238 g_free(g_ptr_array_index(errors, j));
239 }
240 g_ptr_array_free(errors, TRUE);
241 errors = syntax_check_by_offset(i, SYNTAX_CHECK_FRONT_END, "");
242 for (j=0; j<errors->len; j++) {
243 g_free(g_ptr_array_index(errors, j));
244 }
245 g_ptr_array_free(errors, TRUE);
246 }
247 }
248 #endif /* UNIT_TEST */
249
250 /*
251 int parse_error_count = 0;
252
253 int main()
254 {
255 char buf[256];
256 syntax_init();
257 printf("check filter: ");
258 gets(buf);
259 printf("result=%d\n", syntax_check_by_name("filter", SYNTAX_CHECK_FRONT_END, buf));
260 }
261 */
262