## modules/rpsl/syntax.c

/* [<][>][^][v][top][bottom][index][help] */

## FUNCTIONS

This source file includes following functions.

1. syntax_init
2. yywrap
3. yyerror
4. syntax_error
5. min
6. yy_input
7. syntax_check_by_offset
8. syntax_check_by_name
9. 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

/* [<][>][^][v][top][bottom][index][help] */