void gumbo_error_to_string( GumboParser* parser, const GumboError* error, GumboStringBuffer* output) { print_message( parser, output, "@%d:%d: ", error->position.line, error->position.column); switch (error->type) { case GUMBO_ERR_UTF8_INVALID: print_message( parser, output, "Invalid UTF8 character 0x%x", error->v.codepoint); break; case GUMBO_ERR_UTF8_TRUNCATED: print_message(parser, output, "Input stream ends with a truncated UTF8 character 0x%x", error->v.codepoint); break; case GUMBO_ERR_NUMERIC_CHAR_REF_NO_DIGITS: print_message( parser, output, "No digits after &# in numeric character reference"); break; case GUMBO_ERR_NUMERIC_CHAR_REF_WITHOUT_SEMICOLON: print_message(parser, output, "The numeric character reference &#%d should be followed " "by a semicolon", error->v.codepoint); break; case GUMBO_ERR_NUMERIC_CHAR_REF_INVALID: print_message(parser, output, "The numeric character reference &#%d; encodes an invalid " "unicode codepoint", error->v.codepoint); break; case GUMBO_ERR_NAMED_CHAR_REF_WITHOUT_SEMICOLON: // The textual data came from one of the literal strings in the table, and // so it'll be null-terminated. print_message(parser, output, "The named character reference &%.*s should be followed by a " "semicolon", (int) error->v.text.length, error->v.text.data); break; case GUMBO_ERR_NAMED_CHAR_REF_INVALID: print_message(parser, output, "The named character reference &%.*s; is not a valid entity name", (int) error->v.text.length, error->v.text.data); break; case GUMBO_ERR_DUPLICATE_ATTR: print_message(parser, output, "Attribute %s occurs multiple times, at positions %d and %d", error->v.duplicate_attr.name, error->v.duplicate_attr.original_index, error->v.duplicate_attr.new_index); break; case GUMBO_ERR_PARSER: case GUMBO_ERR_UNACKNOWLEDGED_SELF_CLOSING_TAG: handle_parser_error(parser, &error->v.parser, output); break; default: print_message(parser, output, "Tokenizer error with an unimplemented error message"); break; } gumbo_string_buffer_append_codepoint(parser, '.', output); }
static void print_tag_stack(const GumboParserError* error, GumboStringBuffer* output) { print_message(output, " Currently open tags: "); for (int i = 0; i < error->tag_stack.length; ++i) { if (i) { print_message(output, ", "); } GumboTag tag = (GumboTag) error->tag_stack.data[i]; print_message(output, gumbo_normalized_tagname(tag)); } gumbo_string_buffer_append_codepoint('.', output); }
void gumbo_caret_diagnostic_to_string(GumboParser* parser, const GumboError* error, const char* source_text, GumboStringBuffer* output) { gumbo_error_to_string(parser, error, output); const char* line_start = find_last_newline(source_text, error->original_text); const char* line_end = find_next_newline(source_text, error->original_text); GumboStringPiece original_line; original_line.data = line_start; original_line.length = line_end - line_start; gumbo_string_buffer_append_codepoint(parser, '\n', output); gumbo_string_buffer_append_string(parser, &original_line, output); gumbo_string_buffer_append_codepoint(parser, '\n', output); gumbo_string_buffer_reserve( parser, output->length + error->position.column, output); int num_spaces = error->position.column - 1; memset(output->data + output->length, ' ', num_spaces); output->length += num_spaces; gumbo_string_buffer_append_codepoint(parser, '^', output); gumbo_string_buffer_append_codepoint(parser, '\n', output); }
static void print_tag_stack(GumboParser* parser, const GumboParserError* error, GumboStringBuffer* output) { print_message(parser, output, " Currently open tags: "); for (unsigned int i = 0; i < error->tag_stack.length; ++i) { if (i) { print_message(parser, output, ", "); } unsigned int tmp = (unsigned int) (error->tag_stack.data[i]); GumboTag tag = (GumboTag)tmp; print_message(parser, output, gumbo_normalized_tagname(tag)); } gumbo_string_buffer_append_codepoint(parser, '.', output); }