ali@17: #include ali@17: #include ali@17: #include ali@17: #include "testcase.h" ali@17: #include "warningsparser.h" ali@17: ali@17: /* ali@17: * A GMarkupParser for the contents of a WARNINGS tag. ali@17: */ ali@17: ali@17: typedef struct { ali@17: Testcase *testcase; ali@17: TestcaseWarning *warning; ali@17: TestcaseLocation *location; ali@17: enum { ali@17: WARNINGS_INIT, ali@17: WARNINGS_IN_EXPECTED, ali@17: WARNINGS_IN_WARNING, ali@17: WARNINGS_IN_AT, ali@17: WARNINGS_IN_TEXT, ali@17: WARNINGS_DONE, ali@17: } state; ali@17: } WarningsBaton; ali@17: ali@17: static void warnings_parser_start_element(GMarkupParseContext *context, ali@17: const char *element_name,const char **attribute_names, ali@17: const char **attribute_values,void *user_data,GError **error) ali@17: { ali@17: int i; ali@17: guint64 tmp; ali@17: char *endp; ali@17: WarningsBaton *baton=user_data; ali@17: switch(baton->state) ali@17: { ali@17: case WARNINGS_INIT: ali@17: if (strcmp(element_name,"expected")) ali@17: g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT, ali@17: "Unknown root element: '%s'",element_name); ali@17: else if (attribute_names[0]) ali@17: g_set_error(error,G_MARKUP_ERROR, ali@17: G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, ali@17: "Unknown attribute on element 'expected': '%s'", ali@17: attribute_names[0]); ali@17: else ali@17: baton->state=WARNINGS_IN_EXPECTED; ali@17: break; ali@17: case WARNINGS_IN_EXPECTED: ali@17: baton->warning=g_new0(TestcaseWarning,1); ali@17: if (!strcmp(element_name,"error")) ali@17: baton->warning->is_real=TRUE; ali@17: else if (!strcmp(element_name,"false-positive")) ali@17: baton->warning->xfail=TRUE; ali@17: else if (!strcmp(element_name,"false-negative")) ali@17: baton->warning->is_real=baton->warning->xfail=TRUE; ali@17: else ali@17: { ali@17: g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT, ali@17: "Unknown element in 'expected': '%s'",element_name); ali@17: g_free(baton->warning); ali@17: baton->warning=NULL; ali@17: return; ali@17: } ali@17: if (attribute_names[0]) ali@17: { ali@17: g_set_error(error,G_MARKUP_ERROR, ali@17: G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, ali@17: "Unknown attribute on element '%s': '%s'",element_name, ali@17: attribute_names[0]); ali@17: g_free(baton->warning); ali@17: baton->warning=NULL; ali@17: return; ali@17: } ali@17: else ali@17: baton->state=WARNINGS_IN_WARNING; ali@17: break; ali@17: case WARNINGS_IN_WARNING: ali@17: if (!strcmp(element_name,"at")) ali@17: { ali@17: baton->location=g_new0(TestcaseLocation,1); ali@17: for(i=0;attribute_names[i];i++) ali@17: { ali@17: if (!strcmp(attribute_names[i],"line")) ali@17: { ali@17: tmp=g_ascii_strtoull(attribute_values[i],&endp,0); ali@17: if (tmp<1 || tmp>G_MAXUINT || tmp==G_MAXUINT64) ali@17: { ali@17: g_set_error(error,G_MARKUP_ERROR, ali@17: G_MARKUP_ERROR_INVALID_CONTENT,"Invalid value " ali@17: "for attribute 'line' on element '%s': '%s'", ali@17: element_name,attribute_values[i]); ali@17: return; ali@17: } ali@17: baton->location->line=(guint)tmp; ali@17: } ali@17: else if (!strcmp(attribute_names[i],"column")) ali@17: { ali@17: tmp=g_ascii_strtoull(attribute_values[i],&endp,0); ali@17: if (tmp<1 || tmp>G_MAXUINT || tmp==G_MAXUINT64) ali@17: { ali@17: g_set_error(error,G_MARKUP_ERROR, ali@17: G_MARKUP_ERROR_INVALID_CONTENT,"Invalid value " ali@17: "for attribute 'column' on element '%s': '%s'", ali@17: element_name,attribute_values[i]); ali@17: return; ali@17: } ali@17: baton->location->column=(guint)tmp; ali@17: } ali@17: else ali@17: { ali@17: g_set_error(error,G_MARKUP_ERROR, ali@17: G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, ali@17: "Unknown attribute on element '%s': '%s'", ali@17: element_name,attribute_names[i]); ali@17: return; ali@17: } ali@17: } ali@17: if (!baton->location->line) ali@17: { ali@17: g_set_error(error,G_MARKUP_ERROR, ali@17: G_MARKUP_ERROR_MISSING_ATTRIBUTE, ali@17: "Missing attribute on element '%s': 'line'",element_name); ali@17: return; ali@17: } ali@17: baton->state=WARNINGS_IN_AT; ali@17: } ali@17: else if (!strcmp(element_name,"text")) ali@17: { ali@17: if (attribute_names[0]) ali@17: { ali@17: g_set_error(error,G_MARKUP_ERROR, ali@17: G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, ali@17: "Unknown attribute on element 'text': '%s'", ali@17: attribute_names[0]); ali@17: return; ali@17: } ali@17: baton->state=WARNINGS_IN_TEXT; ali@17: } ali@17: break; ali@17: case WARNINGS_IN_AT: ali@17: g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT, ali@17: "Unknown element in 'at': '%s'",element_name); ali@17: return; ali@17: case WARNINGS_IN_TEXT: ali@17: g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT, ali@17: "Unknown element in 'text': '%s'",element_name); ali@17: return; ali@17: default: ali@17: g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT, ali@17: "Unexpected element: '%s'",element_name); ali@17: return; ali@17: } ali@17: } ali@17: ali@17: static void warnings_parser_end_element(GMarkupParseContext *context, ali@17: const char *element_name,void *user_data,GError **error) ali@17: { ali@17: WarningsBaton *baton=user_data; ali@17: switch(baton->state) ali@17: { ali@17: case WARNINGS_IN_EXPECTED: ali@17: baton->testcase->warnings= ali@17: g_slist_reverse(baton->testcase->warnings); ali@17: baton->state=WARNINGS_DONE; ali@17: break; ali@17: case WARNINGS_IN_WARNING: ali@17: baton->warning->locations= ali@17: g_slist_reverse(baton->warning->locations); ali@17: baton->testcase->warnings=g_slist_prepend(baton->testcase->warnings, ali@17: baton->warning); ali@17: baton->warning=NULL; ali@17: baton->state=WARNINGS_IN_EXPECTED; ali@17: break; ali@17: case WARNINGS_IN_AT: ali@17: baton->warning->locations=g_slist_prepend(baton->warning->locations, ali@17: baton->location); ali@17: baton->location=NULL; ali@17: baton->state=WARNINGS_IN_WARNING; ali@17: break; ali@17: case WARNINGS_IN_TEXT: ali@17: baton->state=WARNINGS_IN_WARNING; ali@17: break; ali@17: default: ali@17: g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT, ali@17: "Unexpected element ending: '%s'",element_name); ali@17: return; ali@17: } ali@17: } ali@17: ali@17: static void warnings_parser_text(GMarkupParseContext *context, ali@17: const char *text,gsize text_len,void *user_data,GError **error) ali@17: { ali@17: char *s,*t; ali@17: WarningsBaton *baton=user_data; ali@17: switch(baton->state) ali@17: { ali@17: case WARNINGS_IN_EXPECTED: ali@17: if (strspn(text," \t\n")!=text_len) ali@17: g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT, ali@17: "The 'expected' tag does not take any content"); ali@17: break; ali@17: case WARNINGS_IN_WARNING: ali@17: if (strspn(text," \t\n")!=text_len) ali@17: g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT, ali@17: "The warning tags do not take any content"); ali@17: break; ali@17: case WARNINGS_IN_AT: ali@17: if (strspn(text," \t\n")!=text_len) ali@17: g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT, ali@17: "The 'at' tag does not take any content"); ali@17: break; ali@17: case WARNINGS_IN_TEXT: ali@17: s=g_strdup(text+strspn(text," \t\n")); ali@17: g_strchomp(s); ali@17: if (baton->warning->text) ali@17: { ali@17: t=g_strconcat(baton->warning->text,s,NULL); ali@17: g_free(baton->warning->text); ali@17: g_free(s); ali@17: baton->warning->text=t; ali@17: } ali@17: else ali@17: baton->warning->text=s; ali@17: break; ali@17: default: ali@17: g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT, ali@17: "Unexpected content: '%s'",text); ali@17: return; ali@17: } ali@17: } ali@17: ali@17: GMarkupParseContext *warnings_parse_context_new(Testcase *testcase) ali@17: { ali@17: static GMarkupParser parser={0}; ali@17: WarningsBaton *baton; ali@17: parser.start_element=warnings_parser_start_element; ali@17: parser.end_element=warnings_parser_end_element; ali@17: parser.text=warnings_parser_text; ali@17: baton=g_new0(WarningsBaton,1); ali@17: baton->testcase=testcase; ali@17: baton->state=WARNINGS_INIT; ali@17: return g_markup_parse_context_new(&parser, ali@17: G_MARKUP_TREAT_CDATA_AS_TEXT|G_MARKUP_PREFIX_ERROR_POSITION, ali@17: baton,g_free); ali@17: }