LCOV - code coverage report
Current view: top level - libgfs2 - parser.y (source / functions) Hit Total Coverage
Test: gfs2-utils.info Lines: 39 94 41.5 %
Date: 2023-10-25 12:04:14 Functions: 3 5 60.0 %

          Line data    Source code
       1             : %code requires {
       2             : /* Required to break a circular dependency introduced with bison 2.6 */
       3             : typedef void* yyscan_t;
       4             : }
       5             : %code top {
       6             : #include <errno.h>
       7             : #include "lang.h"
       8             : #include "lexer.h"
       9             : 
      10           0 : static int yyerror(struct lgfs2_lang_state *state, yyscan_t lexer, const char *errorstr)
      11             : {
      12           0 :         fprintf(stderr, "%d:%d: %s\n", state->ls_linenum, state->ls_colnum, errorstr);
      13           0 :         return 1;
      14             : }
      15             : 
      16             : }
      17             : %defines
      18             : %debug
      19             : %define api.pure
      20             : %parse-param { struct lgfs2_lang_state *state }
      21             : %parse-param { yyscan_t lexer }
      22             : %lex-param { yyscan_t lexer }
      23             : %start script
      24             : %token TOK_COLON
      25             : %token TOK_COMMA
      26             : %token TOK_ID
      27             : %token TOK_LBRACE
      28             : %token TOK_LBRACKET
      29             : %token TOK_NUMBER
      30             : %token TOK_OFFSET
      31             : %token TOK_RBRACE
      32             : %token TOK_RBRACKET
      33             : %token TOK_SEMI
      34             : %token TOK_SET
      35             : %token TOK_GET
      36             : %token TOK_STATE
      37             : %token TOK_STRING
      38             : %token TOK_PATH
      39             : %%
      40             : script: statements {
      41           8 :                 state->ls_ast_root = $1;
      42           8 :                 state->ls_interp_curr = $1;
      43             :         }
      44             :         | statements TOK_SEMI {
      45           0 :                 state->ls_ast_root = $1;
      46           0 :                 state->ls_interp_curr = $1;
      47             :         }
      48             : ;
      49             : statements: statements TOK_SEMI statement {
      50           0 :                 state->ls_ast_tail->ast_left = $3;
      51           0 :                 state->ls_ast_tail = $3;
      52           0 :                 $$ = $1;
      53             :         }
      54             :         | statement {
      55           8 :                 if (state->ls_ast_tail == NULL)
      56           8 :                         state->ls_ast_tail = $1;
      57           8 :                 $$ = $1;
      58             :         }
      59             : ;
      60           8 : statement: set_stmt { $$ = $1;}
      61           0 :         | get_stmt { $$ = $1; }
      62             : ;
      63             : set_stmt: TOK_SET blockspec structspec {
      64           8 :                 $1->ast_right = $2;
      65           8 :                 $2->ast_right = $3;
      66           8 :                 $$ = $1;
      67             :         }
      68             :         | TOK_SET blockspec typespec structspec {
      69           0 :                 $1->ast_right = $2;
      70           0 :                 $2->ast_right = $3;
      71           0 :                 $3->ast_right = $4;
      72           0 :                 $$ = $1;
      73             :         }
      74             : ;
      75             : get_stmt: TOK_GET blockspec {
      76           0 :                 $1->ast_right = $2; $$ = $1;
      77             :         }
      78             :         | TOK_GET blockspec TOK_STATE {
      79           0 :                 $1->ast_right = $2;
      80           0 :                 $2->ast_right = $3;
      81           0 :                 $$ = $1;
      82             :         }
      83             : ;
      84           0 : blockspec: offset { $$ = $1; }
      85           0 :         | address { $$ = $1; }
      86           1 :         | path { $$ = $1; }
      87           7 :         | block_literal { $$ = $1; }
      88           0 :         | subscript { $$ = $1; }
      89             : ;
      90             : offset: blockspec TOK_OFFSET {
      91           0 :                 $2->ast_left = $1;
      92           0 :                 $$ = $2;
      93             :         }
      94             : ;
      95             : typespec: identifier {
      96           0 :                 $1->ast_type = AST_EX_TYPESPEC;
      97           0 :                 $$ = $1;
      98             :         }
      99             : ;
     100           7 : block_literal: identifier { $$ = $1; }
     101             : ;
     102             : subscript: block_literal TOK_LBRACKET index TOK_RBRACKET {
     103           0 :                 $4->ast_left = $1;
     104           0 :                 $1->ast_left = $3;
     105           0 :                 $$ = $4;
     106             :         }
     107             : ;
     108           0 : index: number { $$ = $1; }
     109           0 :         | identifier { $$ = $1; }
     110             : ;
     111             : address: number {
     112           0 :                 $1->ast_type = AST_EX_ADDRESS;
     113           0 :                 $$ = $1;
     114             :          }
     115             : ;
     116           8 : structspec: TOK_LBRACE fieldspecs TOK_RBRACE { $$ = $2; }
     117           0 :         | TOK_LBRACE TOK_RBRACE { $$ = NULL; }
     118             : ;
     119             : fieldspecs: fieldspecs TOK_COMMA fieldspec {
     120           0 :                 $1->ast_left = $3;
     121           0 :                 $$ = $1;
     122             :         }
     123           8 :         | fieldspec { $$ = $1; }
     124             : ;
     125             : fieldspec: identifier TOK_COLON fieldvalue {
     126           8 :                 $2->ast_right = $1;
     127           8 :                 $1->ast_right = $3;
     128           8 :                 $$ = $2;
     129             :         }
     130             : ;
     131           8 : fieldvalue: number { $$ = $1; }
     132           0 :         | string { $$ = $1; }
     133             : ;
     134           8 : number: TOK_NUMBER { $$ = $1; }
     135           0 : string: TOK_STRING { $$ = $1; }
     136          15 : identifier: TOK_ID { $$ = $1; }
     137           1 : path: TOK_PATH { $$ = $1; }
     138             : %%
     139             : 
     140             : /**
     141             :  * Allocate and initialize a new parse state structure. The caller must free the
     142             :  * memory returned by this function.
     143             :  */
     144           8 : struct lgfs2_lang_state *lgfs2_lang_init(void)
     145             : {
     146             :         struct lgfs2_lang_state *state;
     147           8 :         state = calloc(1, sizeof(struct lgfs2_lang_state));
     148           8 :         if (state == NULL) {
     149           0 :                 return NULL;
     150             :         }
     151           8 :         state->ls_linenum = 1;
     152           8 :         return state;
     153             : }
     154             : 
     155           8 : void lgfs2_lang_free(struct lgfs2_lang_state **state)
     156             : {
     157           8 :         ast_destroy(&(*state)->ls_ast_root);
     158           8 :         free(*state);
     159           8 :         *state = NULL;
     160           8 : }
     161             : 
     162           8 : int lgfs2_lang_parsef(struct lgfs2_lang_state *state, FILE *src)
     163             : {
     164           8 :         int ret = 0;
     165             :         yyscan_t lexer;
     166             : 
     167           8 :         ret = yylex_init_extra(state, &lexer);
     168           8 :         if (ret != 0) {
     169           0 :                 fprintf(stderr, "Failed to initialize lexer.\n");
     170           0 :                 return ret;
     171             :         }
     172             : 
     173           8 :         yyset_in(src, lexer);
     174           8 :         ret = yyparse(state, lexer);
     175           8 :         yylex_destroy(lexer);
     176           8 :         return ret;
     177             : }
     178             : 
     179           0 : int lgfs2_lang_parses(struct lgfs2_lang_state *state, const char *cstr)
     180             : {
     181             :         int ret;
     182             :         FILE *src;
     183           0 :         char *str = strdup(cstr);
     184             : 
     185           0 :         if (str == NULL) {
     186           0 :                 perror("Failed to duplicate source string");
     187           0 :                 return 1;
     188             :         }
     189             :         /* coverity[alloc_strlen:SUPPRESS] False positive */
     190           0 :         src = fmemopen(str, strlen(str), "r");
     191           0 :         if (src == NULL) {
     192           0 :                 perror("Failed to open string as source file");
     193           0 :                 free(str);
     194           0 :                 return 1;
     195             :         }
     196           0 :         ret = lgfs2_lang_parsef(state, src);
     197           0 :         fclose(src);
     198           0 :         free(str);
     199           0 :         if (ret != 0 || state->ls_errnum != 0) {
     200           0 :                 return 1;
     201             :         }
     202           0 :         return 0;
     203             : }

Generated by: LCOV version 1.14