openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

cint_parser.c (10468B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        cint_parser.c
      8  * Purpose:     CINT parser
      9  */
     10 
     11 #ifdef INCLUDE_EDITLINE
     12 #include <sal/appl/editline/editline.h>
     13 #endif
     14 #include "cint_parser.h"
     15 #include "cint_porting.h"
     16 
     17 static const char* __prompt = NULL; 
     18 static int include_depth = 0; 
     19 
     20 /*
     21  * These are extern'ed manually to avoid conflicts between the scanner and parser headers. 
     22  */
     23 extern int cint_c_lex_init(void** scanner); 
     24 int cint_c_scanner_finish(void *scanner);
     25 
     26 extern void* cint_c_pstate_new(void); 
     27 extern int   cint_c_pull_parse(void* handle, void* scanner, void* ctrl); 
     28 extern int   cint_c_pstate_delete(void* handle); 
     29 extern int cint_c_scanner_start(void*, void*); 
     30 extern void *cint_c__scan_bytes(const char *str, int len, void *scanner);
     31 extern void cint_c_set_lineno(int line_number, void *yyscanner);
     32 extern void cint_c_set_column(int column_no , void *yyscanner);
     33 
     34 
     35 /*
     36  * Create a C Parser instance
     37  */
     38 cint_cparser_t* 
     39 cint_cparser_create(void)
     40 {
     41     cint_cparser_t* cp = CINT_MALLOC(sizeof(*cp)); 
     42     
     43     if(cp == NULL) {
     44         return NULL; 
     45     }
     46 
     47     CINT_MEMSET(cp, 0, sizeof(*cp)); 
     48 
     49     /* Create the scanner instance */
     50     cint_c_lex_init(&cp->scanner); 
     51     
     52     if(cp->scanner == NULL) {
     53         cint_cparser_destroy(cp); 
     54         return NULL; 
     55     }
     56 
     57     /* Create a parser instance */
     58     cp->parser = cint_c_pstate_new(); 
     59     
     60     if(cp->parser == NULL) {
     61         cint_cparser_destroy(cp); 
     62         return NULL; 
     63     }
     64     
     65     return cp; 
     66 }
     67 
     68 /*
     69  * Destroy a C Parser instance
     70  */
     71 int
     72 cint_cparser_destroy(cint_cparser_t* cp)
     73 {
     74     if (cp == NULL) {
     75         return 0;
     76     }
     77 
     78     if (cp->scanner) {
     79         cint_c_scanner_finish(cp->scanner);
     80     }
     81 
     82     if (cp->parser) {
     83         cint_c_pstate_delete(cp->parser);
     84     }
     85 
     86     CINT_FREE(cp);
     87 
     88     return 0;
     89 }
     90 
     91 int 
     92 cint_cparser_start_handle(cint_cparser_t* cp, void* handle)
     93 {
     94     if(cp == NULL) {
     95         return -1; 
     96     }
     97 
     98     cint_c_scanner_start(handle, cp->scanner); 
     99     
    100     return 0; 
    101 }
    102 
    103 int 
    104 cint_cparser_start_string(cint_cparser_t* cp, const char* string)
    105 {
    106     if (cp == NULL) {
    107         return -1;
    108     }
    109 
    110     cint_c__scan_bytes(string, CINT_STRLEN(string), cp->scanner);
    111     /* cint_c__scan_buffer(), which is called by cint_c__scan_bytes,
    112        does not completely initialize YY_BUFFER_STATE; in particular,
    113        yylineno and yycolumn. This may cause accesses to uninitialized
    114        memory later on.  There's no Flex hook as of 2.5.35, so do
    115        further initialization here. */
    116     cint_c_set_lineno(1, cp->scanner);
    117     cint_c_set_column(0, cp->scanner);
    118 
    119     return 0;
    120 }
    121 
    122 cint_ast_t* 
    123 cint_cparser_parse(cint_cparser_t* cp)
    124 {
    125     cint_ast_t* ast; 
    126 
    127     if(cp == NULL) {
    128         return NULL; 
    129     }   
    130    
    131     cp->error = cint_c_pull_parse(cp->parser, cp->scanner, cp); 
    132     ast = cp->result; 
    133     cp->result = NULL; 
    134 
    135     return ast; 
    136 }
    137 
    138 cint_ast_t* 
    139 cint_cparser_parse_string(const char* string)
    140 {
    141     int status; 
    142     cint_ast_t* result = NULL; 
    143     cint_cparser_t* cp = cint_cparser_create(); 
    144     
    145     cint_cparser_start_string(cp, string); 
    146 
    147     for(;;) {
    148         
    149         status = cint_c_pull_parse(cp->parser, cp->scanner, cp); 
    150         if(status == 0) {
    151             /* Successfully parsed a translation unit */
    152             
    153             if(cp->result == NULL) {
    154                 /* EOF */
    155                 break; 
    156             }
    157             else {
    158                 if(result == NULL) {
    159                     result = cp->result; 
    160                 }
    161                 else {
    162                     if (cp->result != result) {
    163                         cint_ast_append(result, cp->result);
    164                     } else {
    165                         break;
    166                     }
    167                 }
    168             }
    169         }
    170         else {
    171             /* Error */
    172             break; 
    173         }
    174     }   
    175 
    176     cint_cparser_destroy(cp); 
    177     return result; 
    178 }
    179 
    180 
    181 static int
    182 cint_cparser_prompt(void)
    183 {
    184     if(cint_cparser_interactive()) {
    185         CINT_PRINTF("%s", __prompt); 
    186     }
    187     return 0; 
    188 }
    189 
    190 int
    191 cint_cparser_error(cint_cparser_t* cp)
    192 {
    193     return cp->error;
    194 }
    195 
    196 void cint_cparser_fatal_error(char *msg)
    197 {
    198     CINT_FATAL_ERROR(msg);
    199 }
    200 
    201 void *
    202 cint_cparser_alloc(unsigned int size)
    203 {
    204     return CINT_MALLOC(size);
    205 }
    206 
    207 #ifdef CINT_REALLOC
    208 
    209 /* System fully supports malloc/realloc/free */
    210 
    211 void
    212 cint_cparser_free(void *ptr)
    213 {
    214     CINT_FREE(ptr);
    215 }
    216 
    217 void *
    218 cint_cparser_realloc(void *ptr,  unsigned int size)
    219 {
    220     return CINT_REALLOC(ptr, size);
    221 }
    222 
    223 #else /* !CINT_REALLOC */
    224 
    225 /* 
    226    Some systems (like SDK SAL) do not support realloc. In that case,
    227    provide something that will work for FLEX, which is the only CINT
    228    component that needs it.
    229 
    230    This interface *just barely* supports the realloc semantics
    231    needed by the FLEX lexer.
    232 
    233      DO NOT USE FOR ANY OTHER PURPOSE
    234 
    235 */
    236 
    237 typedef struct {
    238     void *ptr;
    239     unsigned int size;
    240 } cint_alloc_info_t;
    241 
    242 #define MAX_ALLOC_INFO 10
    243 
    244 static cint_alloc_info_t cint_alloc_info[MAX_ALLOC_INFO];
    245 
    246 static cint_alloc_info_t *
    247 cint_cparser_realloc_find_slot(void *ptr)
    248 {
    249     int i;
    250     cint_alloc_info_t *info = NULL;
    251 
    252     for (i=0; i<MAX_ALLOC_INFO; i++) {
    253         if (cint_alloc_info[i].ptr == ptr) {
    254             info = cint_alloc_info + i;
    255             break;
    256         }
    257     }
    258 
    259     return info;
    260 }
    261 
    262 void
    263 cint_cparser_free(void *ptr)
    264 {
    265     if (ptr != NULL) {
    266         cint_alloc_info_t *info;
    267 
    268         info = cint_cparser_realloc_find_slot(ptr);
    269         if (info != NULL) {
    270             info->ptr = NULL;
    271             info->size = 0;
    272         }
    273         CINT_FREE(ptr);
    274     }
    275 }
    276 
    277 void *
    278 cint_cparser_realloc(void *ptr,  unsigned int size)
    279 {
    280     cint_alloc_info_t *info;
    281     void *new_ptr = NULL;
    282 
    283     info = cint_cparser_realloc_find_slot(ptr);
    284     if (info != NULL) {
    285         new_ptr = cint_cparser_alloc(size);
    286         if (new_ptr != NULL) {
    287             if (ptr != NULL) {
    288                 CINT_MEMCPY(new_ptr, ptr, info->size);
    289             }
    290             /* update info */
    291             info->ptr = new_ptr;
    292             info->size = size;
    293         }
    294     }
    295 
    296     cint_cparser_free(ptr);
    297 
    298     return new_ptr;
    299 }
    300 
    301 #endif /* CINT_REALLOC */
    302 
    303 #if CINT_CONFIG_INCLUDE_PARSER_READLINE == 1
    304 
    305 int 
    306 cint_cparser_input_readline(void *in, char* buf,
    307                             int* result, int max_size, int prompt)
    308 {
    309     FILE *yyin = (FILE *)in;
    310     char* b;
    311 
    312     if (cint_cparser_interactive()) {
    313         if (prompt) {
    314             cint_cparser_prompt(); 
    315         }
    316         b = CINT_READLINE(""); 
    317         if (b) { 
    318             /* Copy readline buffer */
    319             CINT_STRNCPY(buf, b, max_size-1); 
    320 
    321 #if defined(CINT_ADD_HISTORY) && CINT_CONFIG_INCLUDE_PARSER_ADD_HISTORY == 1
    322             CINT_ADD_HISTORY(buf); 
    323 #endif
    324             /* Restore newline. This is necessary to complete some scanner rules */
    325             CINT_STRNCAT(buf, "\n", 1); 
    326             
    327             *result = CINT_STRLEN(buf); 
    328 
    329             CINT_FREE(b); 
    330         } else { 
    331             /* Ctrl-D/EOF */
    332             char *e = "exit;";
    333             int len = CINT_STRLEN(e);
    334             if (max_size > len) {
    335                 /* buf is malloc'ed and may not be initialized, so
    336                    string copy operations here may make valgrind complain */
    337                 CINT_MEMCPY(buf, e, len+1); 
    338                 *result = CINT_STRLEN(buf);
    339             }
    340         } 
    341     } else {
    342 #if CINT_CONFIG_FILE_IO == 1
    343         if (((*result = CINT_FREAD( buf, 1, max_size, yyin )) == 0) &&
    344             CINT_FERROR( yyin ) ) { 
    345             return -1;
    346         }
    347 #else
    348         return -1;
    349 #endif
    350     }
    351 
    352     return 0;
    353 }
    354 
    355 #else
    356 
    357 /* The default YY_INPUT behavior  */
    358 int 
    359 cint_cparser_input_default(void *in, char* buf,
    360                            int* result, int max_size, int prompt)
    361 {
    362     FILE *yyin = (FILE *)in;
    363 
    364     if (cint_cparser_interactive()) {
    365         if (prompt) {
    366             cint_cparser_prompt(); 
    367         }
    368         int c = '*', n;
    369         for ( n = 0; n < max_size &&
    370                   (c = CINT_GETC( yyin )) != EOF && c != '\n'; ++n ) {
    371             buf[n] = (char) c;
    372         }
    373         if ( c == '\n' ) {
    374             buf[n++] = (char) c;
    375         }
    376         
    377         if ( c == EOF && CINT_FERROR( yyin ) ) {
    378             return -1;
    379         }
    380         *result = n;
    381     }
    382     else {
    383 #if CINT_CONFIG_FILE_IO == 1
    384         if ( ((*result = CINT_FREAD( buf, 1, max_size, yyin )) == 0) &&
    385               CINT_FERROR( yyin ) ) {
    386         return -1;
    387     }
    388 #else
    389         return -1;
    390 #endif
    391     }
    392 
    393     return 0;
    394 }       
    395 
    396 /* The default YY_INPUT behavior with optional character echo */
    397 int 
    398 cint_cparser_input_default_echo(void *in, char* buf,
    399                                 int* result, int max_size,
    400                                 int prompt, int echo)
    401 {
    402     FILE *yyin = (FILE *)in;
    403 
    404     if (cint_cparser_interactive()) {
    405         if (prompt) {
    406             cint_cparser_prompt(); 
    407         }
    408         int c = '*', n; 
    409         for ( n = 0; n < max_size && 
    410                   (c = CINT_GETC( yyin )) != EOF && c != '\n'; 
    411               ++n ) {
    412             buf[n] = (char) c; 
    413             if(echo==0) CINT_PRINTF("%c", c); 
    414         }       
    415         if ( c == '\n' ) {
    416             buf[n++] = (char) c; 
    417             if(echo==0) CINT_PRINTF("%c", c); 
    418         }       
    419         
    420         if ( c == EOF && CINT_FERROR( yyin ) ) {
    421             return -1; 
    422         }       
    423         *result = n; 
    424     } else {
    425 #if CINT_CONFIG_FILE_IO == 1
    426         if ( ((*result = CINT_FREAD( buf, 1, max_size, yyin )) == 0) &&
    427               CINT_FERROR( yyin ) ) {
    428         return -1;
    429     }   
    430 #else
    431         return -1;
    432 #endif /* CINT_CONFIG_FILE_IO */
    433     }   
    434     return 0;
    435 }       
    436 #endif
    437 
    438 void *
    439 cint_cparser_memcpy(void *dst, const void *src, int len)
    440 {
    441     return CINT_MEMCPY(dst, src, len);
    442 }
    443 
    444 void *
    445 cint_cparser_memset(void *dst, int c, int len)
    446 {
    447     return CINT_MEMSET(dst, c, len);
    448 }
    449 
    450 void
    451 cint_cparser_message(const char *msg, int len)
    452 {
    453     (void)CINT_PRINTF("*%s", msg); 
    454 }
    455 
    456 const char *
    457 cint_cparser_set_prompt(const char *prompt)
    458 {
    459     const char *old_prompt = __prompt;
    460 
    461     __prompt = prompt;
    462 
    463     return old_prompt;
    464 }
    465 
    466 int
    467 cint_cparser_interactive(void)
    468 {
    469     return (include_depth == 0 && __prompt != NULL);
    470 }
    471 
    472 int cint_cparser_include(int level)
    473 {
    474     int prev_depth = include_depth;
    475 
    476     include_depth += level;
    477     if (include_depth < 0) {
    478         CINT_FATAL_ERROR("include stack underflow");
    479     }
    480 
    481     return prev_depth;
    482 }