| 8390 | */ |
| 8391 | |
| 8392 | const xmlChar * |
| 8393 | xmlParseStartTag(xmlParserCtxtPtr ctxt) { |
| 8394 | const xmlChar *name; |
| 8395 | const xmlChar *attname; |
| 8396 | xmlChar *attvalue; |
| 8397 | const xmlChar **atts = ctxt->atts; |
| 8398 | int nbatts = 0; |
| 8399 | int maxatts = ctxt->maxatts; |
| 8400 | int i; |
| 8401 | |
| 8402 | if (RAW != '<') return(NULL); |
| 8403 | NEXT1; |
| 8404 | |
| 8405 | name = xmlParseName(ctxt); |
| 8406 | if (name == NULL) { |
| 8407 | xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED, |
| 8408 | "xmlParseStartTag: invalid element name\n"); |
| 8409 | return(NULL); |
| 8410 | } |
| 8411 | |
| 8412 | /* |
| 8413 | * Now parse the attributes, it ends up with the ending |
| 8414 | * |
| 8415 | * (S Attribute)* S? |
| 8416 | */ |
| 8417 | SKIP_BLANKS; |
| 8418 | GROW; |
| 8419 | |
| 8420 | while (((RAW != '>') && |
| 8421 | ((RAW != '/') || (NXT(1) != '>')) && |
| 8422 | (IS_BYTE_CHAR(RAW))) && (PARSER_STOPPED(ctxt) == 0)) { |
| 8423 | attname = xmlParseAttribute(ctxt, &attvalue); |
| 8424 | if (attname == NULL) |
| 8425 | break; |
| 8426 | if (attvalue != NULL) { |
| 8427 | /* |
| 8428 | * [ WFC: Unique Att Spec ] |
| 8429 | * No attribute name may appear more than once in the same |
| 8430 | * start-tag or empty-element tag. |
| 8431 | */ |
| 8432 | for (i = 0; i < nbatts;i += 2) { |
| 8433 | if (xmlStrEqual(atts[i], attname)) { |
| 8434 | xmlErrAttributeDup(ctxt, NULL, attname); |
| 8435 | xmlFree(attvalue); |
| 8436 | goto failed; |
| 8437 | } |
| 8438 | } |
| 8439 | /* |
| 8440 | * Add the pair to atts |
| 8441 | */ |
| 8442 | if (atts == NULL) { |
| 8443 | maxatts = 22; /* allow for 10 attrs by default */ |
| 8444 | atts = (const xmlChar **) |
| 8445 | xmlMalloc(maxatts * sizeof(xmlChar *)); |
| 8446 | if (atts == NULL) { |
| 8447 | xmlErrMemory(ctxt); |
| 8448 | if (attvalue != NULL) |
| 8449 | xmlFree(attvalue); |
no test coverage detected