diff --git a/lexer/theme-lexer.l b/lexer/theme-lexer.l index 038d2a03..fae85b1b 100644 --- a/lexer/theme-lexer.l +++ b/lexer/theme-lexer.l @@ -29,12 +29,14 @@ typedef struct _ParseObject { /** File pointer */ FILE *filein; + char *filename; /** Length of string */ int str_len; /** String */ const char *input_str; - + /** Position in file */ + YYLTYPE location; } ParseObject; GQueue *file_queue = NULL; @@ -182,23 +184,37 @@ if ( queue == NULL ){ \"{STRING}\" { yytext[yyleng-1] = '\0'; + ParseObject *top = g_queue_peek_head ( file_queue ); + g_assert ( top != NULL ); char *filename = rofi_expand_path ( &yytext[1] ); + // If no absolute path specified, expand it. + if ( ! g_path_is_absolute ( filename ) && top->type == PT_FILE ) { + char *basedir = g_path_get_dirname ( top->filename ); + char *path = g_build_filename ( basedir, filename, NULL ); + g_free ( filename); + filename = path; + g_free ( basedir ); + } FILE *f = fopen ( filename, "rb" ); if ( f ) { + top->location = *yylloc; ParseObject *po = g_malloc0(sizeof(ParseObject)); po->type = PT_FILE; + po->filename = filename; po->filein = f; current = po; g_queue_push_head ( file_queue, po ); yypush_buffer_state (yy_create_buffer ( 0, YY_BUF_SIZE )); + yylloc->first_line = yylloc->last_line = 1; + yylloc->first_column = yylloc->last_column = 1; } else { char *str = g_markup_printf_escaped ( "Failed to open theme: %s\nError: %s", filename, strerror ( errno ) ); rofi_add_error_message ( g_string_new ( str ) ); g_free ( str ); + g_free(filename); } - g_free(filename); // Pop out of include. */ BEGIN(GPOINTER_TO_INT(g_queue_pop_head ( queue ))); } @@ -408,6 +424,7 @@ if ( queue == NULL ){ if ( po ) { if ( po->type == PT_FILE ){ fclose ( po->filein ); + g_free ( po->filename ); } g_free ( po ); } @@ -420,6 +437,7 @@ if ( queue == NULL ){ } else { yypop_buffer_state(); current = po; + *yylloc = current->location; BEGIN(GPOINTER_TO_INT ( g_queue_pop_head ( queue ))); } } @@ -447,8 +465,8 @@ if ( queue == NULL ){ . { return T_ERROR_DEFAULTS; } -<*>. { - return T_ERROR; +. { + return T_ERROR_INCLUDE; } %% @@ -469,13 +487,13 @@ gboolean rofi_theme_parse_file ( const char *file ) file_queue = g_queue_new (); ParseObject *po = g_malloc0(sizeof(ParseObject)); po->type = PT_FILE; + po->filename = filename; po->filein = yyin; current = po; g_queue_push_head ( file_queue, po ); int parser_retv = yyparse ( file ); yylex_destroy (); - g_free ( filename ); yyin = NULL; // Free up. diff --git a/lexer/theme-parser.y b/lexer/theme-parser.y index fcbc0f49..81a91486 100644 --- a/lexer/theme-parser.y +++ b/lexer/theme-parser.y @@ -1,9 +1,9 @@ %define api.pure +%define parse.error verbose %locations %glr-parser %skeleton "glr.c" %debug -%error-verbose %parse-param {const char *what} %code requires { #include "theme.h" @@ -25,7 +25,7 @@ int yylex (YYSTYPE *, YYLTYPE *); char *sval; int bval; ThemeColor colorval; - ThemeWidget *theme; + ThemeWidget *theme; GList *name_path; Property *property; GHashTable *property_list; @@ -38,6 +38,7 @@ int yylex (YYSTYPE *, YYLTYPE *); %token T_ERROR_ENTRY 3 "invalid property name" %token T_ERROR_NAMESTRING 4 "invalid element name" %token T_ERROR_DEFAULTS 5 "invalid defaults name" +%token T_ERROR_INCLUDE 6 "invalid import value" %token T_INT %token T_DOUBLE %token T_STRING @@ -56,7 +57,7 @@ int yylex (YYSTYPE *, YYLTYPE *); %token PSEP "property separator" %token PCLOSE "property close" %token NSEP "Name separator" -%token NAME_PREFIX "Name element prefix ('#')" +%token NAME_PREFIX "Element section ('# {name} { ... }')" %token WHITESPACE "White space" %token PDEFAULTS "Default settings section ( '* { ... }')" diff --git a/source/theme.c b/source/theme.c index 8839128b..26824275 100644 --- a/source/theme.c +++ b/source/theme.c @@ -267,7 +267,7 @@ void yyerror ( YYLTYPE *yylloc, const char *what, const char* s ) { char *what_esc = g_markup_escape_text ( what, -1 ); GString *str = g_string_new ( "" ); - g_string_printf ( str, "Error while parsing them: %s\n", what_esc ); + g_string_printf ( str, "Error while parsing theme: %s\n", what_esc ); g_free ( what_esc ); char *esc = g_markup_escape_text ( s, -1 ); g_string_append_printf ( str, "\tParser error: %s\n", esc );