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 }