2020-02-28 12:36:12 +03:00
// SPDX-License-Identifier: GPL-2.0
2020-02-28 12:36:13 +03:00
# include <stdbool.h>
2020-02-28 12:36:12 +03:00
# include <assert.h>
# include "expr.h"
2020-02-28 12:36:13 +03:00
# include "expr-bison.h"
# include "expr-flex.h"
# ifdef PARSER_DEBUG
extern int expr_debug ;
# endif
2020-02-28 12:36:12 +03:00
/* Caller must make sure id is allocated */
2020-04-01 23:33:34 +03:00
void expr__add_id ( struct expr_parse_ctx * ctx , const char * name , double val )
2020-02-28 12:36:12 +03:00
{
int idx ;
assert ( ctx - > num_ids < MAX_PARSE_ID ) ;
idx = ctx - > num_ids + + ;
ctx - > ids [ idx ] . name = name ;
ctx - > ids [ idx ] . val = val ;
}
2020-04-01 23:33:34 +03:00
void expr__ctx_init ( struct expr_parse_ctx * ctx )
2020-02-28 12:36:12 +03:00
{
ctx - > num_ids = 0 ;
}
2020-02-28 12:36:13 +03:00
static int
2020-04-01 23:33:34 +03:00
__expr__parse ( double * val , struct expr_parse_ctx * ctx , const char * expr ,
2020-02-28 12:36:13 +03:00
int start )
{
2020-04-01 23:33:35 +03:00
struct expr_scanner_ctx scanner_ctx = {
. start_token = start ,
} ;
2020-02-28 12:36:13 +03:00
YY_BUFFER_STATE buffer ;
void * scanner ;
int ret ;
2020-04-01 23:33:35 +03:00
ret = expr_lex_init_extra ( & scanner_ctx , & scanner ) ;
2020-02-28 12:36:13 +03:00
if ( ret )
return ret ;
buffer = expr__scan_string ( expr , scanner ) ;
# ifdef PARSER_DEBUG
expr_debug = 1 ;
# endif
ret = expr_parse ( val , ctx , scanner ) ;
expr__flush_buffer ( buffer , scanner ) ;
expr__delete_buffer ( buffer , scanner ) ;
expr_lex_destroy ( scanner ) ;
return ret ;
}
2020-04-01 23:33:34 +03:00
int expr__parse ( double * final_val , struct expr_parse_ctx * ctx , const char * expr )
2020-02-28 12:36:13 +03:00
{
2020-02-28 12:36:16 +03:00
return __expr__parse ( final_val , ctx , expr , EXPR_PARSE ) ? - 1 : 0 ;
2020-02-28 12:36:13 +03:00
}
static bool
already_seen ( const char * val , const char * one , const char * * other ,
int num_other )
{
int i ;
if ( one & & ! strcasecmp ( one , val ) )
return true ;
for ( i = 0 ; i < num_other ; i + + )
if ( ! strcasecmp ( other [ i ] , val ) )
return true ;
return false ;
}
2020-02-28 12:36:15 +03:00
int expr__find_other ( const char * expr , const char * one , const char * * * other ,
2020-02-28 12:36:13 +03:00
int * num_other )
{
int err , i = 0 , j = 0 ;
2020-04-01 23:33:34 +03:00
struct expr_parse_ctx ctx ;
2020-02-28 12:36:13 +03:00
expr__ctx_init ( & ctx ) ;
2020-02-28 12:36:15 +03:00
err = __expr__parse ( NULL , & ctx , expr , EXPR_OTHER ) ;
2020-02-28 12:36:13 +03:00
if ( err )
return - 1 ;
* other = malloc ( ( ctx . num_ids + 1 ) * sizeof ( char * ) ) ;
if ( ! * other )
return - ENOMEM ;
for ( i = 0 , j = 0 ; i < ctx . num_ids ; i + + ) {
const char * str = ctx . ids [ i ] . name ;
if ( already_seen ( str , one , * other , j ) )
continue ;
str = strdup ( str ) ;
if ( ! str )
goto out ;
( * other ) [ j + + ] = str ;
}
( * other ) [ j ] = NULL ;
out :
if ( i ! = ctx . num_ids ) {
while ( - - j )
free ( ( char * ) ( * other ) [ i ] ) ;
free ( * other ) ;
err = - 1 ;
}
* num_other = j ;
return err ;
}