diff options
author | Benjamin Otte <otte@redhat.com> | 2016-04-07 20:04:31 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2016-04-08 16:18:32 +0200 |
commit | 62b2f979e5ce33ae6ffcd90081ee64bfd6bc945a (patch) | |
tree | 1aa468c5e2c0d8594f24c35bc6eb5fd785580459 | |
parent | c6951488f963c676342161c82d182c944b889820 (diff) | |
download | gtk+-62b2f979e5ce33ae6ffcd90081ee64bfd6bc945a.tar.gz |
csstokenizer: Collect error, don't just emit it
This again is part of the quest to make it possible to "undo" reading
a token.
-rw-r--r-- | gtk/gtkcsstokenizer.c | 122 |
1 files changed, 75 insertions, 47 deletions
diff --git a/gtk/gtkcsstokenizer.c b/gtk/gtkcsstokenizer.c index 8801cecd10..171c7f2a23 100644 --- a/gtk/gtkcsstokenizer.c +++ b/gtk/gtkcsstokenizer.c @@ -52,6 +52,13 @@ gtk_css_location_init (GtkCssLocation *location) } static void +gtk_css_location_init_copy (GtkCssLocation *location, + const GtkCssLocation *source) +{ + *location = *source; +} + +static void gtk_css_location_advance (GtkCssLocation *location, gsize bytes, gsize chars) @@ -551,31 +558,39 @@ gtk_css_tokenizer_get_location (GtkCssTokenizer *tokenizer) } static void -gtk_css_tokenizer_parse_error (GtkCssTokenizer *tokenizer, - const GtkCssToken *token, - const char *format, - ...) G_GNUC_PRINTF(3, 4); +set_parse_error (GError **error, + const char *format, + ...) G_GNUC_PRINTF(2, 3); static void -gtk_css_tokenizer_parse_error (GtkCssTokenizer *tokenizer, - const GtkCssToken *token, - const char *format, - ...) +set_parse_error (GError **error, + const char *format, + ...) { - GError *error; va_list args; - va_start (args, format); - error = g_error_new_valist (GTK_CSS_PROVIDER_ERROR, - GTK_CSS_PROVIDER_ERROR_SYNTAX, - format, args); + if (error == NULL) + return; + + g_assert (*error == NULL); + + va_start (args, format); + *error = g_error_new_valist (GTK_CSS_PROVIDER_ERROR, + GTK_CSS_PROVIDER_ERROR_SYNTAX, + format, + args); va_end (args); +} +static void +gtk_css_tokenizer_emit_error (GtkCssTokenizer *tokenizer, + const GtkCssLocation *location, + const GtkCssToken *token, + const GError *error) +{ if (tokenizer->error_func) tokenizer->error_func (tokenizer, token, error, tokenizer->user_data); else - g_print ("error: %s\n", error->message); - - g_error_free (error); + g_warning ("Unhandled CSS error: %zu:%zu: %s", location->lines + 1, location->line_chars + 1, error->message); } static gboolean @@ -869,9 +884,9 @@ gtk_css_token_reader_read_bad_url (GtkCssTokenReader *reader, } static void -gtk_css_token_reader_read_url (GtkCssTokenizer *tokenizer, - GtkCssTokenReader *reader, - GtkCssToken *token) +gtk_css_token_reader_read_url (GtkCssTokenReader *reader, + GtkCssToken *token, + GError **error) { GString *url = g_string_new (NULL); @@ -903,7 +918,7 @@ gtk_css_token_reader_read_url (GtkCssTokenizer *tokenizer, else { gtk_css_token_reader_read_bad_url (reader, token); - gtk_css_tokenizer_parse_error (tokenizer, token, "Whitespace only allowed at start and end of url"); + set_parse_error (error, "Whitespace only allowed at start and end of url"); return; } } @@ -911,7 +926,7 @@ gtk_css_token_reader_read_url (GtkCssTokenizer *tokenizer, { gtk_css_token_reader_read_bad_url (reader, token); g_string_free (url, TRUE); - gtk_css_tokenizer_parse_error (tokenizer, token, "Nonprintable character 0x%02X in url", *reader->data); + set_parse_error (error, "Nonprintable character 0x%02X in url", *reader->data); return; } else if (*reader->data == '"' || @@ -919,7 +934,7 @@ gtk_css_token_reader_read_url (GtkCssTokenizer *tokenizer, *reader->data == '(') { gtk_css_token_reader_read_bad_url (reader, token); - gtk_css_tokenizer_parse_error (tokenizer, token, "Invalid character %c in url", *reader->data); + set_parse_error (error, "Invalid character %c in url", *reader->data); g_string_free (url, TRUE); return; } @@ -930,7 +945,7 @@ gtk_css_token_reader_read_url (GtkCssTokenizer *tokenizer, else if (*reader->data == '\\') { gtk_css_token_reader_read_bad_url (reader, token); - gtk_css_tokenizer_parse_error (tokenizer, token, "Newline may not follow '\' escape character"); + set_parse_error (error, "Newline may not follow '\' escape character"); g_string_free (url, TRUE); return; } @@ -944,9 +959,9 @@ gtk_css_token_reader_read_url (GtkCssTokenizer *tokenizer, } static void -gtk_css_token_reader_read_ident_like (GtkCssTokenizer *tokenizer, - GtkCssTokenReader *reader, - GtkCssToken *token) +gtk_css_token_reader_read_ident_like (GtkCssTokenReader *reader, + GtkCssToken *token, + GError **error) { char *name = gtk_css_token_reader_read_name (reader); @@ -963,7 +978,7 @@ gtk_css_token_reader_read_ident_like (GtkCssTokenizer *tokenizer, if (*data != '"' && *data != '\'') { - gtk_css_token_reader_read_url (tokenizer, reader, token); + gtk_css_token_reader_read_url (reader, token, error); return; } } @@ -1083,9 +1098,9 @@ gtk_css_token_reader_read_delim (GtkCssTokenReader *reader, } static void -gtk_css_token_reader_read_dash (GtkCssTokenizer *tokenizer, - GtkCssTokenReader *reader, - GtkCssToken *token) +gtk_css_token_reader_read_dash (GtkCssTokenReader *reader, + GtkCssToken *token, + GError **error) { if (gtk_css_token_reader_remaining (reader) == 1) { @@ -1104,7 +1119,7 @@ gtk_css_token_reader_read_dash (GtkCssTokenizer *tokenizer, } else if (gtk_css_token_reader_has_identifier (reader)) { - gtk_css_token_reader_read_ident_like (tokenizer, reader, token); + gtk_css_token_reader_read_ident_like (reader, token, error); } else { @@ -1113,9 +1128,9 @@ gtk_css_token_reader_read_dash (GtkCssTokenizer *tokenizer, } static void -gtk_css_token_reader_read_string (GtkCssTokenizer *tokenizer, - GtkCssTokenReader *reader, - GtkCssToken *token) +gtk_css_token_reader_read_string (GtkCssTokenReader *reader, + GtkCssToken *token, + GError **error) { GString *string = g_string_new (NULL); char end = *reader->data; @@ -1150,7 +1165,7 @@ gtk_css_token_reader_read_string (GtkCssTokenizer *tokenizer, { g_string_free (string, TRUE); gtk_css_token_init (token, GTK_CSS_TOKEN_BAD_STRING); - gtk_css_tokenizer_parse_error (tokenizer, token, "Newlines inside strings must be escaped"); + set_parse_error (error, "Newlines inside strings must be escaped"); return; } else @@ -1163,9 +1178,9 @@ gtk_css_token_reader_read_string (GtkCssTokenizer *tokenizer, } static void -gtk_css_token_reader_read_comment (GtkCssTokenizer *tokenizer, - GtkCssTokenReader *reader, - GtkCssToken *token) +gtk_css_token_reader_read_comment (GtkCssTokenReader *reader, + GtkCssToken *token, + GError **error) { gtk_css_token_reader_consume (reader, 2, 2); @@ -1182,7 +1197,7 @@ gtk_css_token_reader_read_comment (GtkCssTokenizer *tokenizer, } gtk_css_token_init (token, GTK_CSS_TOKEN_COMMENT); - gtk_css_tokenizer_parse_error (tokenizer, token, "Comment not terminated at end of document."); + set_parse_error (error, "Comment not terminated at end of document."); } static void @@ -1206,6 +1221,7 @@ gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer, GtkCssToken *token) { GtkCssTokenReader reader; + GError *error = NULL; if (tokenizer->reader.data == tokenizer->reader.end) { @@ -1218,7 +1234,7 @@ gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer, if (reader.data[0] == '/' && gtk_css_token_reader_remaining (&reader) > 1 && reader.data[1] == '*') { - gtk_css_token_reader_read_comment (tokenizer, &reader, token); + gtk_css_token_reader_read_comment (&reader, token, &error); goto out; } @@ -1233,7 +1249,7 @@ gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer, break; case '"': - gtk_css_token_reader_read_string (tokenizer, &reader, token); + gtk_css_token_reader_read_string (&reader, token, &error); break; case '#': @@ -1262,7 +1278,7 @@ gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer, break; case '\'': - gtk_css_token_reader_read_string (tokenizer, &reader, token); + gtk_css_token_reader_read_string (&reader, token, &error); break; case '(': @@ -1292,7 +1308,7 @@ gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer, break; case '-': - gtk_css_token_reader_read_dash (tokenizer, &reader, token); + gtk_css_token_reader_read_dash (&reader, token, &error); break; case '.': @@ -1349,12 +1365,12 @@ gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer, case '\\': if (gtk_css_token_reader_has_valid_escape (&reader)) { - gtk_css_token_reader_read_ident_like (tokenizer, &reader, token); + gtk_css_token_reader_read_ident_like (&reader, token, &error); } else { gtk_css_token_init (token, GTK_CSS_TOKEN_DELIM, '\\'); - gtk_css_tokenizer_parse_error (tokenizer, token, "Newline may not follow '\' escape character"); + set_parse_error (&error, "Newline may not follow '\' escape character"); } break; @@ -1400,7 +1416,7 @@ gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer, } else if (is_name_start (*reader.data)) { - gtk_css_token_reader_read_ident_like (tokenizer, &reader, token); + gtk_css_token_reader_read_ident_like (&reader, token, &error); } else gtk_css_token_reader_read_delim (&reader, token); @@ -1408,6 +1424,18 @@ gtk_css_tokenizer_read_token (GtkCssTokenizer *tokenizer, } out: - gtk_css_token_reader_init_copy (&tokenizer->reader, &reader); + if (error != NULL) + { + GtkCssLocation error_location; + + gtk_css_location_init_copy (&error_location, &reader.position); + gtk_css_token_reader_init_copy (&tokenizer->reader, &reader); + gtk_css_tokenizer_emit_error (tokenizer, &error_location, token, error); + g_error_free (error); + } + else + { + gtk_css_token_reader_init_copy (&tokenizer->reader, &reader); + } } |