test/harness/warningsparser.c
author ali <ali@juiblex.co.uk>
Sat Oct 05 21:37:31 2013 +0100 (2013-10-05)
changeset 99 783eff3047bc
child 101 f44c530f80da
permissions -rw-r--r--
Fix bug #21: False positive: Opening slanted double-quote, followed by single slanted quote, should be accepted by BL
     1 #include <stdlib.h>
     2 #include <string.h>
     3 #include <glib.h>
     4 #include "testcase.h"
     5 #include "warningsparser.h"
     6 
     7 /*
     8  * A GMarkupParser for the contents of a WARNINGS tag.
     9  */
    10 
    11 typedef struct {
    12     Testcase *testcase;
    13     TestcaseWarning *warning;
    14     TestcaseLocation *location;
    15     enum {
    16 	WARNINGS_INIT,
    17 	WARNINGS_IN_EXPECTED,
    18 	WARNINGS_IN_WARNING,
    19 	WARNINGS_IN_AT,
    20 	WARNINGS_IN_TEXT,
    21 	WARNINGS_DONE,
    22     } state;
    23 } WarningsBaton;
    24 
    25 static void warnings_parser_start_element(GMarkupParseContext *context,
    26   const char *element_name,const char **attribute_names,
    27   const char **attribute_values,void *user_data,GError **error)
    28 {
    29     int i;
    30     guint64 tmp;
    31     char *endp;
    32     WarningsBaton *baton=user_data;
    33     switch(baton->state)
    34     {
    35 	case WARNINGS_INIT:
    36 	    if (strcmp(element_name,"expected"))
    37 		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
    38 		  "Unknown root element: '%s'",element_name);
    39 	    else if (attribute_names[0])
    40 		g_set_error(error,G_MARKUP_ERROR,
    41 		  G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
    42 		  "Unknown attribute on element 'expected': '%s'",
    43 		  attribute_names[0]);
    44 	    else
    45 		baton->state=WARNINGS_IN_EXPECTED;
    46 	    break;
    47 	case WARNINGS_IN_EXPECTED:
    48 	    baton->warning=g_new0(TestcaseWarning,1);
    49 	    if (!strcmp(element_name,"error"))
    50 		baton->warning->is_real=TRUE;
    51 	    else if (!strcmp(element_name,"false-positive"))
    52 		baton->warning->xfail=TRUE;
    53 	    else if (!strcmp(element_name,"false-negative"))
    54 		baton->warning->is_real=baton->warning->xfail=TRUE;
    55 	    else
    56 	    {
    57 		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
    58 		  "Unknown element in 'expected': '%s'",element_name);
    59 		g_free(baton->warning);
    60 		baton->warning=NULL;
    61 		return;
    62 	    }
    63 	    if (attribute_names[0])
    64 	    {
    65 		g_set_error(error,G_MARKUP_ERROR,
    66 		  G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
    67 		  "Unknown attribute on element '%s': '%s'",element_name,
    68 		  attribute_names[0]);
    69 		g_free(baton->warning);
    70 		baton->warning=NULL;
    71 		return;
    72 	    }
    73 	    else
    74 		baton->state=WARNINGS_IN_WARNING;
    75 	    break;
    76 	case WARNINGS_IN_WARNING:
    77 	    if (!strcmp(element_name,"at"))
    78 	    {
    79 		baton->location=g_new0(TestcaseLocation,1);
    80 		for(i=0;attribute_names[i];i++)
    81 		{
    82 		    if (!strcmp(attribute_names[i],"line"))
    83 		    {
    84 			tmp=g_ascii_strtoull(attribute_values[i],&endp,0);
    85 			if (tmp<1 || tmp>G_MAXUINT || tmp==G_MAXUINT64)
    86 			{
    87 			    g_set_error(error,G_MARKUP_ERROR,
    88 			      G_MARKUP_ERROR_INVALID_CONTENT,"Invalid value "
    89 			      "for attribute 'line' on element '%s': '%s'",
    90 			      element_name,attribute_values[i]);
    91 			    return;
    92 			}
    93 			baton->location->line=(guint)tmp;
    94 		    }
    95 		    else if (!strcmp(attribute_names[i],"column"))
    96 		    {
    97 			tmp=g_ascii_strtoull(attribute_values[i],&endp,0);
    98 			if (tmp<1 || tmp>G_MAXUINT || tmp==G_MAXUINT64)
    99 			{
   100 			    g_set_error(error,G_MARKUP_ERROR,
   101 			      G_MARKUP_ERROR_INVALID_CONTENT,"Invalid value "
   102 			      "for attribute 'column' on element '%s': '%s'",
   103 			      element_name,attribute_values[i]);
   104 			    return;
   105 			}
   106 			baton->location->column=(guint)tmp;
   107 		    }
   108 		    else
   109 		    {
   110 			g_set_error(error,G_MARKUP_ERROR,
   111 			  G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
   112 			  "Unknown attribute on element '%s': '%s'",
   113 			  element_name,attribute_names[i]);
   114 			return;
   115 		    }
   116 		}
   117 		if (!baton->location->line)
   118 		{
   119 		    g_set_error(error,G_MARKUP_ERROR,
   120 		      G_MARKUP_ERROR_MISSING_ATTRIBUTE,
   121 		      "Missing attribute on element '%s': 'line'",element_name);
   122 		    return;
   123 		}
   124 		baton->state=WARNINGS_IN_AT;
   125 	    }
   126 	    else if (!strcmp(element_name,"text"))
   127 	    {
   128 		if (attribute_names[0])
   129 		{
   130 		    g_set_error(error,G_MARKUP_ERROR,
   131 		      G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
   132 		      "Unknown attribute on element 'text': '%s'",
   133 		      attribute_names[0]);
   134 		    return;
   135 		}
   136 		baton->state=WARNINGS_IN_TEXT;
   137 	    }
   138 	    break;
   139 	case WARNINGS_IN_AT:
   140 	    g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
   141 	      "Unknown element in 'at': '%s'",element_name);
   142 	    return;
   143 	case WARNINGS_IN_TEXT:
   144 	    g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
   145 	      "Unknown element in 'text': '%s'",element_name);
   146 	    return;
   147 	default:
   148 	    g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
   149 	      "Unexpected element: '%s'",element_name);
   150 	    return;
   151     }
   152 }
   153 
   154 static void warnings_parser_end_element(GMarkupParseContext *context,
   155   const char *element_name,void *user_data,GError **error)
   156 {
   157     WarningsBaton *baton=user_data;
   158     switch(baton->state)
   159     {
   160 	case WARNINGS_IN_EXPECTED:
   161 	    baton->testcase->warnings=
   162 	      g_slist_reverse(baton->testcase->warnings);
   163 	    baton->state=WARNINGS_DONE;
   164 	    break;
   165 	case WARNINGS_IN_WARNING:
   166 	    baton->warning->locations=
   167 	      g_slist_reverse(baton->warning->locations);
   168 	    baton->testcase->warnings=g_slist_prepend(baton->testcase->warnings,
   169 	      baton->warning);
   170 	    baton->warning=NULL;
   171 	    baton->state=WARNINGS_IN_EXPECTED;
   172 	    break;
   173 	case WARNINGS_IN_AT:
   174 	    baton->warning->locations=g_slist_prepend(baton->warning->locations,
   175 	      baton->location);
   176 	    baton->location=NULL;
   177 	    baton->state=WARNINGS_IN_WARNING;
   178 	    break;
   179 	case WARNINGS_IN_TEXT:
   180 	    baton->state=WARNINGS_IN_WARNING;
   181 	    break;
   182 	default:
   183 	    g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_UNKNOWN_ELEMENT,
   184 	      "Unexpected element ending: '%s'",element_name);
   185 	    return;
   186     }
   187 }
   188 
   189 static void warnings_parser_text(GMarkupParseContext *context,
   190   const char *text,gsize text_len,void *user_data,GError **error)
   191 {
   192     char *s,*t;
   193     WarningsBaton *baton=user_data;
   194     switch(baton->state)
   195     {
   196 	case WARNINGS_IN_EXPECTED:
   197 	    if (strspn(text," \t\n")!=text_len)
   198 		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
   199 		  "The 'expected' tag does not take any content");
   200 	    break;
   201 	case WARNINGS_IN_WARNING:
   202 	    if (strspn(text," \t\n")!=text_len)
   203 		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
   204 		  "The warning tags do not take any content");
   205 	    break;
   206 	case WARNINGS_IN_AT:
   207 	    if (strspn(text," \t\n")!=text_len)
   208 		g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
   209 		  "The 'at' tag does not take any content");
   210 	    break;
   211 	case WARNINGS_IN_TEXT:
   212 	    s=g_strdup(text+strspn(text," \t\n"));
   213 	    g_strchomp(s);
   214 	    if (baton->warning->text)
   215 	    {
   216 		t=g_strconcat(baton->warning->text,s,NULL);
   217 		g_free(baton->warning->text);
   218 		g_free(s);
   219 		baton->warning->text=t;
   220 	    }
   221 	    else
   222 		baton->warning->text=s;
   223 	    break;
   224 	default:
   225 	    g_set_error(error,G_MARKUP_ERROR,G_MARKUP_ERROR_INVALID_CONTENT,
   226 	      "Unexpected content: '%s'",text);
   227 	    return;
   228     }
   229 }
   230 
   231 GMarkupParseContext *warnings_parse_context_new(Testcase *testcase)
   232 {
   233     static GMarkupParser parser={0};
   234     WarningsBaton *baton;
   235     parser.start_element=warnings_parser_start_element;
   236     parser.end_element=warnings_parser_end_element;
   237     parser.text=warnings_parser_text;
   238     baton=g_new0(WarningsBaton,1);
   239     baton->testcase=testcase;
   240     baton->state=WARNINGS_INIT;
   241     return g_markup_parse_context_new(&parser,
   242       G_MARKUP_TREAT_CDATA_AS_TEXT|G_MARKUP_PREFIX_ERROR_POSITION,
   243       baton,g_free);
   244 }