Annotation of XML/parser.c, revision 1.133

1.1       veillard    1: /*
1.3       veillard    2:  * parser.c : an XML 1.0 non-verifying parser
1.15      veillard    3:  *
                      4:  * See Copyright for the status of this software.
                      5:  *
1.60      daniel      6:  * Daniel.Veillard@w3.org
1.1       veillard    7:  */
                      8: 
1.26      daniel      9: #ifdef WIN32
                     10: #define HAVE_FCNTL_H
                     11: #include <io.h>
                     12: #else
1.121     daniel     13: #include "config.h"
1.26      daniel     14: #endif
1.121     daniel     15: 
1.1       veillard   16: #include <stdio.h>
1.121     daniel     17: #include <string.h> /* for memset() only */
                     18: #ifdef HAVE_CTYPE_H
1.1       veillard   19: #include <ctype.h>
1.121     daniel     20: #endif
                     21: #ifdef HAVE_STDLIB_H
1.50      daniel     22: #include <stdlib.h>
1.121     daniel     23: #endif
                     24: #ifdef HAVE_SYS_STAT_H
1.9       httpng     25: #include <sys/stat.h>
1.121     daniel     26: #endif
1.9       httpng     27: #ifdef HAVE_FCNTL_H
                     28: #include <fcntl.h>
                     29: #endif
1.10      httpng     30: #ifdef HAVE_UNISTD_H
                     31: #include <unistd.h>
                     32: #endif
1.20      daniel     33: #ifdef HAVE_ZLIB_H
                     34: #include <zlib.h>
                     35: #endif
1.1       veillard   36: 
1.119     daniel     37: #include "xmlmemory.h"
1.14      veillard   38: #include "tree.h"
1.1       veillard   39: #include "parser.h"
1.14      veillard   40: #include "entities.h"
1.75      daniel     41: #include "encoding.h"
1.61      daniel     42: #include "valid.h"
1.69      daniel     43: #include "parserInternals.h"
1.91      daniel     44: #include "xmlIO.h"
1.122     daniel     45: #include "xml-error.h"
1.1       veillard   46: 
1.86      daniel     47: const char *xmlParserVersion = LIBXML_VERSION;
                     48: 
1.91      daniel     49: 
                     50: /************************************************************************
                     51:  *                                                                     *
                     52:  *             Input handling functions for progressive parsing        *
                     53:  *                                                                     *
                     54:  ************************************************************************/
                     55: 
                     56: /* #define DEBUG_INPUT */
                     57: 
1.110     daniel     58: #define INPUT_CHUNK    250
                     59: /* we need to keep enough input to show errors in context */
                     60: #define LINE_LEN        80
1.91      daniel     61: 
                     62: #ifdef DEBUG_INPUT
                     63: #define CHECK_BUFFER(in) check_buffer(in)
                     64: 
                     65: void check_buffer(xmlParserInputPtr in) {
                     66:     if (in->base != in->buf->buffer->content) {
                     67:         fprintf(stderr, "xmlParserInput: base mismatch problem\n");
                     68:     }
                     69:     if (in->cur < in->base) {
                     70:         fprintf(stderr, "xmlParserInput: cur < base problem\n");
                     71:     }
                     72:     if (in->cur > in->base + in->buf->buffer->use) {
                     73:         fprintf(stderr, "xmlParserInput: cur > base + use problem\n");
                     74:     }
                     75:     fprintf(stderr,"buffer %x : content %x, cur %d, use %d, size %d\n",
                     76:             (int) in, (int) in->buf->buffer->content, in->cur - in->base,
                     77:            in->buf->buffer->use, in->buf->buffer->size);
                     78: }
                     79: 
1.110     daniel     80: #else
                     81: #define CHECK_BUFFER(in) 
                     82: #endif
                     83: 
1.91      daniel     84: 
                     85: /**
                     86:  * xmlParserInputRead:
                     87:  * @in:  an XML parser input
                     88:  * @len:  an indicative size for the lookahead
                     89:  *
                     90:  * This function refresh the input for the parser. It doesn't try to
                     91:  * preserve pointers to the input buffer, and discard already read data
                     92:  *
1.123     daniel     93:  * Returns the number of xmlChars read, or -1 in case of error, 0 indicate the
1.91      daniel     94:  * end of this entity
                     95:  */
                     96: int
                     97: xmlParserInputRead(xmlParserInputPtr in, int len) {
                     98:     int ret;
                     99:     int used;
                    100:     int index;
                    101: 
                    102: #ifdef DEBUG_INPUT
                    103:     fprintf(stderr, "Read\n");
                    104: #endif
                    105:     if (in->buf == NULL) return(-1);
                    106:     if (in->base == NULL) return(-1);
                    107:     if (in->cur == NULL) return(-1);
                    108:     if (in->buf->buffer == NULL) return(-1);
                    109: 
                    110:     CHECK_BUFFER(in);
                    111: 
                    112:     used = in->cur - in->buf->buffer->content;
                    113:     ret = xmlBufferShrink(in->buf->buffer, used);
                    114:     if (ret > 0) {
                    115:        in->cur -= ret;
                    116:        in->consumed += ret;
                    117:     }
                    118:     ret = xmlParserInputBufferRead(in->buf, len);
                    119:     if (in->base != in->buf->buffer->content) {
                    120:         /*
                    121:         * the buffer has been realloced
                    122:         */
                    123:        index = in->cur - in->base;
                    124:        in->base = in->buf->buffer->content;
                    125:        in->cur = &in->buf->buffer->content[index];
                    126:     }
                    127: 
                    128:     CHECK_BUFFER(in);
                    129: 
                    130:     return(ret);
                    131: }
                    132: 
                    133: /**
                    134:  * xmlParserInputGrow:
                    135:  * @in:  an XML parser input
                    136:  * @len:  an indicative size for the lookahead
                    137:  *
                    138:  * This function increase the input for the parser. It tries to
                    139:  * preserve pointers to the input buffer, and keep already read data
                    140:  *
1.123     daniel    141:  * Returns the number of xmlChars read, or -1 in case of error, 0 indicate the
1.91      daniel    142:  * end of this entity
                    143:  */
                    144: int
                    145: xmlParserInputGrow(xmlParserInputPtr in, int len) {
                    146:     int ret;
                    147:     int index;
                    148: 
                    149: #ifdef DEBUG_INPUT
                    150:     fprintf(stderr, "Grow\n");
                    151: #endif
                    152:     if (in->buf == NULL) return(-1);
                    153:     if (in->base == NULL) return(-1);
                    154:     if (in->cur == NULL) return(-1);
                    155:     if (in->buf->buffer == NULL) return(-1);
                    156: 
                    157:     CHECK_BUFFER(in);
                    158: 
                    159:     index = in->cur - in->base;
                    160:     if (in->buf->buffer->use > index + INPUT_CHUNK) {
                    161: 
                    162:        CHECK_BUFFER(in);
                    163: 
                    164:         return(0);
                    165:     }
                    166:     ret = xmlParserInputBufferGrow(in->buf, len);
                    167:     if (in->base != in->buf->buffer->content) {
                    168:         /*
                    169:         * the buffer has been realloced
                    170:         */
                    171:        index = in->cur - in->base;
                    172:        in->base = in->buf->buffer->content;
                    173:        in->cur = &in->buf->buffer->content[index];
                    174:     }
                    175: 
                    176:     CHECK_BUFFER(in);
                    177: 
                    178:     return(ret);
                    179: }
                    180: 
                    181: /**
                    182:  * xmlParserInputShrink:
                    183:  * @in:  an XML parser input
                    184:  *
                    185:  * This function removes used input for the parser.
                    186:  */
                    187: void
                    188: xmlParserInputShrink(xmlParserInputPtr in) {
                    189:     int used;
                    190:     int ret;
                    191:     int index;
                    192: 
                    193: #ifdef DEBUG_INPUT
                    194:     fprintf(stderr, "Shrink\n");
                    195: #endif
                    196:     if (in->buf == NULL) return;
                    197:     if (in->base == NULL) return;
                    198:     if (in->cur == NULL) return;
                    199:     if (in->buf->buffer == NULL) return;
                    200: 
                    201:     CHECK_BUFFER(in);
                    202: 
                    203:     used = in->cur - in->buf->buffer->content;
                    204:     if (used > INPUT_CHUNK) {
1.110     daniel    205:        ret = xmlBufferShrink(in->buf->buffer, used - LINE_LEN);
1.91      daniel    206:        if (ret > 0) {
                    207:            in->cur -= ret;
                    208:            in->consumed += ret;
                    209:        }
                    210:     }
                    211: 
                    212:     CHECK_BUFFER(in);
                    213: 
                    214:     if (in->buf->buffer->use > INPUT_CHUNK) {
                    215:         return;
                    216:     }
                    217:     xmlParserInputBufferRead(in->buf, 2 * INPUT_CHUNK);
                    218:     if (in->base != in->buf->buffer->content) {
                    219:         /*
                    220:         * the buffer has been realloced
                    221:         */
                    222:        index = in->cur - in->base;
                    223:        in->base = in->buf->buffer->content;
                    224:        in->cur = &in->buf->buffer->content[index];
                    225:     }
                    226: 
                    227:     CHECK_BUFFER(in);
                    228: }
                    229: 
1.45      daniel    230: /************************************************************************
                    231:  *                                                                     *
                    232:  *             Parser stacks related functions and macros              *
                    233:  *                                                                     *
                    234:  ************************************************************************/
1.79      daniel    235: 
                    236: int xmlSubstituteEntitiesDefaultValue = 0;
1.100     daniel    237: int xmlDoValidityCheckingDefaultValue = 0;
1.79      daniel    238: 
1.1       veillard  239: /*
1.40      daniel    240:  * Generic function for accessing stacks in the Parser Context
1.1       veillard  241:  */
                    242: 
1.31      daniel    243: #define PUSH_AND_POP(type, name)                                       \
1.72      daniel    244: extern int name##Push(xmlParserCtxtPtr ctxt, type value) {             \
1.31      daniel    245:     if (ctxt->name##Nr >= ctxt->name##Max) {                           \
                    246:        ctxt->name##Max *= 2;                                           \
1.119     daniel    247:         ctxt->name##Tab = (void *) xmlRealloc(ctxt->name##Tab,         \
1.40      daniel    248:                     ctxt->name##Max * sizeof(ctxt->name##Tab[0]));     \
                    249:         if (ctxt->name##Tab == NULL) {                                 \
1.31      daniel    250:            fprintf(stderr, "realloc failed !\n");                      \
                    251:            exit(1);                                                    \
                    252:        }                                                               \
                    253:     }                                                                  \
1.40      daniel    254:     ctxt->name##Tab[ctxt->name##Nr] = value;                           \
                    255:     ctxt->name = value;                                                        \
                    256:     return(ctxt->name##Nr++);                                          \
1.31      daniel    257: }                                                                      \
1.72      daniel    258: extern type name##Pop(xmlParserCtxtPtr ctxt) {                         \
1.69      daniel    259:     type ret;                                                          \
1.40      daniel    260:     if (ctxt->name##Nr <= 0) return(0);                                        \
                    261:     ctxt->name##Nr--;                                                  \
1.50      daniel    262:     if (ctxt->name##Nr > 0)                                            \
                    263:        ctxt->name = ctxt->name##Tab[ctxt->name##Nr - 1];               \
                    264:     else                                                               \
                    265:         ctxt->name = NULL;                                             \
1.69      daniel    266:     ret = ctxt->name##Tab[ctxt->name##Nr];                             \
                    267:     ctxt->name##Tab[ctxt->name##Nr] = 0;                               \
                    268:     return(ret);                                                       \
1.31      daniel    269: }                                                                      \
                    270: 
1.40      daniel    271: PUSH_AND_POP(xmlParserInputPtr, input)
1.41      daniel    272: PUSH_AND_POP(xmlNodePtr, node)
1.40      daniel    273: 
1.55      daniel    274: /*
                    275:  * Macros for accessing the content. Those should be used only by the parser,
                    276:  * and not exported.
                    277:  *
                    278:  * Dirty macros, i.e. one need to make assumption on the context to use them
                    279:  *
1.123     daniel    280:  *   CUR_PTR return the current pointer to the xmlChar to be parsed.
                    281:  *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
1.55      daniel    282:  *           in ISO-Latin or UTF-8, and the current 16 bit value if compiled
                    283:  *           in UNICODE mode. This should be used internally by the parser
                    284:  *           only to compare to ASCII values otherwise it would break when
                    285:  *           running with UTF-8 encoding.
1.123     daniel    286:  *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
1.55      daniel    287:  *           to compare on ASCII based substring.
1.123     daniel    288:  *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
1.55      daniel    289:  *           strings within the parser.
                    290:  *
1.77      daniel    291:  * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
1.55      daniel    292:  *
                    293:  *   CURRENT Returns the current char value, with the full decoding of
                    294:  *           UTF-8 if we are using this mode. It returns an int.
                    295:  *   NEXT    Skip to the next character, this does the proper decoding
                    296:  *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
1.77      daniel    297:  *   COPY(to) copy one char to *to, increment CUR_PTR and to accordingly
1.55      daniel    298:  */
1.45      daniel    299: 
1.97      daniel    300: #define CUR (ctxt->token ? ctxt->token : (*ctxt->input->cur))
1.55      daniel    301: #define SKIP(val) ctxt->input->cur += (val)
                    302: #define NXT(val) ctxt->input->cur[(val)]
                    303: #define CUR_PTR ctxt->input->cur
1.97      daniel    304: #define SHRINK  xmlParserInputShrink(ctxt->input);                     \
                    305:     if ((*ctxt->input->cur == 0) &&                                    \
                    306:         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))           \
                    307:            xmlPopInput(ctxt)
                    308: 
                    309: #define GROW  xmlParserInputGrow(ctxt->input, INPUT_CHUNK);            \
                    310:     if ((*ctxt->input->cur == 0) &&                                    \
                    311:         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))           \
                    312:            xmlPopInput(ctxt)
1.55      daniel    313: 
                    314: #define SKIP_BLANKS                                                    \
1.101     daniel    315:     do {                                                               \
                    316:        while (IS_BLANK(CUR)) NEXT;                                     \
                    317:        if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
                    318:        if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt);   \
                    319:     } while (IS_BLANK(CUR));
1.55      daniel    320: 
                    321: #define CURRENT (*ctxt->input->cur)
1.91      daniel    322: #define NEXT {                                                         \
1.97      daniel    323:     if (ctxt->token != 0) ctxt->token = 0;                             \
                    324:     else {                                                             \
1.91      daniel    325:     if ((*ctxt->input->cur == 0) &&                                    \
                    326:         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) {         \
                    327:            xmlPopInput(ctxt);                                          \
                    328:     } else {                                                           \
                    329:         if (*(ctxt->input->cur) == '\n') {                             \
                    330:            ctxt->input->line++; ctxt->input->col = 1;                  \
                    331:        } else ctxt->input->col++;                                      \
                    332:        ctxt->input->cur++;                                             \
                    333:         if (*ctxt->input->cur == 0)                                    \
                    334:            xmlParserInputGrow(ctxt->input, INPUT_CHUNK);               \
1.96      daniel    335:     }                                                                  \
                    336:     if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);    \
                    337:     if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt);      \
1.97      daniel    338: }}
1.91      daniel    339: 
1.42      daniel    340: 
1.97      daniel    341: /************************************************************************
                    342:  *                                                                     *
                    343:  *     Commodity functions to handle entities processing               *
                    344:  *                                                                     *
                    345:  ************************************************************************/
1.40      daniel    346: 
1.50      daniel    347: /**
                    348:  * xmlPopInput:
                    349:  * @ctxt:  an XML parser context
                    350:  *
1.40      daniel    351:  * xmlPopInput: the current input pointed by ctxt->input came to an end
                    352:  *          pop it and return the next char.
1.45      daniel    353:  *
1.123     daniel    354:  * Returns the current xmlChar in the parser context
1.40      daniel    355:  */
1.123     daniel    356: xmlChar
1.55      daniel    357: xmlPopInput(xmlParserCtxtPtr ctxt) {
1.40      daniel    358:     if (ctxt->inputNr == 1) return(0); /* End of main Input */
1.69      daniel    359:     xmlFreeInputStream(inputPop(ctxt));
1.97      daniel    360:     if ((*ctxt->input->cur == 0) &&
                    361:         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
                    362:            return(xmlPopInput(ctxt));
1.40      daniel    363:     return(CUR);
                    364: }
                    365: 
1.50      daniel    366: /**
                    367:  * xmlPushInput:
                    368:  * @ctxt:  an XML parser context
                    369:  * @input:  an XML parser input fragment (entity, XML fragment ...).
                    370:  *
1.40      daniel    371:  * xmlPushInput: switch to a new input stream which is stacked on top
                    372:  *               of the previous one(s).
                    373:  */
1.55      daniel    374: void
                    375: xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
1.40      daniel    376:     if (input == NULL) return;
                    377:     inputPush(ctxt, input);
                    378: }
                    379: 
1.50      daniel    380: /**
1.69      daniel    381:  * xmlFreeInputStream:
1.127     daniel    382:  * @input:  an xmlParserInputPtr
1.69      daniel    383:  *
                    384:  * Free up an input stream.
                    385:  */
                    386: void
                    387: xmlFreeInputStream(xmlParserInputPtr input) {
                    388:     if (input == NULL) return;
                    389: 
1.119     daniel    390:     if (input->filename != NULL) xmlFree((char *) input->filename);
                    391:     if (input->directory != NULL) xmlFree((char *) input->directory);
1.69      daniel    392:     if ((input->free != NULL) && (input->base != NULL))
1.123     daniel    393:         input->free((xmlChar *) input->base);
1.93      veillard  394:     if (input->buf != NULL) 
                    395:         xmlFreeParserInputBuffer(input->buf);
1.69      daniel    396:     memset(input, -1, sizeof(xmlParserInput));
1.119     daniel    397:     xmlFree(input);
1.69      daniel    398: }
                    399: 
                    400: /**
1.96      daniel    401:  * xmlNewInputStream:
                    402:  * @ctxt:  an XML parser context
                    403:  *
                    404:  * Create a new input stream structure
                    405:  * Returns the new input stream or NULL
                    406:  */
                    407: xmlParserInputPtr
                    408: xmlNewInputStream(xmlParserCtxtPtr ctxt) {
                    409:     xmlParserInputPtr input;
                    410: 
1.119     daniel    411:     input = (xmlParserInputPtr) xmlMalloc(sizeof(xmlParserInput));
1.96      daniel    412:     if (input == NULL) {
1.123     daniel    413:         ctxt->errNo = XML_ERR_NO_MEMORY;
1.96      daniel    414:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel    415:            ctxt->sax->error(ctxt->userData, 
                    416:                             "malloc: couldn't allocate a new input stream\n");
1.123     daniel    417:        ctxt->errNo = XML_ERR_NO_MEMORY;
1.96      daniel    418:        return(NULL);
                    419:     }
                    420:     input->filename = NULL;
                    421:     input->directory = NULL;
                    422:     input->base = NULL;
                    423:     input->cur = NULL;
                    424:     input->buf = NULL;
                    425:     input->line = 1;
                    426:     input->col = 1;
                    427:     input->buf = NULL;
                    428:     input->free = NULL;
                    429:     input->consumed = 0;
                    430:     return(input);
                    431: }
                    432: 
                    433: /**
1.50      daniel    434:  * xmlNewEntityInputStream:
                    435:  * @ctxt:  an XML parser context
                    436:  * @entity:  an Entity pointer
                    437:  *
1.82      daniel    438:  * Create a new input stream based on an xmlEntityPtr
1.113     daniel    439:  *
                    440:  * Returns the new input stream or NULL
1.45      daniel    441:  */
1.50      daniel    442: xmlParserInputPtr
                    443: xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
1.45      daniel    444:     xmlParserInputPtr input;
                    445: 
                    446:     if (entity == NULL) {
1.123     daniel    447:         ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.55      daniel    448:         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel    449:            ctxt->sax->error(ctxt->userData,
1.45      daniel    450:              "internal: xmlNewEntityInputStream entity = NULL\n");
1.123     daniel    451:        ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.50      daniel    452:        return(NULL);
1.45      daniel    453:     }
                    454:     if (entity->content == NULL) {
1.113     daniel    455:        switch (entity->type) {
                    456:             case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1.123     daniel    457:                ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
1.113     daniel    458:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    459:                    ctxt->sax->error(ctxt->userData,
                    460:                      "xmlNewEntityInputStream unparsed entity !\n");
                    461:                 break;
                    462:             case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                    463:             case XML_EXTERNAL_PARAMETER_ENTITY:
1.116     daniel    464:                return(xmlLoadExternalEntity((char *) entity->SystemID,
                    465:                       (char *) entity->ExternalID, ctxt->input));
1.113     daniel    466:             case XML_INTERNAL_GENERAL_ENTITY:
                    467:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    468:                    ctxt->sax->error(ctxt->userData,
                    469:          "Internal entity %s without content !\n", entity->name);
                    470:                 break;
                    471:             case XML_INTERNAL_PARAMETER_ENTITY:
1.123     daniel    472:                ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.113     daniel    473:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    474:                    ctxt->sax->error(ctxt->userData,
                    475:          "Internal parameter entity %s without content !\n", entity->name);
                    476:                 break;
                    477:             case XML_INTERNAL_PREDEFINED_ENTITY:
1.123     daniel    478:                ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.113     daniel    479:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    480:                    ctxt->sax->error(ctxt->userData,
                    481:              "Predefined entity %s without content !\n", entity->name);
                    482:                 break;
                    483:        }
1.50      daniel    484:        return(NULL);
1.45      daniel    485:     }
1.96      daniel    486:     input = xmlNewInputStream(ctxt);
1.45      daniel    487:     if (input == NULL) {
1.50      daniel    488:        return(NULL);
1.45      daniel    489:     }
1.123     daniel    490:     input->filename = (char *) entity->SystemID; /* TODO !!! char <- xmlChar */
1.45      daniel    491:     input->base = entity->content;
                    492:     input->cur = entity->content;
1.50      daniel    493:     return(input);
1.45      daniel    494: }
                    495: 
1.59      daniel    496: /**
                    497:  * xmlNewStringInputStream:
                    498:  * @ctxt:  an XML parser context
1.96      daniel    499:  * @buffer:  an memory buffer
1.59      daniel    500:  *
                    501:  * Create a new input stream based on a memory buffer.
1.68      daniel    502:  * Returns the new input stream
1.59      daniel    503:  */
                    504: xmlParserInputPtr
1.123     daniel    505: xmlNewStringInputStream(xmlParserCtxtPtr ctxt, const xmlChar *buffer) {
1.59      daniel    506:     xmlParserInputPtr input;
                    507: 
1.96      daniel    508:     if (buffer == NULL) {
1.123     daniel    509:        ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.59      daniel    510:         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel    511:            ctxt->sax->error(ctxt->userData,
1.59      daniel    512:              "internal: xmlNewStringInputStream string = NULL\n");
                    513:        return(NULL);
                    514:     }
1.96      daniel    515:     input = xmlNewInputStream(ctxt);
1.59      daniel    516:     if (input == NULL) {
                    517:        return(NULL);
                    518:     }
1.96      daniel    519:     input->base = buffer;
                    520:     input->cur = buffer;
1.59      daniel    521:     return(input);
                    522: }
                    523: 
1.76      daniel    524: /**
                    525:  * xmlNewInputFromFile:
                    526:  * @ctxt:  an XML parser context
                    527:  * @filename:  the filename to use as entity
                    528:  *
                    529:  * Create a new input stream based on a file.
                    530:  *
                    531:  * Returns the new input stream or NULL in case of error
                    532:  */
                    533: xmlParserInputPtr
1.79      daniel    534: xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) {
1.91      daniel    535:     xmlParserInputBufferPtr buf;
1.76      daniel    536:     xmlParserInputPtr inputStream;
1.111     daniel    537:     char *directory = NULL;
1.76      daniel    538: 
1.96      daniel    539:     if (ctxt == NULL) return(NULL);
1.91      daniel    540:     buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
1.94      daniel    541:     if (buf == NULL) {
1.106     daniel    542:        char name[1024];
                    543: 
1.94      daniel    544:         if ((ctxt->input != NULL) && (ctxt->input->directory != NULL)) {
                    545: #ifdef WIN32
                    546:             sprintf(name, "%s\\%s", ctxt->input->directory, filename);
                    547: #else
                    548:             sprintf(name, "%s/%s", ctxt->input->directory, filename);
                    549: #endif
                    550:             buf = xmlParserInputBufferCreateFilename(name,
                    551:                                                     XML_CHAR_ENCODING_NONE);
1.106     daniel    552:            if (buf != NULL)
1.119     daniel    553:                directory = xmlMemStrdup(ctxt->input->directory);
1.106     daniel    554:        }
                    555:        if ((buf == NULL) && (ctxt->directory != NULL)) {
                    556: #ifdef WIN32
                    557:             sprintf(name, "%s\\%s", ctxt->directory, filename);
                    558: #else
                    559:             sprintf(name, "%s/%s", ctxt->directory, filename);
                    560: #endif
                    561:             buf = xmlParserInputBufferCreateFilename(name,
                    562:                                                     XML_CHAR_ENCODING_NONE);
                    563:            if (buf != NULL)
1.119     daniel    564:                directory = xmlMemStrdup(ctxt->directory);
1.106     daniel    565:        }
                    566:        if (buf == NULL)
1.94      daniel    567:            return(NULL);
                    568:     }
                    569:     if (directory == NULL)
                    570:         directory = xmlParserGetDirectory(filename);
1.76      daniel    571: 
1.96      daniel    572:     inputStream = xmlNewInputStream(ctxt);
1.76      daniel    573:     if (inputStream == NULL) {
1.119     daniel    574:        if (directory != NULL) xmlFree((char *) directory);
1.76      daniel    575:        return(NULL);
                    576:     }
                    577: 
1.119     daniel    578:     inputStream->filename = xmlMemStrdup(filename);
1.94      daniel    579:     inputStream->directory = directory;
1.91      daniel    580:     inputStream->buf = buf;
1.76      daniel    581: 
1.91      daniel    582:     inputStream->base = inputStream->buf->buffer->content;
                    583:     inputStream->cur = inputStream->buf->buffer->content;
1.106     daniel    584:     if ((ctxt->directory == NULL) && (directory != NULL))
1.110     daniel    585:         ctxt->directory = directory;
1.76      daniel    586:     return(inputStream);
                    587: }
                    588: 
1.77      daniel    589: /************************************************************************
                    590:  *                                                                     *
1.97      daniel    591:  *             Commodity functions to handle parser contexts           *
                    592:  *                                                                     *
                    593:  ************************************************************************/
                    594: 
                    595: /**
                    596:  * xmlInitParserCtxt:
                    597:  * @ctxt:  an XML parser context
                    598:  *
                    599:  * Initialize a parser context
                    600:  */
                    601: 
                    602: void
                    603: xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
                    604: {
                    605:     xmlSAXHandler *sax;
                    606: 
1.119     daniel    607:     sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
1.97      daniel    608:     if (sax == NULL) {
                    609:         fprintf(stderr, "xmlInitParserCtxt: out of memory\n");
                    610:     }
                    611: 
                    612:     /* Allocate the Input stack */
1.119     daniel    613:     ctxt->inputTab = (xmlParserInputPtr *) xmlMalloc(5 * sizeof(xmlParserInputPtr));
1.97      daniel    614:     ctxt->inputNr = 0;
                    615:     ctxt->inputMax = 5;
                    616:     ctxt->input = NULL;
                    617:     ctxt->version = NULL;
                    618:     ctxt->encoding = NULL;
                    619:     ctxt->standalone = -1;
1.98      daniel    620:     ctxt->hasExternalSubset = 0;
                    621:     ctxt->hasPErefs = 0;
1.97      daniel    622:     ctxt->html = 0;
1.98      daniel    623:     ctxt->external = 0;
1.97      daniel    624:     ctxt->instate = XML_PARSER_PROLOG;
                    625:     ctxt->token = 0;
1.106     daniel    626:     ctxt->directory = NULL;
1.97      daniel    627: 
                    628:     /* Allocate the Node stack */
1.119     daniel    629:     ctxt->nodeTab = (xmlNodePtr *) xmlMalloc(10 * sizeof(xmlNodePtr));
1.97      daniel    630:     ctxt->nodeNr = 0;
                    631:     ctxt->nodeMax = 10;
                    632:     ctxt->node = NULL;
                    633: 
                    634:     if (sax == NULL) ctxt->sax = &xmlDefaultSAXHandler;
                    635:     else {
                    636:         ctxt->sax = sax;
                    637:        memcpy(sax, &xmlDefaultSAXHandler, sizeof(xmlSAXHandler));
                    638:     }
                    639:     ctxt->userData = ctxt;
                    640:     ctxt->myDoc = NULL;
                    641:     ctxt->wellFormed = 1;
1.99      daniel    642:     ctxt->valid = 1;
1.100     daniel    643:     ctxt->validate = xmlDoValidityCheckingDefaultValue;
                    644:     ctxt->vctxt.userData = ctxt;
                    645:     ctxt->vctxt.error = xmlParserValidityError;
                    646:     ctxt->vctxt.warning = xmlParserValidityWarning;
1.97      daniel    647:     ctxt->replaceEntities = xmlSubstituteEntitiesDefaultValue;
                    648:     ctxt->record_info = 0;
                    649:     xmlInitNodeInfoSeq(&ctxt->node_seq);
                    650: }
                    651: 
                    652: /**
                    653:  * xmlFreeParserCtxt:
                    654:  * @ctxt:  an XML parser context
                    655:  *
                    656:  * Free all the memory used by a parser context. However the parsed
                    657:  * document in ctxt->myDoc is not freed.
                    658:  */
                    659: 
                    660: void
                    661: xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
                    662: {
                    663:     xmlParserInputPtr input;
                    664: 
                    665:     if (ctxt == NULL) return;
                    666: 
                    667:     while ((input = inputPop(ctxt)) != NULL) {
                    668:         xmlFreeInputStream(input);
                    669:     }
                    670: 
1.119     daniel    671:     if (ctxt->nodeTab != NULL) xmlFree(ctxt->nodeTab);
                    672:     if (ctxt->inputTab != NULL) xmlFree(ctxt->inputTab);
                    673:     if (ctxt->version != NULL) xmlFree((char *) ctxt->version);
                    674:     if (ctxt->encoding != NULL) xmlFree((char *) ctxt->encoding);
1.97      daniel    675:     if ((ctxt->sax != NULL) && (ctxt->sax != &xmlDefaultSAXHandler))
1.119     daniel    676:         xmlFree(ctxt->sax);
                    677:     if (ctxt->directory != NULL) xmlFree((char *) ctxt->directory);
                    678:     xmlFree(ctxt);
1.97      daniel    679: }
                    680: 
                    681: /**
                    682:  * xmlNewParserCtxt:
                    683:  *
                    684:  * Allocate and initialize a new parser context.
                    685:  *
                    686:  * Returns the xmlParserCtxtPtr or NULL
                    687:  */
                    688: 
                    689: xmlParserCtxtPtr
                    690: xmlNewParserCtxt()
                    691: {
                    692:     xmlParserCtxtPtr ctxt;
                    693: 
1.119     daniel    694:     ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt));
1.97      daniel    695:     if (ctxt == NULL) {
                    696:         fprintf(stderr, "xmlNewParserCtxt : cannot allocate context\n");
                    697:         perror("malloc");
                    698:        return(NULL);
                    699:     }
                    700:     xmlInitParserCtxt(ctxt);
                    701:     return(ctxt);
                    702: }
                    703: 
                    704: /**
                    705:  * xmlClearParserCtxt:
                    706:  * @ctxt:  an XML parser context
                    707:  *
                    708:  * Clear (release owned resources) and reinitialize a parser context
                    709:  */
                    710: 
                    711: void
                    712: xmlClearParserCtxt(xmlParserCtxtPtr ctxt)
                    713: {
                    714:   xmlClearNodeInfoSeq(&ctxt->node_seq);
                    715:   xmlInitParserCtxt(ctxt);
                    716: }
                    717: 
                    718: /************************************************************************
                    719:  *                                                                     *
1.77      daniel    720:  *             Commodity functions to handle entities                  *
                    721:  *                                                                     *
                    722:  ************************************************************************/
                    723: 
1.97      daniel    724: void xmlParserHandleReference(xmlParserCtxtPtr ctxt);
                    725: void xmlParserHandlePEReference(xmlParserCtxtPtr ctxt);
                    726: 
                    727: /**
                    728:  * xmlParseCharRef:
                    729:  * @ctxt:  an XML parser context
                    730:  *
                    731:  * parse Reference declarations
                    732:  *
                    733:  * [66] CharRef ::= '&#' [0-9]+ ';' |
                    734:  *                  '&#x' [0-9a-fA-F]+ ';'
                    735:  *
1.98      daniel    736:  * [ WFC: Legal Character ]
                    737:  * Characters referred to using character references must match the
                    738:  * production for Char. 
                    739:  *
1.97      daniel    740:  * Returns the value parsed (as an int)
1.77      daniel    741:  */
1.97      daniel    742: int
                    743: xmlParseCharRef(xmlParserCtxtPtr ctxt) {
                    744:     int val = 0;
                    745: 
1.111     daniel    746:     if (ctxt->token != 0) {
1.126     daniel    747: fprintf(stderr, "xmlParseCharRef : ctxt->token != 0\n");    
1.111     daniel    748:        val = ctxt->token;
                    749:         ctxt->token = 0;
                    750:         return(val);
                    751:     }
1.97      daniel    752:     if ((CUR == '&') && (NXT(1) == '#') &&
                    753:         (NXT(2) == 'x')) {
                    754:        SKIP(3);
                    755:        while (CUR != ';') {
                    756:            if ((CUR >= '0') && (CUR <= '9')) 
                    757:                val = val * 16 + (CUR - '0');
                    758:            else if ((CUR >= 'a') && (CUR <= 'f'))
                    759:                val = val * 16 + (CUR - 'a') + 10;
                    760:            else if ((CUR >= 'A') && (CUR <= 'F'))
                    761:                val = val * 16 + (CUR - 'A') + 10;
                    762:            else {
1.123     daniel    763:                ctxt->errNo = XML_ERR_INVALID_HEX_CHARREF;
1.97      daniel    764:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    765:                    ctxt->sax->error(ctxt->userData, 
                    766:                         "xmlParseCharRef: invalid hexadecimal value\n");
                    767:                ctxt->wellFormed = 0;
                    768:                val = 0;
                    769:                break;
                    770:            }
                    771:            NEXT;
                    772:        }
                    773:        if (CUR == ';')
1.126     daniel    774:            SKIP(1); /* on purpose to avoid reentrancy problems with NEXT */
1.97      daniel    775:     } else if  ((CUR == '&') && (NXT(1) == '#')) {
                    776:        SKIP(2);
                    777:        while (CUR != ';') {
                    778:            if ((CUR >= '0') && (CUR <= '9')) 
                    779:                val = val * 10 + (CUR - '0');
                    780:            else {
1.123     daniel    781:                ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF;
1.97      daniel    782:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    783:                    ctxt->sax->error(ctxt->userData, 
                    784:                         "xmlParseCharRef: invalid decimal value\n");
                    785:                ctxt->wellFormed = 0;
                    786:                val = 0;
                    787:                break;
                    788:            }
                    789:            NEXT;
                    790:        }
                    791:        if (CUR == ';')
1.126     daniel    792:            SKIP(1); /* on purpose to avoid reentrancy problems with NEXT */
1.97      daniel    793:     } else {
1.123     daniel    794:        ctxt->errNo = XML_ERR_INVALID_CHARREF;
1.97      daniel    795:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.98      daniel    796:            ctxt->sax->error(ctxt->userData,
                    797:               "xmlParseCharRef: invalid value\n");
1.97      daniel    798:        ctxt->wellFormed = 0;
                    799:     }
1.98      daniel    800: 
1.97      daniel    801:     /*
1.98      daniel    802:      * [ WFC: Legal Character ]
                    803:      * Characters referred to using character references must match the
                    804:      * production for Char. 
1.97      daniel    805:      */
                    806:     if (IS_CHAR(val)) {
                    807:         return(val);
                    808:     } else {
1.123     daniel    809:        ctxt->errNo = XML_ERR_INVALID_CHAR;
1.97      daniel    810:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.123     daniel    811:            ctxt->sax->error(ctxt->userData, "CharRef: invalid xmlChar value %d\n",
1.97      daniel    812:                             val);
                    813:        ctxt->wellFormed = 0;
                    814:     }
                    815:     return(0);
1.77      daniel    816: }
                    817: 
1.96      daniel    818: /**
                    819:  * xmlParserHandleReference:
                    820:  * @ctxt:  the parser context
                    821:  * 
1.97      daniel    822:  * [67] Reference ::= EntityRef | CharRef
                    823:  *
1.96      daniel    824:  * [68] EntityRef ::= '&' Name ';'
                    825:  *
1.98      daniel    826:  * [ WFC: Entity Declared ]
                    827:  * the Name given in the entity reference must match that in an entity
                    828:  * declaration, except that well-formed documents need not declare any
                    829:  * of the following entities: amp, lt, gt, apos, quot. 
                    830:  *
                    831:  * [ WFC: Parsed Entity ]
                    832:  * An entity reference must not contain the name of an unparsed entity
                    833:  *
1.97      daniel    834:  * [66] CharRef ::= '&#' [0-9]+ ';' |
                    835:  *                  '&#x' [0-9a-fA-F]+ ';'
                    836:  *
1.96      daniel    837:  * A PEReference may have been detectect in the current input stream
                    838:  * the handling is done accordingly to 
                    839:  *      http://www.w3.org/TR/REC-xml#entproc
                    840:  */
                    841: void
                    842: xmlParserHandleReference(xmlParserCtxtPtr ctxt) {
1.97      daniel    843:     xmlParserInputPtr input;
1.123     daniel    844:     xmlChar *name;
1.97      daniel    845:     xmlEntityPtr ent = NULL;
                    846: 
1.126     daniel    847:     if (ctxt->token != 0) {
                    848: fprintf(stderr, "xmlParserHandleReference : ctxt->token != 0\n");
                    849:         return;
                    850:     }  
1.97      daniel    851:     if (CUR != '&') return;
                    852:     GROW;
                    853:     if ((CUR == '&') && (NXT(1) == '#')) {
                    854:        switch(ctxt->instate) {
1.109     daniel    855:            case XML_PARSER_CDATA_SECTION:
                    856:                return;
1.97      daniel    857:            case XML_PARSER_COMMENT:
                    858:                return;
                    859:            case XML_PARSER_EOF:
1.123     daniel    860:                ctxt->errNo = XML_ERR_CHARREF_AT_EOF;
1.97      daniel    861:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    862:                    ctxt->sax->error(ctxt->userData, "CharRef at EOF\n");
                    863:                ctxt->wellFormed = 0;
                    864:                return;
                    865:            case XML_PARSER_PROLOG:
1.123     daniel    866:                ctxt->errNo = XML_ERR_CHARREF_IN_PROLOG;
1.97      daniel    867:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    868:                    ctxt->sax->error(ctxt->userData, "CharRef in prolog!\n");
                    869:                ctxt->wellFormed = 0;
                    870:                return;
                    871:            case XML_PARSER_EPILOG:
1.123     daniel    872:                ctxt->errNo = XML_ERR_CHARREF_IN_EPILOG;
1.97      daniel    873:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    874:                    ctxt->sax->error(ctxt->userData, "CharRef in epilog!\n");
                    875:                ctxt->wellFormed = 0;
                    876:                return;
                    877:            case XML_PARSER_DTD:
1.123     daniel    878:                ctxt->errNo = XML_ERR_CHARREF_IN_DTD;
1.97      daniel    879:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    880:                    ctxt->sax->error(ctxt->userData, 
                    881:                           "CharRef are forbiden in DTDs!\n");
                    882:                ctxt->wellFormed = 0;
                    883:                return;
                    884:            case XML_PARSER_ENTITY_DECL:
                    885:                /* we just ignore it there */
                    886:                return;
                    887:            case XML_PARSER_ENTITY_VALUE:
                    888:                /*
                    889:                 * NOTE: in the case of entity values, we don't do the
1.127     daniel    890:                 *       substitution here since we need the literal
1.97      daniel    891:                 *       entity value to be able to save the internal
                    892:                 *       subset of the document.
                    893:                 *       This will be handled by xmlDecodeEntities
                    894:                 */
                    895:                return;
                    896:            case XML_PARSER_CONTENT:
                    897:            case XML_PARSER_ATTRIBUTE_VALUE:
1.116     daniel    898:                /* !!! this may not be Ok for UTF-8, multibyte sequence */
1.97      daniel    899:                ctxt->token = xmlParseCharRef(ctxt);
                    900:                return;
                    901:        }
                    902:        return;
                    903:     }
                    904: 
                    905:     switch(ctxt->instate) {
1.109     daniel    906:        case XML_PARSER_CDATA_SECTION:
                    907:            return;
1.97      daniel    908:         case XML_PARSER_COMMENT:
                    909:            return;
                    910:         case XML_PARSER_EOF:
1.123     daniel    911:            ctxt->errNo = XML_ERR_ENTITYREF_AT_EOF;
1.97      daniel    912:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    913:                ctxt->sax->error(ctxt->userData, "Reference at EOF\n");
                    914:            ctxt->wellFormed = 0;
                    915:            return;
                    916:         case XML_PARSER_PROLOG:
1.123     daniel    917:            ctxt->errNo = XML_ERR_ENTITYREF_IN_PROLOG;
1.97      daniel    918:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    919:                ctxt->sax->error(ctxt->userData, "Reference in prolog!\n");
                    920:            ctxt->wellFormed = 0;
                    921:            return;
                    922:         case XML_PARSER_EPILOG:
1.123     daniel    923:            ctxt->errNo = XML_ERR_ENTITYREF_IN_EPILOG;
1.97      daniel    924:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    925:                ctxt->sax->error(ctxt->userData, "Reference in epilog!\n");
                    926:            ctxt->wellFormed = 0;
                    927:            return;
                    928:        case XML_PARSER_ENTITY_VALUE:
                    929:            /*
                    930:             * NOTE: in the case of entity values, we don't do the
1.127     daniel    931:             *       substitution here since we need the literal
1.97      daniel    932:             *       entity value to be able to save the internal
                    933:             *       subset of the document.
                    934:             *       This will be handled by xmlDecodeEntities
                    935:             */
                    936:            return;
                    937:         case XML_PARSER_ATTRIBUTE_VALUE:
                    938:            /*
                    939:             * NOTE: in the case of attributes values, we don't do the
                    940:             *       substitution here unless we are in a mode where
                    941:             *       the parser is explicitely asked to substitute
                    942:             *       entities. The SAX callback is called with values
                    943:             *       without entity substitution.
                    944:             *       This will then be handled by xmlDecodeEntities
                    945:             */
1.113     daniel    946:            return;
1.97      daniel    947:        case XML_PARSER_ENTITY_DECL:
                    948:            /*
                    949:             * we just ignore it there
                    950:             * the substitution will be done once the entity is referenced
                    951:             */
                    952:            return;
                    953:         case XML_PARSER_DTD:
1.123     daniel    954:            ctxt->errNo = XML_ERR_ENTITYREF_IN_DTD;
1.97      daniel    955:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    956:                ctxt->sax->error(ctxt->userData, 
                    957:                       "Entity references are forbiden in DTDs!\n");
                    958:            ctxt->wellFormed = 0;
                    959:            return;
                    960:         case XML_PARSER_CONTENT:
1.113     daniel    961:            return;
1.97      daniel    962:     }
                    963: 
                    964:     NEXT;
                    965:     name = xmlScanName(ctxt);
                    966:     if (name == NULL) {
1.123     daniel    967:        ctxt->errNo = XML_ERR_ENTITYREF_NO_NAME;
1.97      daniel    968:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    969:            ctxt->sax->error(ctxt->userData, "Entity reference: no name\n");
                    970:        ctxt->wellFormed = 0;
                    971:        ctxt->token = '&';
                    972:        return;
                    973:     }
                    974:     if (NXT(xmlStrlen(name)) != ';') {
1.123     daniel    975:        ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
1.97      daniel    976:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    977:            ctxt->sax->error(ctxt->userData, 
                    978:                             "Entity reference: ';' expected\n");
                    979:        ctxt->wellFormed = 0;
                    980:        ctxt->token = '&';
1.119     daniel    981:        xmlFree(name);
1.97      daniel    982:        return;
                    983:     }
                    984:     SKIP(xmlStrlen(name) + 1);
                    985:     if (ctxt->sax != NULL) {
                    986:        if (ctxt->sax->getEntity != NULL)
                    987:            ent = ctxt->sax->getEntity(ctxt->userData, name);
                    988:     }
1.98      daniel    989: 
                    990:     /*
                    991:      * [ WFC: Entity Declared ]
                    992:      * the Name given in the entity reference must match that in an entity
                    993:      * declaration, except that well-formed documents need not declare any
                    994:      * of the following entities: amp, lt, gt, apos, quot. 
                    995:      */
1.97      daniel    996:     if (ent == NULL)
                    997:        ent = xmlGetPredefinedEntity(name);
                    998:     if (ent == NULL) {
1.123     daniel    999:         ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
1.97      daniel   1000:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1001:            ctxt->sax->error(ctxt->userData, 
1.98      daniel   1002:                             "Entity reference: entity %s not declared\n",
                   1003:                             name);
1.97      daniel   1004:        ctxt->wellFormed = 0;
1.119     daniel   1005:        xmlFree(name);
1.97      daniel   1006:        return;
                   1007:     }
1.98      daniel   1008: 
                   1009:     /*
                   1010:      * [ WFC: Parsed Entity ]
                   1011:      * An entity reference must not contain the name of an unparsed entity
                   1012:      */
                   1013:     if (ent->type == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
1.123     daniel   1014:         ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
1.98      daniel   1015:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1016:            ctxt->sax->error(ctxt->userData, 
                   1017:                         "Entity reference to unparsed entity %s\n", name);
                   1018:        ctxt->wellFormed = 0;
                   1019:     }
                   1020: 
1.97      daniel   1021:     if (ent->type == XML_INTERNAL_PREDEFINED_ENTITY) {
                   1022:         ctxt->token = ent->content[0];
1.119     daniel   1023:        xmlFree(name);
1.97      daniel   1024:        return;
                   1025:     }
                   1026:     input = xmlNewEntityInputStream(ctxt, ent);
                   1027:     xmlPushInput(ctxt, input);
1.119     daniel   1028:     xmlFree(name);
1.96      daniel   1029:     return;
                   1030: }
                   1031: 
                   1032: /**
                   1033:  * xmlParserHandlePEReference:
                   1034:  * @ctxt:  the parser context
                   1035:  * 
                   1036:  * [69] PEReference ::= '%' Name ';'
                   1037:  *
1.98      daniel   1038:  * [ WFC: No Recursion ]
                   1039:  * TODO A parsed entity must not contain a recursive
                   1040:  * reference to itself, either directly or indirectly. 
                   1041:  *
                   1042:  * [ WFC: Entity Declared ]
                   1043:  * In a document without any DTD, a document with only an internal DTD
                   1044:  * subset which contains no parameter entity references, or a document
                   1045:  * with "standalone='yes'", ...  ... The declaration of a parameter
                   1046:  * entity must precede any reference to it...
                   1047:  *
                   1048:  * [ VC: Entity Declared ]
                   1049:  * In a document with an external subset or external parameter entities
                   1050:  * with "standalone='no'", ...  ... The declaration of a parameter entity
                   1051:  * must precede any reference to it...
                   1052:  *
                   1053:  * [ WFC: In DTD ]
                   1054:  * Parameter-entity references may only appear in the DTD.
                   1055:  * NOTE: misleading but this is handled.
                   1056:  *
                   1057:  * A PEReference may have been detected in the current input stream
1.96      daniel   1058:  * the handling is done accordingly to 
                   1059:  *      http://www.w3.org/TR/REC-xml#entproc
                   1060:  * i.e. 
                   1061:  *   - Included in literal in entity values
                   1062:  *   - Included as Paraemeter Entity reference within DTDs
                   1063:  */
                   1064: void
                   1065: xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
1.123     daniel   1066:     xmlChar *name;
1.96      daniel   1067:     xmlEntityPtr entity = NULL;
                   1068:     xmlParserInputPtr input;
                   1069: 
1.126     daniel   1070:     if (ctxt->token != 0) {
                   1071: fprintf(stderr, "xmlParserHandlePEReference : ctxt->token != 0\n");
                   1072:         return;
                   1073:     }  
1.111     daniel   1074:     if (CUR != '%') return;
1.96      daniel   1075:     switch(ctxt->instate) {
1.109     daniel   1076:        case XML_PARSER_CDATA_SECTION:
                   1077:            return;
1.97      daniel   1078:         case XML_PARSER_COMMENT:
                   1079:            return;
1.96      daniel   1080:         case XML_PARSER_EOF:
1.123     daniel   1081:            ctxt->errNo = XML_ERR_PEREF_AT_EOF;
1.96      daniel   1082:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1083:                ctxt->sax->error(ctxt->userData, "PEReference at EOF\n");
                   1084:            ctxt->wellFormed = 0;
                   1085:            return;
                   1086:         case XML_PARSER_PROLOG:
1.123     daniel   1087:            ctxt->errNo = XML_ERR_PEREF_IN_PROLOG;
1.96      daniel   1088:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1089:                ctxt->sax->error(ctxt->userData, "PEReference in prolog!\n");
                   1090:            ctxt->wellFormed = 0;
                   1091:            return;
1.97      daniel   1092:        case XML_PARSER_ENTITY_DECL:
1.96      daniel   1093:         case XML_PARSER_CONTENT:
                   1094:         case XML_PARSER_ATTRIBUTE_VALUE:
                   1095:            /* we just ignore it there */
                   1096:            return;
                   1097:         case XML_PARSER_EPILOG:
1.123     daniel   1098:            ctxt->errNo = XML_ERR_PEREF_IN_EPILOG;
1.96      daniel   1099:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.97      daniel   1100:                ctxt->sax->error(ctxt->userData, "PEReference in epilog!\n");
1.96      daniel   1101:            ctxt->wellFormed = 0;
                   1102:            return;
1.97      daniel   1103:        case XML_PARSER_ENTITY_VALUE:
                   1104:            /*
                   1105:             * NOTE: in the case of entity values, we don't do the
1.127     daniel   1106:             *       substitution here since we need the literal
1.97      daniel   1107:             *       entity value to be able to save the internal
                   1108:             *       subset of the document.
                   1109:             *       This will be handled by xmlDecodeEntities
                   1110:             */
                   1111:            return;
1.96      daniel   1112:         case XML_PARSER_DTD:
1.98      daniel   1113:            /*
                   1114:             * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
                   1115:             * In the internal DTD subset, parameter-entity references
                   1116:             * can occur only where markup declarations can occur, not
                   1117:             * within markup declarations.
                   1118:             * In that case this is handled in xmlParseMarkupDecl
                   1119:             */
                   1120:            if ((ctxt->external == 0) && (ctxt->inputNr == 1))
                   1121:                return;
1.96      daniel   1122:     }
                   1123: 
                   1124:     NEXT;
                   1125:     name = xmlParseName(ctxt);
                   1126:     if (name == NULL) {
1.123     daniel   1127:         ctxt->errNo = XML_ERR_PEREF_NO_NAME;
1.96      daniel   1128:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1129:            ctxt->sax->error(ctxt->userData, "xmlHandlePEReference: no name\n");
                   1130:        ctxt->wellFormed = 0;
                   1131:     } else {
                   1132:        if (CUR == ';') {
                   1133:            NEXT;
1.98      daniel   1134:            if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
                   1135:                entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
1.96      daniel   1136:            if (entity == NULL) {
1.98      daniel   1137:                
                   1138:                /*
                   1139:                 * [ WFC: Entity Declared ]
                   1140:                 * In a document without any DTD, a document with only an
                   1141:                 * internal DTD subset which contains no parameter entity
                   1142:                 * references, or a document with "standalone='yes'", ...
                   1143:                 * ... The declaration of a parameter entity must precede
                   1144:                 * any reference to it...
                   1145:                 */
                   1146:                if ((ctxt->standalone == 1) ||
                   1147:                    ((ctxt->hasExternalSubset == 0) &&
                   1148:                     (ctxt->hasPErefs == 0))) {
                   1149:                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1150:                        ctxt->sax->error(ctxt->userData,
                   1151:                         "PEReference: %%%s; not found\n", name);
                   1152:                    ctxt->wellFormed = 0;
                   1153:                } else {
                   1154:                    /*
                   1155:                     * [ VC: Entity Declared ]
                   1156:                     * In a document with an external subset or external
                   1157:                     * parameter entities with "standalone='no'", ...
                   1158:                     * ... The declaration of a parameter entity must precede
                   1159:                     * any reference to it...
                   1160:                     */
                   1161:                    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
                   1162:                        ctxt->sax->warning(ctxt->userData,
                   1163:                         "PEReference: %%%s; not found\n", name);
                   1164:                    ctxt->valid = 0;
                   1165:                }
1.96      daniel   1166:            } else {
                   1167:                if ((entity->type == XML_INTERNAL_PARAMETER_ENTITY) ||
                   1168:                    (entity->type == XML_EXTERNAL_PARAMETER_ENTITY)) {
                   1169:                    /*
                   1170:                     * TODO !!!! handle the extra spaces added before and after
                   1171:                     * c.f. http://www.w3.org/TR/REC-xml#as-PE
                   1172:                     * TODO !!!! Avoid quote processing in parameters value
                   1173:                     * c.f. http://www.w3.org/TR/REC-xml#inliteral
                   1174:                     */
                   1175:                    input = xmlNewEntityInputStream(ctxt, entity);
                   1176:                    xmlPushInput(ctxt, input);
                   1177:                } else {
                   1178:                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1179:                        ctxt->sax->error(ctxt->userData,
                   1180:                         "xmlHandlePEReference: %s is not a parameter entity\n",
                   1181:                                         name);
                   1182:                    ctxt->wellFormed = 0;
                   1183:                }
                   1184:            }
                   1185:        } else {
1.123     daniel   1186:            ctxt->errNo = XML_ERR_PEREF_SEMICOL_MISSING;
1.96      daniel   1187:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1188:                ctxt->sax->error(ctxt->userData,
                   1189:                                 "xmlHandlePEReference: expecting ';'\n");
                   1190:            ctxt->wellFormed = 0;
                   1191:        }
1.119     daniel   1192:        xmlFree(name);
1.97      daniel   1193:     }
                   1194: }
                   1195: 
                   1196: /*
                   1197:  * Macro used to grow the current buffer.
                   1198:  */
                   1199: #define growBuffer(buffer) {                                           \
                   1200:     buffer##_size *= 2;                                                        \
1.123     daniel   1201:     buffer = (xmlChar *) xmlRealloc(buffer, buffer##_size * sizeof(xmlChar));  \
1.97      daniel   1202:     if (buffer == NULL) {                                              \
                   1203:        perror("realloc failed");                                       \
                   1204:        exit(1);                                                        \
                   1205:     }                                                                  \
1.96      daniel   1206: }
1.77      daniel   1207: 
                   1208: /**
                   1209:  * xmlDecodeEntities:
                   1210:  * @ctxt:  the parser context
                   1211:  * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
                   1212:  * @len:  the len to decode (in bytes !), -1 for no size limit
1.123     daniel   1213:  * @end:  an end marker xmlChar, 0 if none
                   1214:  * @end2:  an end marker xmlChar, 0 if none
                   1215:  * @end3:  an end marker xmlChar, 0 if none
1.77      daniel   1216:  * 
                   1217:  * [67] Reference ::= EntityRef | CharRef
                   1218:  *
                   1219:  * [69] PEReference ::= '%' Name ';'
                   1220:  *
                   1221:  * Returns A newly allocated string with the substitution done. The caller
                   1222:  *      must deallocate it !
                   1223:  */
1.123     daniel   1224: xmlChar *
1.77      daniel   1225: xmlDecodeEntities(xmlParserCtxtPtr ctxt, int len, int what,
1.123     daniel   1226:                   xmlChar end, xmlChar  end2, xmlChar end3) {
                   1227:     xmlChar *buffer = NULL;
1.78      daniel   1228:     int buffer_size = 0;
1.123     daniel   1229:     xmlChar *out = NULL;
1.78      daniel   1230: 
1.123     daniel   1231:     xmlChar *current = NULL;
1.77      daniel   1232:     xmlEntityPtr ent;
1.91      daniel   1233:     int nbchars = 0;
1.77      daniel   1234:     unsigned int max = (unsigned int) len;
1.123     daniel   1235:     xmlChar cur;
1.77      daniel   1236: 
                   1237:     /*
                   1238:      * allocate a translation buffer.
                   1239:      */
                   1240:     buffer_size = 1000;
1.123     daniel   1241:     buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
1.77      daniel   1242:     if (buffer == NULL) {
                   1243:        perror("xmlDecodeEntities: malloc failed");
                   1244:        return(NULL);
                   1245:     }
                   1246:     out = buffer;
                   1247: 
1.78      daniel   1248:     /*
                   1249:      * Ok loop until we reach one of the ending char or a size limit.
                   1250:      */
1.97      daniel   1251:     cur = CUR;
                   1252:     while ((nbchars < max) && (cur != end) &&
                   1253:            (cur != end2) && (cur != end3)) {
1.77      daniel   1254: 
1.98      daniel   1255:        if (cur == 0) break;
                   1256:         if ((cur == '&') && (NXT(1) == '#')) {
                   1257:            int val = xmlParseCharRef(ctxt);
                   1258:            *out++ = val;
                   1259:            nbchars += 3; 
                   1260:        } else if ((cur == '&') && (what & XML_SUBSTITUTE_REF)) {
                   1261:            ent = xmlParseEntityRef(ctxt);
                   1262:            if ((ent != NULL) && 
                   1263:                (ctxt->replaceEntities != 0)) {
                   1264:                current = ent->content;
                   1265:                while (*current != 0) {
                   1266:                    *out++ = *current++;
                   1267:                    if (out - buffer > buffer_size - 100) {
                   1268:                        int index = out - buffer;
                   1269: 
                   1270:                        growBuffer(buffer);
                   1271:                        out = &buffer[index];
1.77      daniel   1272:                    }
                   1273:                }
1.98      daniel   1274:                nbchars += 3 + xmlStrlen(ent->name);
                   1275:            } else if (ent != NULL) {
                   1276:                int i = xmlStrlen(ent->name);
1.123     daniel   1277:                const xmlChar *cur = ent->name;
1.98      daniel   1278: 
                   1279:                nbchars += i + 2;
                   1280:                *out++ = '&';
                   1281:                if (out - buffer > buffer_size - i - 100) {
                   1282:                    int index = out - buffer;
                   1283: 
                   1284:                    growBuffer(buffer);
                   1285:                    out = &buffer[index];
                   1286:                }
                   1287:                for (;i > 0;i--)
                   1288:                    *out++ = *cur++;
                   1289:                *out++ = ';';
1.77      daniel   1290:            }
1.97      daniel   1291:        } else if (cur == '%' && (what & XML_SUBSTITUTE_PEREF)) {
                   1292:            /*
1.77      daniel   1293:             * a PEReference induce to switch the entity flow,
                   1294:             * we break here to flush the current set of chars
                   1295:             * parsed if any. We will be called back later.
1.97      daniel   1296:             */
1.91      daniel   1297:            if (nbchars != 0) break;
1.77      daniel   1298: 
                   1299:            xmlParsePEReference(ctxt);
1.79      daniel   1300: 
1.97      daniel   1301:            /*
1.79      daniel   1302:             * Pop-up of finished entities.
1.97      daniel   1303:             */
1.79      daniel   1304:            while ((CUR == 0) && (ctxt->inputNr > 1))
                   1305:                xmlPopInput(ctxt);
                   1306: 
1.98      daniel   1307:            break;
1.77      daniel   1308:        } else {
1.116     daniel   1309:            /*  invalid for UTF-8 , use COPY(out); !!!!!! */
1.97      daniel   1310:            *out++ = cur;
1.91      daniel   1311:            nbchars++;
1.86      daniel   1312:            if (out - buffer > buffer_size - 100) {
                   1313:              int index = out - buffer;
                   1314:              
                   1315:              growBuffer(buffer);
                   1316:              out = &buffer[index];
                   1317:            }
1.77      daniel   1318:            NEXT;
                   1319:        }
1.97      daniel   1320:        cur = CUR;
1.77      daniel   1321:     }
                   1322:     *out++ = 0;
                   1323:     return(buffer);
                   1324: }
                   1325: 
1.1       veillard 1326: 
1.28      daniel   1327: /************************************************************************
                   1328:  *                                                                     *
1.75      daniel   1329:  *             Commodity functions to handle encodings                 *
                   1330:  *                                                                     *
                   1331:  ************************************************************************/
                   1332: 
                   1333: /**
                   1334:  * xmlSwitchEncoding:
                   1335:  * @ctxt:  the parser context
1.124     daniel   1336:  * @enc:  the encoding value (number)
1.75      daniel   1337:  *
                   1338:  * change the input functions when discovering the character encoding
                   1339:  * of a given entity.
                   1340:  */
                   1341: void
                   1342: xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
                   1343: {
                   1344:     switch (enc) {
                   1345:         case XML_CHAR_ENCODING_ERROR:
1.123     daniel   1346:            ctxt->errNo = XML_ERR_UNKNOWN_ENCODING;
1.75      daniel   1347:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1348:                ctxt->sax->error(ctxt->userData, "encoding unknown\n");
                   1349:            ctxt->wellFormed = 0;
                   1350:             break;
                   1351:         case XML_CHAR_ENCODING_NONE:
                   1352:            /* let's assume it's UTF-8 without the XML decl */
                   1353:             return;
                   1354:         case XML_CHAR_ENCODING_UTF8:
                   1355:            /* default encoding, no conversion should be needed */
                   1356:             return;
                   1357:         case XML_CHAR_ENCODING_UTF16LE:
1.123     daniel   1358:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1359:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1360:                 ctxt->sax->error(ctxt->userData,
                   1361:                  "char encoding UTF16 little endian not supported\n");
                   1362:             break;
                   1363:         case XML_CHAR_ENCODING_UTF16BE:
1.123     daniel   1364:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1365:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1366:                 ctxt->sax->error(ctxt->userData,
                   1367:                  "char encoding UTF16 big endian not supported\n");
                   1368:             break;
                   1369:         case XML_CHAR_ENCODING_UCS4LE:
1.123     daniel   1370:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1371:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1372:                 ctxt->sax->error(ctxt->userData,
                   1373:                  "char encoding USC4 little endian not supported\n");
                   1374:             break;
                   1375:         case XML_CHAR_ENCODING_UCS4BE:
1.123     daniel   1376:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1377:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1378:                 ctxt->sax->error(ctxt->userData,
                   1379:                  "char encoding USC4 big endian not supported\n");
                   1380:             break;
                   1381:         case XML_CHAR_ENCODING_EBCDIC:
1.123     daniel   1382:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1383:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1384:                 ctxt->sax->error(ctxt->userData,
                   1385:                  "char encoding EBCDIC not supported\n");
                   1386:             break;
                   1387:         case XML_CHAR_ENCODING_UCS4_2143:
1.123     daniel   1388:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1389:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1390:                 ctxt->sax->error(ctxt->userData,
                   1391:                  "char encoding UCS4 2143 not supported\n");
                   1392:             break;
                   1393:         case XML_CHAR_ENCODING_UCS4_3412:
1.123     daniel   1394:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1395:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1396:                 ctxt->sax->error(ctxt->userData,
                   1397:                  "char encoding UCS4 3412 not supported\n");
                   1398:             break;
                   1399:         case XML_CHAR_ENCODING_UCS2:
1.123     daniel   1400:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1401:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1402:                 ctxt->sax->error(ctxt->userData,
                   1403:                  "char encoding UCS2 not supported\n");
                   1404:             break;
                   1405:         case XML_CHAR_ENCODING_8859_1:
1.123     daniel   1406:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1407:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1408:                 ctxt->sax->error(ctxt->userData,
                   1409:                  "char encoding ISO_8859_1 ISO Latin 1 not supported\n");
                   1410:             break;
                   1411:         case XML_CHAR_ENCODING_8859_2:
1.123     daniel   1412:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1413:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1414:                 ctxt->sax->error(ctxt->userData,
                   1415:                  "char encoding ISO_8859_2 ISO Latin 2 not supported\n");
                   1416:             break;
                   1417:         case XML_CHAR_ENCODING_8859_3:
1.123     daniel   1418:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1419:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1420:                 ctxt->sax->error(ctxt->userData,
                   1421:                  "char encoding ISO_8859_3 not supported\n");
                   1422:             break;
                   1423:         case XML_CHAR_ENCODING_8859_4:
1.123     daniel   1424:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1425:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1426:                 ctxt->sax->error(ctxt->userData,
                   1427:                  "char encoding ISO_8859_4 not supported\n");
                   1428:             break;
                   1429:         case XML_CHAR_ENCODING_8859_5:
1.123     daniel   1430:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1431:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1432:                 ctxt->sax->error(ctxt->userData,
                   1433:                  "char encoding ISO_8859_5 not supported\n");
                   1434:             break;
                   1435:         case XML_CHAR_ENCODING_8859_6:
1.123     daniel   1436:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1437:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1438:                 ctxt->sax->error(ctxt->userData,
                   1439:                  "char encoding ISO_8859_6 not supported\n");
                   1440:             break;
                   1441:         case XML_CHAR_ENCODING_8859_7:
1.123     daniel   1442:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1443:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1444:                 ctxt->sax->error(ctxt->userData,
                   1445:                  "char encoding ISO_8859_7 not supported\n");
                   1446:             break;
                   1447:         case XML_CHAR_ENCODING_8859_8:
1.123     daniel   1448:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1449:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1450:                 ctxt->sax->error(ctxt->userData,
                   1451:                  "char encoding ISO_8859_8 not supported\n");
                   1452:             break;
                   1453:         case XML_CHAR_ENCODING_8859_9:
1.123     daniel   1454:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1455:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1456:                 ctxt->sax->error(ctxt->userData,
                   1457:                  "char encoding ISO_8859_9 not supported\n");
                   1458:             break;
                   1459:         case XML_CHAR_ENCODING_2022_JP:
1.123     daniel   1460:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1461:             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1462:                 ctxt->sax->error(ctxt->userData,
                   1463:                   "char encoding ISO-2022-JPnot supported\n");
                   1464:             break;
                   1465:         case XML_CHAR_ENCODING_SHIFT_JIS:
1.123     daniel   1466:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1467:             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1468:                 ctxt->sax->error(ctxt->userData,
                   1469:                   "char encoding Shift_JISnot supported\n");
                   1470:             break;
                   1471:         case XML_CHAR_ENCODING_EUC_JP:
1.123     daniel   1472:            ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
1.75      daniel   1473:             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1474:                 ctxt->sax->error(ctxt->userData,
                   1475:                   "char encoding EUC-JPnot supported\n");
                   1476:             break;
                   1477:     }
                   1478: }
                   1479: 
                   1480: /************************************************************************
                   1481:  *                                                                     *
1.123     daniel   1482:  *             Commodity functions to handle xmlChars                  *
1.28      daniel   1483:  *                                                                     *
                   1484:  ************************************************************************/
                   1485: 
1.50      daniel   1486: /**
                   1487:  * xmlStrndup:
1.123     daniel   1488:  * @cur:  the input xmlChar *
1.50      daniel   1489:  * @len:  the len of @cur
                   1490:  *
1.123     daniel   1491:  * a strndup for array of xmlChar's
1.68      daniel   1492:  *
1.123     daniel   1493:  * Returns a new xmlChar * or NULL
1.1       veillard 1494:  */
1.123     daniel   1495: xmlChar *
                   1496: xmlStrndup(const xmlChar *cur, int len) {
                   1497:     xmlChar *ret = xmlMalloc((len + 1) * sizeof(xmlChar));
1.1       veillard 1498: 
                   1499:     if (ret == NULL) {
1.86      daniel   1500:         fprintf(stderr, "malloc of %ld byte failed\n",
1.123     daniel   1501:                (len + 1) * (long)sizeof(xmlChar));
1.1       veillard 1502:         return(NULL);
                   1503:     }
1.123     daniel   1504:     memcpy(ret, cur, len * sizeof(xmlChar));
1.1       veillard 1505:     ret[len] = 0;
                   1506:     return(ret);
                   1507: }
                   1508: 
1.50      daniel   1509: /**
                   1510:  * xmlStrdup:
1.123     daniel   1511:  * @cur:  the input xmlChar *
1.50      daniel   1512:  *
1.123     daniel   1513:  * a strdup for array of xmlChar's
1.68      daniel   1514:  *
1.123     daniel   1515:  * Returns a new xmlChar * or NULL
1.1       veillard 1516:  */
1.123     daniel   1517: xmlChar *
                   1518: xmlStrdup(const xmlChar *cur) {
                   1519:     const xmlChar *p = cur;
1.1       veillard 1520: 
                   1521:     while (IS_CHAR(*p)) p++;
                   1522:     return(xmlStrndup(cur, p - cur));
                   1523: }
                   1524: 
1.50      daniel   1525: /**
                   1526:  * xmlCharStrndup:
                   1527:  * @cur:  the input char *
                   1528:  * @len:  the len of @cur
                   1529:  *
1.123     daniel   1530:  * a strndup for char's to xmlChar's
1.68      daniel   1531:  *
1.123     daniel   1532:  * Returns a new xmlChar * or NULL
1.45      daniel   1533:  */
                   1534: 
1.123     daniel   1535: xmlChar *
1.55      daniel   1536: xmlCharStrndup(const char *cur, int len) {
1.45      daniel   1537:     int i;
1.123     daniel   1538:     xmlChar *ret = xmlMalloc((len + 1) * sizeof(xmlChar));
1.45      daniel   1539: 
                   1540:     if (ret == NULL) {
1.86      daniel   1541:         fprintf(stderr, "malloc of %ld byte failed\n",
1.123     daniel   1542:                (len + 1) * (long)sizeof(xmlChar));
1.45      daniel   1543:         return(NULL);
                   1544:     }
                   1545:     for (i = 0;i < len;i++)
1.123     daniel   1546:         ret[i] = (xmlChar) cur[i];
1.45      daniel   1547:     ret[len] = 0;
                   1548:     return(ret);
                   1549: }
                   1550: 
1.50      daniel   1551: /**
                   1552:  * xmlCharStrdup:
                   1553:  * @cur:  the input char *
                   1554:  * @len:  the len of @cur
                   1555:  *
1.123     daniel   1556:  * a strdup for char's to xmlChar's
1.68      daniel   1557:  *
1.123     daniel   1558:  * Returns a new xmlChar * or NULL
1.45      daniel   1559:  */
                   1560: 
1.123     daniel   1561: xmlChar *
1.55      daniel   1562: xmlCharStrdup(const char *cur) {
1.45      daniel   1563:     const char *p = cur;
                   1564: 
                   1565:     while (*p != '\0') p++;
                   1566:     return(xmlCharStrndup(cur, p - cur));
                   1567: }
                   1568: 
1.50      daniel   1569: /**
                   1570:  * xmlStrcmp:
1.123     daniel   1571:  * @str1:  the first xmlChar *
                   1572:  * @str2:  the second xmlChar *
1.50      daniel   1573:  *
1.123     daniel   1574:  * a strcmp for xmlChar's
1.68      daniel   1575:  *
                   1576:  * Returns the integer result of the comparison
1.14      veillard 1577:  */
                   1578: 
1.55      daniel   1579: int
1.123     daniel   1580: xmlStrcmp(const xmlChar *str1, const xmlChar *str2) {
1.14      veillard 1581:     register int tmp;
                   1582: 
                   1583:     do {
                   1584:         tmp = *str1++ - *str2++;
                   1585:        if (tmp != 0) return(tmp);
                   1586:     } while ((*str1 != 0) && (*str2 != 0));
                   1587:     return (*str1 - *str2);
                   1588: }
                   1589: 
1.50      daniel   1590: /**
                   1591:  * xmlStrncmp:
1.123     daniel   1592:  * @str1:  the first xmlChar *
                   1593:  * @str2:  the second xmlChar *
1.50      daniel   1594:  * @len:  the max comparison length
                   1595:  *
1.123     daniel   1596:  * a strncmp for xmlChar's
1.68      daniel   1597:  *
                   1598:  * Returns the integer result of the comparison
1.14      veillard 1599:  */
                   1600: 
1.55      daniel   1601: int
1.123     daniel   1602: xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len) {
1.14      veillard 1603:     register int tmp;
                   1604: 
                   1605:     if (len <= 0) return(0);
                   1606:     do {
                   1607:         tmp = *str1++ - *str2++;
                   1608:        if (tmp != 0) return(tmp);
                   1609:        len--;
                   1610:         if (len <= 0) return(0);
                   1611:     } while ((*str1 != 0) && (*str2 != 0));
                   1612:     return (*str1 - *str2);
                   1613: }
                   1614: 
1.50      daniel   1615: /**
                   1616:  * xmlStrchr:
1.123     daniel   1617:  * @str:  the xmlChar * array
                   1618:  * @val:  the xmlChar to search
1.50      daniel   1619:  *
1.123     daniel   1620:  * a strchr for xmlChar's
1.68      daniel   1621:  *
1.123     daniel   1622:  * Returns the xmlChar * for the first occurence or NULL.
1.14      veillard 1623:  */
                   1624: 
1.123     daniel   1625: const xmlChar *
                   1626: xmlStrchr(const xmlChar *str, xmlChar val) {
1.14      veillard 1627:     while (*str != 0) {
1.123     daniel   1628:         if (*str == val) return((xmlChar *) str);
1.14      veillard 1629:        str++;
                   1630:     }
                   1631:     return(NULL);
1.89      daniel   1632: }
                   1633: 
                   1634: /**
                   1635:  * xmlStrstr:
1.123     daniel   1636:  * @str:  the xmlChar * array (haystack)
                   1637:  * @val:  the xmlChar to search (needle)
1.89      daniel   1638:  *
1.123     daniel   1639:  * a strstr for xmlChar's
1.89      daniel   1640:  *
1.123     daniel   1641:  * Returns the xmlChar * for the first occurence or NULL.
1.89      daniel   1642:  */
                   1643: 
1.123     daniel   1644: const xmlChar *
                   1645: xmlStrstr(const xmlChar *str, xmlChar *val) {
1.89      daniel   1646:     int n;
                   1647:     
                   1648:     if (str == NULL) return(NULL);
                   1649:     if (val == NULL) return(NULL);
                   1650:     n = xmlStrlen(val);
                   1651: 
                   1652:     if (n == 0) return(str);
                   1653:     while (*str != 0) {
                   1654:         if (*str == *val) {
1.123     daniel   1655:            if (!xmlStrncmp(str, val, n)) return((const xmlChar *) str);
1.89      daniel   1656:        }
                   1657:        str++;
                   1658:     }
                   1659:     return(NULL);
                   1660: }
                   1661: 
                   1662: /**
                   1663:  * xmlStrsub:
1.123     daniel   1664:  * @str:  the xmlChar * array (haystack)
1.89      daniel   1665:  * @start:  the index of the first char (zero based)
                   1666:  * @len:  the length of the substring
                   1667:  *
                   1668:  * Extract a substring of a given string
                   1669:  *
1.123     daniel   1670:  * Returns the xmlChar * for the first occurence or NULL.
1.89      daniel   1671:  */
                   1672: 
1.123     daniel   1673: xmlChar *
                   1674: xmlStrsub(const xmlChar *str, int start, int len) {
1.89      daniel   1675:     int i;
                   1676:     
                   1677:     if (str == NULL) return(NULL);
                   1678:     if (start < 0) return(NULL);
1.90      daniel   1679:     if (len < 0) return(NULL);
1.89      daniel   1680: 
                   1681:     for (i = 0;i < start;i++) {
                   1682:         if (*str == 0) return(NULL);
                   1683:        str++;
                   1684:     }
                   1685:     if (*str == 0) return(NULL);
                   1686:     return(xmlStrndup(str, len));
1.14      veillard 1687: }
1.28      daniel   1688: 
1.50      daniel   1689: /**
                   1690:  * xmlStrlen:
1.123     daniel   1691:  * @str:  the xmlChar * array
1.50      daniel   1692:  *
1.127     daniel   1693:  * length of a xmlChar's string
1.68      daniel   1694:  *
1.123     daniel   1695:  * Returns the number of xmlChar contained in the ARRAY.
1.45      daniel   1696:  */
                   1697: 
1.55      daniel   1698: int
1.123     daniel   1699: xmlStrlen(const xmlChar *str) {
1.45      daniel   1700:     int len = 0;
                   1701: 
                   1702:     if (str == NULL) return(0);
                   1703:     while (*str != 0) {
                   1704:        str++;
                   1705:        len++;
                   1706:     }
                   1707:     return(len);
                   1708: }
                   1709: 
1.50      daniel   1710: /**
                   1711:  * xmlStrncat:
1.123     daniel   1712:  * @cur:  the original xmlChar * array
                   1713:  * @add:  the xmlChar * array added
1.50      daniel   1714:  * @len:  the length of @add
                   1715:  *
1.123     daniel   1716:  * a strncat for array of xmlChar's
1.68      daniel   1717:  *
1.123     daniel   1718:  * Returns a new xmlChar * containing the concatenated string.
1.45      daniel   1719:  */
                   1720: 
1.123     daniel   1721: xmlChar *
                   1722: xmlStrncat(xmlChar *cur, const xmlChar *add, int len) {
1.45      daniel   1723:     int size;
1.123     daniel   1724:     xmlChar *ret;
1.45      daniel   1725: 
                   1726:     if ((add == NULL) || (len == 0))
                   1727:         return(cur);
                   1728:     if (cur == NULL)
                   1729:         return(xmlStrndup(add, len));
                   1730: 
                   1731:     size = xmlStrlen(cur);
1.123     daniel   1732:     ret = xmlRealloc(cur, (size + len + 1) * sizeof(xmlChar));
1.45      daniel   1733:     if (ret == NULL) {
1.86      daniel   1734:         fprintf(stderr, "xmlStrncat: realloc of %ld byte failed\n",
1.123     daniel   1735:                (size + len + 1) * (long)sizeof(xmlChar));
1.45      daniel   1736:         return(cur);
                   1737:     }
1.123     daniel   1738:     memcpy(&ret[size], add, len * sizeof(xmlChar));
1.45      daniel   1739:     ret[size + len] = 0;
                   1740:     return(ret);
                   1741: }
                   1742: 
1.50      daniel   1743: /**
                   1744:  * xmlStrcat:
1.123     daniel   1745:  * @cur:  the original xmlChar * array
                   1746:  * @add:  the xmlChar * array added
1.50      daniel   1747:  *
1.123     daniel   1748:  * a strcat for array of xmlChar's
1.68      daniel   1749:  *
1.123     daniel   1750:  * Returns a new xmlChar * containing the concatenated string.
1.45      daniel   1751:  */
1.123     daniel   1752: xmlChar *
                   1753: xmlStrcat(xmlChar *cur, const xmlChar *add) {
                   1754:     const xmlChar *p = add;
1.45      daniel   1755: 
                   1756:     if (add == NULL) return(cur);
                   1757:     if (cur == NULL) 
                   1758:         return(xmlStrdup(add));
                   1759: 
                   1760:     while (IS_CHAR(*p)) p++;
                   1761:     return(xmlStrncat(cur, add, p - add));
                   1762: }
                   1763: 
                   1764: /************************************************************************
                   1765:  *                                                                     *
                   1766:  *             Commodity functions, cleanup needed ?                   *
                   1767:  *                                                                     *
                   1768:  ************************************************************************/
                   1769: 
1.50      daniel   1770: /**
                   1771:  * areBlanks:
                   1772:  * @ctxt:  an XML parser context
1.123     daniel   1773:  * @str:  a xmlChar *
1.50      daniel   1774:  * @len:  the size of @str
                   1775:  *
1.45      daniel   1776:  * Is this a sequence of blank chars that one can ignore ?
1.50      daniel   1777:  *
1.99      daniel   1778:  * TODO: Whether white space are significant has to be checked accordingly
                   1779:  *       to DTD informations if available
1.68      daniel   1780:  *
                   1781:  * Returns 1 if ignorable 0 otherwise.
1.45      daniel   1782:  */
                   1783: 
1.123     daniel   1784: static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1.104     daniel   1785:     int i, ret;
1.45      daniel   1786:     xmlNodePtr lastChild;
                   1787: 
                   1788:     for (i = 0;i < len;i++)
                   1789:         if (!(IS_BLANK(str[i]))) return(0);
                   1790: 
                   1791:     if (CUR != '<') return(0);
1.72      daniel   1792:     if (ctxt->node == NULL) return(0);
1.104     daniel   1793:     if (ctxt->myDoc != NULL) {
                   1794:        ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
                   1795:         if (ret == 0) return(1);
                   1796:         if (ret == 1) return(0);
                   1797:     }
                   1798:     /*
                   1799:      * heuristic
                   1800:      */
1.45      daniel   1801:     lastChild = xmlGetLastChild(ctxt->node);
                   1802:     if (lastChild == NULL) {
                   1803:         if (ctxt->node->content != NULL) return(0);
                   1804:     } else if (xmlNodeIsText(lastChild))
                   1805:         return(0);
1.104     daniel   1806:     else if ((ctxt->node->childs != NULL) &&
                   1807:              (xmlNodeIsText(ctxt->node->childs)))
                   1808:         return(0);
1.45      daniel   1809:     return(1);
                   1810: }
                   1811: 
1.50      daniel   1812: /**
                   1813:  * xmlHandleEntity:
                   1814:  * @ctxt:  an XML parser context
                   1815:  * @entity:  an XML entity pointer.
                   1816:  *
                   1817:  * Default handling of defined entities, when should we define a new input
1.45      daniel   1818:  * stream ? When do we just handle that as a set of chars ?
1.99      daniel   1819:  *
                   1820:  * OBSOLETE: to be removed at some point.
1.45      daniel   1821:  */
                   1822: 
1.55      daniel   1823: void
                   1824: xmlHandleEntity(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
1.45      daniel   1825:     int len;
1.50      daniel   1826:     xmlParserInputPtr input;
1.45      daniel   1827: 
                   1828:     if (entity->content == NULL) {
1.123     daniel   1829:        ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.55      daniel   1830:         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1831:            ctxt->sax->error(ctxt->userData, "xmlHandleEntity %s: content == NULL\n",
1.45      daniel   1832:                       entity->name);
1.59      daniel   1833:        ctxt->wellFormed = 0;
1.45      daniel   1834:         return;
                   1835:     }
                   1836:     len = xmlStrlen(entity->content);
                   1837:     if (len <= 2) goto handle_as_char;
                   1838: 
                   1839:     /*
                   1840:      * Redefine its content as an input stream.
                   1841:      */
1.50      daniel   1842:     input = xmlNewEntityInputStream(ctxt, entity);
                   1843:     xmlPushInput(ctxt, input);
1.45      daniel   1844:     return;
                   1845: 
                   1846: handle_as_char:
                   1847:     /*
                   1848:      * Just handle the content as a set of chars.
                   1849:      */
1.72      daniel   1850:     if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
1.74      daniel   1851:        ctxt->sax->characters(ctxt->userData, entity->content, len);
1.45      daniel   1852: 
                   1853: }
                   1854: 
                   1855: /*
                   1856:  * Forward definition for recusive behaviour.
                   1857:  */
1.77      daniel   1858: void xmlParsePEReference(xmlParserCtxtPtr ctxt);
                   1859: void xmlParseReference(xmlParserCtxtPtr ctxt);
1.45      daniel   1860: 
1.28      daniel   1861: /************************************************************************
                   1862:  *                                                                     *
                   1863:  *             Extra stuff for namespace support                       *
                   1864:  *     Relates to http://www.w3.org/TR/WD-xml-names                    *
                   1865:  *                                                                     *
                   1866:  ************************************************************************/
                   1867: 
1.50      daniel   1868: /**
                   1869:  * xmlNamespaceParseNCName:
                   1870:  * @ctxt:  an XML parser context
                   1871:  *
                   1872:  * parse an XML namespace name.
1.28      daniel   1873:  *
                   1874:  * [NS 3] NCName ::= (Letter | '_') (NCNameChar)*
                   1875:  *
                   1876:  * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
                   1877:  *                       CombiningChar | Extender
1.68      daniel   1878:  *
                   1879:  * Returns the namespace name or NULL
1.28      daniel   1880:  */
                   1881: 
1.123     daniel   1882: xmlChar *
1.55      daniel   1883: xmlNamespaceParseNCName(xmlParserCtxtPtr ctxt) {
1.123     daniel   1884:     xmlChar buf[XML_MAX_NAMELEN];
1.91      daniel   1885:     int len = 0;
1.28      daniel   1886: 
1.40      daniel   1887:     if (!IS_LETTER(CUR) && (CUR != '_')) return(NULL);
1.28      daniel   1888: 
1.40      daniel   1889:     while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
                   1890:            (CUR == '.') || (CUR == '-') ||
                   1891:           (CUR == '_') ||
                   1892:           (IS_COMBINING(CUR)) ||
1.91      daniel   1893:           (IS_EXTENDER(CUR))) {
                   1894:        buf[len++] = CUR;
1.40      daniel   1895:        NEXT;
1.91      daniel   1896:        if (len >= XML_MAX_NAMELEN) {
                   1897:            fprintf(stderr, 
                   1898:               "xmlNamespaceParseNCName: reached XML_MAX_NAMELEN limit\n");
                   1899:            while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
                   1900:                   (CUR == '.') || (CUR == '-') ||
                   1901:                   (CUR == '_') ||
                   1902:                   (IS_COMBINING(CUR)) ||
                   1903:                   (IS_EXTENDER(CUR)))
                   1904:                 NEXT;
                   1905:            break;
                   1906:        }
                   1907:     }
                   1908:     return(xmlStrndup(buf, len));
1.28      daniel   1909: }
                   1910: 
1.50      daniel   1911: /**
                   1912:  * xmlNamespaceParseQName:
                   1913:  * @ctxt:  an XML parser context
1.123     daniel   1914:  * @prefix:  a xmlChar ** 
1.50      daniel   1915:  *
                   1916:  * parse an XML qualified name
1.28      daniel   1917:  *
                   1918:  * [NS 5] QName ::= (Prefix ':')? LocalPart
                   1919:  *
                   1920:  * [NS 6] Prefix ::= NCName
                   1921:  *
                   1922:  * [NS 7] LocalPart ::= NCName
1.68      daniel   1923:  *
1.127     daniel   1924:  * Returns the local part, and prefix is updated
1.50      daniel   1925:  *   to get the Prefix if any.
1.28      daniel   1926:  */
                   1927: 
1.123     daniel   1928: xmlChar *
                   1929: xmlNamespaceParseQName(xmlParserCtxtPtr ctxt, xmlChar **prefix) {
                   1930:     xmlChar *ret = NULL;
1.28      daniel   1931: 
                   1932:     *prefix = NULL;
                   1933:     ret = xmlNamespaceParseNCName(ctxt);
1.40      daniel   1934:     if (CUR == ':') {
1.28      daniel   1935:         *prefix = ret;
1.40      daniel   1936:        NEXT;
1.28      daniel   1937:        ret = xmlNamespaceParseNCName(ctxt);
                   1938:     }
                   1939: 
                   1940:     return(ret);
                   1941: }
                   1942: 
1.50      daniel   1943: /**
1.72      daniel   1944:  * xmlSplitQName:
                   1945:  * @name:  an XML parser context
1.123     daniel   1946:  * @prefix:  a xmlChar ** 
1.72      daniel   1947:  *
                   1948:  * parse an XML qualified name string
                   1949:  *
                   1950:  * [NS 5] QName ::= (Prefix ':')? LocalPart
                   1951:  *
                   1952:  * [NS 6] Prefix ::= NCName
                   1953:  *
                   1954:  * [NS 7] LocalPart ::= NCName
                   1955:  *
1.127     daniel   1956:  * Returns the local part, and prefix is updated
1.72      daniel   1957:  *   to get the Prefix if any.
                   1958:  */
                   1959: 
1.123     daniel   1960: xmlChar *
                   1961: xmlSplitQName(const xmlChar *name, xmlChar **prefix) {
                   1962:     xmlChar *ret = NULL;
                   1963:     const xmlChar *q;
                   1964:     const xmlChar *cur = name;
1.72      daniel   1965: 
                   1966:     *prefix = NULL;
1.113     daniel   1967: 
                   1968:     /* xml: prefix is not really a namespace */
                   1969:     if ((cur[0] == 'x') && (cur[1] == 'm') &&
                   1970:         (cur[2] == 'l') && (cur[3] == ':'))
                   1971:        return(xmlStrdup(name));
                   1972: 
1.72      daniel   1973:     if (!IS_LETTER(*cur) && (*cur != '_')) return(NULL);
                   1974:     q = cur++;
                   1975: 
                   1976:     while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
                   1977:            (*cur == '.') || (*cur == '-') ||
                   1978:           (*cur == '_') ||
                   1979:           (IS_COMBINING(*cur)) ||
                   1980:           (IS_EXTENDER(*cur)))
                   1981:        cur++;
                   1982:     
                   1983:     ret = xmlStrndup(q, cur - q);
                   1984: 
                   1985:     if (*cur == ':') {
                   1986:        cur++;
                   1987:        if (!IS_LETTER(*cur) && (*cur != '_')) return(ret);
                   1988:         *prefix = ret;
                   1989: 
                   1990:        q = cur++;
                   1991: 
                   1992:        while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
                   1993:               (*cur == '.') || (*cur == '-') ||
                   1994:               (*cur == '_') ||
                   1995:               (IS_COMBINING(*cur)) ||
                   1996:               (IS_EXTENDER(*cur)))
                   1997:            cur++;
                   1998:        
                   1999:        ret = xmlStrndup(q, cur - q);
                   2000:     }
                   2001: 
                   2002:     return(ret);
                   2003: }
                   2004: /**
1.50      daniel   2005:  * xmlNamespaceParseNSDef:
                   2006:  * @ctxt:  an XML parser context
                   2007:  *
                   2008:  * parse a namespace prefix declaration
1.28      daniel   2009:  *
                   2010:  * [NS 1] NSDef ::= PrefixDef Eq SystemLiteral
                   2011:  *
                   2012:  * [NS 2] PrefixDef ::= 'xmlns' (':' NCName)?
1.68      daniel   2013:  *
                   2014:  * Returns the namespace name
1.28      daniel   2015:  */
                   2016: 
1.123     daniel   2017: xmlChar *
1.55      daniel   2018: xmlNamespaceParseNSDef(xmlParserCtxtPtr ctxt) {
1.123     daniel   2019:     xmlChar *name = NULL;
1.28      daniel   2020: 
1.40      daniel   2021:     if ((CUR == 'x') && (NXT(1) == 'm') &&
                   2022:         (NXT(2) == 'l') && (NXT(3) == 'n') &&
                   2023:        (NXT(4) == 's')) {
                   2024:        SKIP(5);
                   2025:        if (CUR == ':') {
                   2026:            NEXT;
1.28      daniel   2027:            name = xmlNamespaceParseNCName(ctxt);
                   2028:        }
                   2029:     }
1.39      daniel   2030:     return(name);
1.28      daniel   2031: }
                   2032: 
1.50      daniel   2033: /**
                   2034:  * xmlParseQuotedString:
                   2035:  * @ctxt:  an XML parser context
                   2036:  *
1.45      daniel   2037:  * [OLD] Parse and return a string between quotes or doublequotes
1.110     daniel   2038:  * To be removed at next drop of binary compatibility
1.68      daniel   2039:  *
                   2040:  * Returns the string parser or NULL.
1.45      daniel   2041:  */
1.123     daniel   2042: xmlChar *
1.55      daniel   2043: xmlParseQuotedString(xmlParserCtxtPtr ctxt) {
1.123     daniel   2044:     xmlChar *ret = NULL;
                   2045:     const xmlChar *q;
1.45      daniel   2046: 
                   2047:     if (CUR == '"') {
                   2048:         NEXT;
                   2049:        q = CUR_PTR;
                   2050:        while (IS_CHAR(CUR) && (CUR != '"')) NEXT;
1.55      daniel   2051:        if (CUR != '"') {
1.123     daniel   2052:            ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55      daniel   2053:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2054:                ctxt->sax->error(ctxt->userData, "String not closed \"%.50s\"\n", q);
1.59      daniel   2055:            ctxt->wellFormed = 0;
1.55      daniel   2056:         } else {
1.45      daniel   2057:             ret = xmlStrndup(q, CUR_PTR - q);
                   2058:            NEXT;
                   2059:        }
                   2060:     } else if (CUR == '\''){
                   2061:         NEXT;
                   2062:        q = CUR_PTR;
                   2063:        while (IS_CHAR(CUR) && (CUR != '\'')) NEXT;
1.55      daniel   2064:        if (CUR != '\'') {
1.123     daniel   2065:            ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55      daniel   2066:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2067:                ctxt->sax->error(ctxt->userData, "String not closed \"%.50s\"\n", q);
1.59      daniel   2068:            ctxt->wellFormed = 0;
1.55      daniel   2069:         } else {
1.45      daniel   2070:             ret = xmlStrndup(q, CUR_PTR - q);
                   2071:            NEXT;
                   2072:        }
                   2073:     }
                   2074:     return(ret);
                   2075: }
                   2076: 
1.50      daniel   2077: /**
                   2078:  * xmlParseNamespace:
                   2079:  * @ctxt:  an XML parser context
                   2080:  *
1.45      daniel   2081:  * [OLD] xmlParseNamespace: parse specific PI '<?namespace ...' constructs.
                   2082:  *
                   2083:  * This is what the older xml-name Working Draft specified, a bunch of
                   2084:  * other stuff may still rely on it, so support is still here as
1.127     daniel   2085:  * if it was declared on the root of the Tree:-(
1.110     daniel   2086:  *
                   2087:  * To be removed at next drop of binary compatibility
1.45      daniel   2088:  */
                   2089: 
1.55      daniel   2090: void
                   2091: xmlParseNamespace(xmlParserCtxtPtr ctxt) {
1.123     daniel   2092:     xmlChar *href = NULL;
                   2093:     xmlChar *prefix = NULL;
1.45      daniel   2094:     int garbage = 0;
                   2095: 
                   2096:     /*
                   2097:      * We just skipped "namespace" or "xml:namespace"
                   2098:      */
                   2099:     SKIP_BLANKS;
                   2100: 
                   2101:     while (IS_CHAR(CUR) && (CUR != '>')) {
                   2102:        /*
                   2103:         * We can have "ns" or "prefix" attributes
                   2104:         * Old encoding as 'href' or 'AS' attributes is still supported
                   2105:         */
                   2106:        if ((CUR == 'n') && (NXT(1) == 's')) {
                   2107:            garbage = 0;
                   2108:            SKIP(2);
                   2109:            SKIP_BLANKS;
                   2110: 
                   2111:            if (CUR != '=') continue;
                   2112:            NEXT;
                   2113:            SKIP_BLANKS;
                   2114: 
                   2115:            href = xmlParseQuotedString(ctxt);
                   2116:            SKIP_BLANKS;
                   2117:        } else if ((CUR == 'h') && (NXT(1) == 'r') &&
                   2118:            (NXT(2) == 'e') && (NXT(3) == 'f')) {
                   2119:            garbage = 0;
                   2120:            SKIP(4);
                   2121:            SKIP_BLANKS;
                   2122: 
                   2123:            if (CUR != '=') continue;
                   2124:            NEXT;
                   2125:            SKIP_BLANKS;
                   2126: 
                   2127:            href = xmlParseQuotedString(ctxt);
                   2128:            SKIP_BLANKS;
                   2129:        } else if ((CUR == 'p') && (NXT(1) == 'r') &&
                   2130:                   (NXT(2) == 'e') && (NXT(3) == 'f') &&
                   2131:                   (NXT(4) == 'i') && (NXT(5) == 'x')) {
                   2132:            garbage = 0;
                   2133:            SKIP(6);
                   2134:            SKIP_BLANKS;
                   2135: 
                   2136:            if (CUR != '=') continue;
                   2137:            NEXT;
                   2138:            SKIP_BLANKS;
                   2139: 
                   2140:            prefix = xmlParseQuotedString(ctxt);
                   2141:            SKIP_BLANKS;
                   2142:        } else if ((CUR == 'A') && (NXT(1) == 'S')) {
                   2143:            garbage = 0;
                   2144:            SKIP(2);
                   2145:            SKIP_BLANKS;
                   2146: 
                   2147:            if (CUR != '=') continue;
                   2148:            NEXT;
                   2149:            SKIP_BLANKS;
                   2150: 
                   2151:            prefix = xmlParseQuotedString(ctxt);
                   2152:            SKIP_BLANKS;
                   2153:        } else if ((CUR == '?') && (NXT(1) == '>')) {
                   2154:            garbage = 0;
1.91      daniel   2155:            NEXT;
1.45      daniel   2156:        } else {
                   2157:             /*
                   2158:             * Found garbage when parsing the namespace
                   2159:             */
1.122     daniel   2160:            if (!garbage) {
1.55      daniel   2161:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   2162:                    ctxt->sax->error(ctxt->userData,
                   2163:                                     "xmlParseNamespace found garbage\n");
                   2164:            }
1.123     daniel   2165:            ctxt->errNo = XML_ERR_NS_DECL_ERROR;
1.59      daniel   2166:            ctxt->wellFormed = 0;
1.45      daniel   2167:             NEXT;
                   2168:         }
                   2169:     }
                   2170: 
                   2171:     MOVETO_ENDTAG(CUR_PTR);
                   2172:     NEXT;
                   2173: 
                   2174:     /*
                   2175:      * Register the DTD.
1.72      daniel   2176:     if (href != NULL)
                   2177:        if ((ctxt->sax != NULL) && (ctxt->sax->globalNamespace != NULL))
1.74      daniel   2178:            ctxt->sax->globalNamespace(ctxt->userData, href, prefix);
1.45      daniel   2179:      */
                   2180: 
1.119     daniel   2181:     if (prefix != NULL) xmlFree(prefix);
                   2182:     if (href != NULL) xmlFree(href);
1.45      daniel   2183: }
                   2184: 
1.28      daniel   2185: /************************************************************************
                   2186:  *                                                                     *
                   2187:  *                     The parser itself                               *
                   2188:  *     Relates to http://www.w3.org/TR/REC-xml                         *
                   2189:  *                                                                     *
                   2190:  ************************************************************************/
1.14      veillard 2191: 
1.50      daniel   2192: /**
1.97      daniel   2193:  * xmlScanName:
                   2194:  * @ctxt:  an XML parser context
                   2195:  *
                   2196:  * Trickery: parse an XML name but without consuming the input flow
                   2197:  * Needed for rollback cases.
                   2198:  *
                   2199:  * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
                   2200:  *                  CombiningChar | Extender
                   2201:  *
                   2202:  * [5] Name ::= (Letter | '_' | ':') (NameChar)*
                   2203:  *
                   2204:  * [6] Names ::= Name (S Name)*
                   2205:  *
                   2206:  * Returns the Name parsed or NULL
                   2207:  */
                   2208: 
1.123     daniel   2209: xmlChar *
1.97      daniel   2210: xmlScanName(xmlParserCtxtPtr ctxt) {
1.123     daniel   2211:     xmlChar buf[XML_MAX_NAMELEN];
1.97      daniel   2212:     int len = 0;
                   2213: 
                   2214:     GROW;
                   2215:     if (!IS_LETTER(CUR) && (CUR != '_') &&
                   2216:         (CUR != ':')) {
                   2217:        return(NULL);
                   2218:     }
                   2219: 
                   2220:     while ((IS_LETTER(NXT(len))) || (IS_DIGIT(NXT(len))) ||
                   2221:            (NXT(len) == '.') || (NXT(len) == '-') ||
                   2222:           (NXT(len) == '_') || (NXT(len) == ':') || 
                   2223:           (IS_COMBINING(NXT(len))) ||
                   2224:           (IS_EXTENDER(NXT(len)))) {
                   2225:        buf[len] = NXT(len);
                   2226:        len++;
                   2227:        if (len >= XML_MAX_NAMELEN) {
                   2228:            fprintf(stderr, 
                   2229:               "xmlScanName: reached XML_MAX_NAMELEN limit\n");
                   2230:            while ((IS_LETTER(NXT(len))) || (IS_DIGIT(NXT(len))) ||
                   2231:                   (NXT(len) == '.') || (NXT(len) == '-') ||
                   2232:                   (NXT(len) == '_') || (NXT(len) == ':') || 
                   2233:                   (IS_COMBINING(NXT(len))) ||
                   2234:                   (IS_EXTENDER(NXT(len))))
                   2235:                 len++;
                   2236:            break;
                   2237:        }
                   2238:     }
                   2239:     return(xmlStrndup(buf, len));
                   2240: }
                   2241: 
                   2242: /**
1.50      daniel   2243:  * xmlParseName:
                   2244:  * @ctxt:  an XML parser context
                   2245:  *
                   2246:  * parse an XML name.
1.22      daniel   2247:  *
                   2248:  * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
                   2249:  *                  CombiningChar | Extender
                   2250:  *
                   2251:  * [5] Name ::= (Letter | '_' | ':') (NameChar)*
                   2252:  *
                   2253:  * [6] Names ::= Name (S Name)*
1.68      daniel   2254:  *
                   2255:  * Returns the Name parsed or NULL
1.1       veillard 2256:  */
                   2257: 
1.123     daniel   2258: xmlChar *
1.55      daniel   2259: xmlParseName(xmlParserCtxtPtr ctxt) {
1.123     daniel   2260:     xmlChar buf[XML_MAX_NAMELEN];
1.91      daniel   2261:     int len = 0;
1.123     daniel   2262:     xmlChar cur;
1.1       veillard 2263: 
1.91      daniel   2264:     GROW;
1.97      daniel   2265:     cur = CUR;
                   2266:     if (!IS_LETTER(cur) && (cur != '_') &&
                   2267:         (cur != ':')) {
1.91      daniel   2268:        return(NULL);
                   2269:     }
1.40      daniel   2270: 
1.97      daniel   2271:     while ((IS_LETTER(cur)) || (IS_DIGIT(cur)) ||
                   2272:            (cur == '.') || (cur == '-') ||
                   2273:           (cur == '_') || (cur == ':') || 
                   2274:           (IS_COMBINING(cur)) ||
                   2275:           (IS_EXTENDER(cur))) {
                   2276:        buf[len++] = cur;
1.40      daniel   2277:        NEXT;
1.97      daniel   2278:        cur = CUR;
1.91      daniel   2279:        if (len >= XML_MAX_NAMELEN) {
                   2280:            fprintf(stderr, 
                   2281:               "xmlParseName: reached XML_MAX_NAMELEN limit\n");
1.97      daniel   2282:            while ((IS_LETTER(cur)) || (IS_DIGIT(cur)) ||
                   2283:                   (cur == '.') || (cur == '-') ||
                   2284:                   (cur == '_') || (cur == ':') || 
                   2285:                   (IS_COMBINING(cur)) ||
                   2286:                   (IS_EXTENDER(cur))) {
                   2287:                NEXT;
                   2288:                cur = CUR;
                   2289:            }
1.91      daniel   2290:            break;
                   2291:        }
                   2292:     }
                   2293:     return(xmlStrndup(buf, len));
1.22      daniel   2294: }
                   2295: 
1.50      daniel   2296: /**
                   2297:  * xmlParseNmtoken:
                   2298:  * @ctxt:  an XML parser context
                   2299:  * 
                   2300:  * parse an XML Nmtoken.
1.22      daniel   2301:  *
                   2302:  * [7] Nmtoken ::= (NameChar)+
                   2303:  *
                   2304:  * [8] Nmtokens ::= Nmtoken (S Nmtoken)*
1.68      daniel   2305:  *
                   2306:  * Returns the Nmtoken parsed or NULL
1.22      daniel   2307:  */
                   2308: 
1.123     daniel   2309: xmlChar *
1.55      daniel   2310: xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
1.123     daniel   2311:     xmlChar buf[XML_MAX_NAMELEN];
1.91      daniel   2312:     int len = 0;
1.22      daniel   2313: 
1.91      daniel   2314:     GROW;
1.40      daniel   2315:     while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
                   2316:            (CUR == '.') || (CUR == '-') ||
                   2317:           (CUR == '_') || (CUR == ':') || 
                   2318:           (IS_COMBINING(CUR)) ||
1.91      daniel   2319:           (IS_EXTENDER(CUR))) {
                   2320:        buf[len++] = CUR;
1.40      daniel   2321:        NEXT;
1.91      daniel   2322:        if (len >= XML_MAX_NAMELEN) {
                   2323:            fprintf(stderr, 
                   2324:               "xmlParseNmtoken: reached XML_MAX_NAMELEN limit\n");
                   2325:            while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
                   2326:                   (CUR == '.') || (CUR == '-') ||
                   2327:                   (CUR == '_') || (CUR == ':') || 
                   2328:                   (IS_COMBINING(CUR)) ||
                   2329:                   (IS_EXTENDER(CUR)))
                   2330:                 NEXT;
                   2331:            break;
                   2332:        }
                   2333:     }
                   2334:     return(xmlStrndup(buf, len));
1.1       veillard 2335: }
                   2336: 
1.50      daniel   2337: /**
                   2338:  * xmlParseEntityValue:
                   2339:  * @ctxt:  an XML parser context
1.78      daniel   2340:  * @orig:  if non-NULL store a copy of the original entity value
1.50      daniel   2341:  *
                   2342:  * parse a value for ENTITY decl.
1.24      daniel   2343:  *
                   2344:  * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
                   2345:  *                    "'" ([^%&'] | PEReference | Reference)* "'"
1.68      daniel   2346:  *
1.78      daniel   2347:  * Returns the EntityValue parsed with reference substitued or NULL
1.24      daniel   2348:  */
                   2349: 
1.123     daniel   2350: xmlChar *
                   2351: xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
                   2352:     xmlChar *ret = NULL;
                   2353:     const xmlChar *org = NULL;
                   2354:     const xmlChar *tst = NULL;
                   2355:     const xmlChar *temp = NULL;
1.98      daniel   2356:     xmlParserInputPtr input;
1.24      daniel   2357: 
1.91      daniel   2358:     SHRINK;
1.40      daniel   2359:     if (CUR == '"') {
1.96      daniel   2360:        ctxt->instate = XML_PARSER_ENTITY_VALUE;
1.98      daniel   2361:        input = ctxt->input;
1.40      daniel   2362:         NEXT;
1.78      daniel   2363:        org = CUR_PTR;
1.98      daniel   2364:        /*
                   2365:         * NOTE: 4.4.5 Included in Literal
                   2366:         * When a parameter entity reference appears in a literal entity
                   2367:         * value, ... a single or double quote character in the replacement
                   2368:         * text is always treated as a normal data character and will not
                   2369:         * terminate the literal. 
                   2370:         * In practice it means we stop the loop only when back at parsing
                   2371:         * the initial entity and the quote is found
                   2372:         */
                   2373:        while ((CUR != '"') || (ctxt->input != input)) {
1.79      daniel   2374:            tst = CUR_PTR;
1.98      daniel   2375:            /*
                   2376:             * NOTE: 4.4.7 Bypassed
                   2377:             * When a general entity reference appears in the EntityValue in
                   2378:             * an entity declaration, it is bypassed and left as is.
                   2379:             * so XML_SUBSTITUTE_REF is not set.
                   2380:             */
                   2381:            if (ctxt->input != input)
                   2382:                temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF,
                   2383:                                         0, 0, 0);
                   2384:            else 
                   2385:                temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF,
                   2386:                                         '"', 0, 0);
1.94      daniel   2387: 
                   2388:            /*
                   2389:             * Pop-up of finished entities.
                   2390:             */
                   2391:            while ((CUR == 0) && (ctxt->inputNr > 1))
                   2392:                xmlPopInput(ctxt);
                   2393: 
                   2394:            if ((temp == NULL) && (tst == CUR_PTR)) {
1.123     daniel   2395:                ret = xmlStrndup((xmlChar *) "", 0);
1.94      daniel   2396:                break;
                   2397:            }
                   2398:            if ((temp[0] == 0) && (tst == CUR_PTR)) {
1.119     daniel   2399:                xmlFree((char *)temp);
1.123     daniel   2400:                ret = xmlStrndup((xmlChar *) "", 0);
1.94      daniel   2401:                break;
                   2402:            }
1.79      daniel   2403:            ret = xmlStrcat(ret, temp);
1.119     daniel   2404:            if (temp != NULL) xmlFree((char *)temp);
1.94      daniel   2405:            GROW;
1.79      daniel   2406:        }
1.77      daniel   2407:         if (CUR != '"') {
1.123     daniel   2408:            ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
1.55      daniel   2409:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.79      daniel   2410:                ctxt->sax->error(ctxt->userData, "EntityValue: \" expected\n");
1.59      daniel   2411:            ctxt->wellFormed = 0;
1.78      daniel   2412:        } else {
1.99      daniel   2413:            if (orig != NULL) /* !!!!!!!!! */
1.78      daniel   2414:                *orig = xmlStrndup(org, CUR_PTR - org);
1.94      daniel   2415:            if (ret == NULL)
1.123     daniel   2416:                ret = xmlStrndup((xmlChar *) "", 0);
1.40      daniel   2417:            NEXT;
1.78      daniel   2418:        }
1.40      daniel   2419:     } else if (CUR == '\'') {
1.96      daniel   2420:        ctxt->instate = XML_PARSER_ENTITY_VALUE;
1.98      daniel   2421:        input = ctxt->input;
1.40      daniel   2422:         NEXT;
1.78      daniel   2423:        org = CUR_PTR;
1.98      daniel   2424:        /*
                   2425:         * NOTE: 4.4.5 Included in Literal
                   2426:         * When a parameter entity reference appears in a literal entity
                   2427:         * value, ... a single or double quote character in the replacement
                   2428:         * text is always treated as a normal data character and will not
                   2429:         * terminate the literal. 
                   2430:         * In practice it means we stop the loop only when back at parsing
                   2431:         * the initial entity and the quote is found
                   2432:         */
                   2433:        while ((CUR != '\'') || (ctxt->input != input)) {
1.79      daniel   2434:            tst = CUR_PTR;
1.98      daniel   2435:            /*
                   2436:             * NOTE: 4.4.7 Bypassed
                   2437:             * When a general entity reference appears in the EntityValue in
                   2438:             * an entity declaration, it is bypassed and left as is.
                   2439:             * so XML_SUBSTITUTE_REF is not set.
                   2440:             */
                   2441:            if (ctxt->input != input)
                   2442:                temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF,
                   2443:                                         0, 0, 0);
                   2444:            else 
                   2445:                temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_PEREF,
                   2446:                                         '\'', 0, 0);
1.94      daniel   2447: 
                   2448:            /*
                   2449:             * Pop-up of finished entities.
                   2450:             */
                   2451:            while ((CUR == 0) && (ctxt->inputNr > 1))
                   2452:                xmlPopInput(ctxt);
                   2453: 
                   2454:            if ((temp == NULL) && (tst == CUR_PTR)) {
1.123     daniel   2455:                ret = xmlStrndup((xmlChar *) "", 0);
1.94      daniel   2456:                break;
                   2457:            }
                   2458:            if ((temp[0] == 0) && (tst == CUR_PTR)) {
1.119     daniel   2459:                xmlFree((char *)temp);
1.123     daniel   2460:                ret = xmlStrndup((xmlChar *) "", 0);
1.94      daniel   2461:                break;
                   2462:            }
1.79      daniel   2463:            ret = xmlStrcat(ret, temp);
1.119     daniel   2464:            if (temp != NULL) xmlFree((char *)temp);
1.94      daniel   2465:            GROW;
1.79      daniel   2466:        }
1.77      daniel   2467:         if (CUR != '\'') {
1.123     daniel   2468:            ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
1.55      daniel   2469:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.77      daniel   2470:                ctxt->sax->error(ctxt->userData, "EntityValue: ' expected\n");
1.59      daniel   2471:            ctxt->wellFormed = 0;
1.78      daniel   2472:        } else {
1.99      daniel   2473:            if (orig != NULL) /* !!!!!!!!! */
1.78      daniel   2474:                *orig = xmlStrndup(org, CUR_PTR - org);
1.94      daniel   2475:            if (ret == NULL)
1.123     daniel   2476:                ret = xmlStrndup((xmlChar *) "", 0);
1.40      daniel   2477:            NEXT;
1.78      daniel   2478:        }
1.24      daniel   2479:     } else {
1.123     daniel   2480:        ctxt->errNo = XML_ERR_ENTITY_NOT_STARTED;
1.55      daniel   2481:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.77      daniel   2482:            ctxt->sax->error(ctxt->userData, "EntityValue: \" or ' expected\n");
1.59      daniel   2483:        ctxt->wellFormed = 0;
1.24      daniel   2484:     }
                   2485:     
                   2486:     return(ret);
                   2487: }
                   2488: 
1.50      daniel   2489: /**
                   2490:  * xmlParseAttValue:
                   2491:  * @ctxt:  an XML parser context
                   2492:  *
                   2493:  * parse a value for an attribute
1.78      daniel   2494:  * Note: the parser won't do substitution of entities here, this
1.113     daniel   2495:  * will be handled later in xmlStringGetNodeList
1.29      daniel   2496:  *
                   2497:  * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
                   2498:  *                   "'" ([^<&'] | Reference)* "'"
1.68      daniel   2499:  *
1.129     daniel   2500:  * 3.3.3 Attribute-Value Normalization:
                   2501:  * Before the value of an attribute is passed to the application or
                   2502:  * checked for validity, the XML processor must normalize it as follows: 
                   2503:  * - a character reference is processed by appending the referenced
                   2504:  *   character to the attribute value
                   2505:  * - an entity reference is processed by recursively processing the
                   2506:  *   replacement text of the entity 
                   2507:  * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
                   2508:  *   appending #x20 to the normalized value, except that only a single
                   2509:  *   #x20 is appended for a "#xD#xA" sequence that is part of an external
                   2510:  *   parsed entity or the literal entity value of an internal parsed entity 
                   2511:  * - other characters are processed by appending them to the normalized value 
1.130     daniel   2512:  * If the declared value is not CDATA, then the XML processor must further
                   2513:  * process the normalized attribute value by discarding any leading and
                   2514:  * trailing space (#x20) characters, and by replacing sequences of space
                   2515:  * (#x20) characters by a single space (#x20) character.  
                   2516:  * All attributes for which no declaration has been read should be treated
                   2517:  * by a non-validating parser as if declared CDATA.
1.129     daniel   2518:  *
                   2519:  * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
1.29      daniel   2520:  */
                   2521: 
1.123     daniel   2522: xmlChar *
1.55      daniel   2523: xmlParseAttValue(xmlParserCtxtPtr ctxt) {
1.129     daniel   2524:     xmlChar limit = 0;
                   2525:     xmlChar *buffer = NULL;
                   2526:     int buffer_size = 0;
                   2527:     xmlChar *out = NULL;
                   2528: 
                   2529:     xmlChar *current = NULL;
                   2530:     xmlEntityPtr ent;
                   2531:     xmlChar cur;
                   2532: 
1.29      daniel   2533: 
1.91      daniel   2534:     SHRINK;
1.40      daniel   2535:     if (CUR == '"') {
1.96      daniel   2536:        ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
1.129     daniel   2537:        limit = '"';
1.40      daniel   2538:         NEXT;
                   2539:     } else if (CUR == '\'') {
1.129     daniel   2540:        limit = '\'';
1.96      daniel   2541:        ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
1.40      daniel   2542:         NEXT;
1.29      daniel   2543:     } else {
1.123     daniel   2544:        ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_STARTED;
1.55      daniel   2545:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2546:            ctxt->sax->error(ctxt->userData, "AttValue: \" or ' expected\n");
1.59      daniel   2547:        ctxt->wellFormed = 0;
1.129     daniel   2548:        return(NULL);
1.29      daniel   2549:     }
                   2550:     
1.129     daniel   2551:     /*
                   2552:      * allocate a translation buffer.
                   2553:      */
                   2554:     buffer_size = 100;
                   2555:     buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
                   2556:     if (buffer == NULL) {
                   2557:        perror("xmlParseAttValue: malloc failed");
                   2558:        return(NULL);
                   2559:     }
                   2560:     out = buffer;
                   2561: 
                   2562:     /*
                   2563:      * Ok loop until we reach one of the ending char or a size limit.
                   2564:      */
                   2565:     cur = CUR;
                   2566:     while ((cur != limit) && (cur != '<')) {
                   2567: 
                   2568:        if (cur == 0) break;
                   2569:         if ((cur == '&') && (NXT(1) == '#')) {
                   2570:            int val = xmlParseCharRef(ctxt);
                   2571:            *out++ = val;
                   2572:        } else if (cur == '&') {
                   2573:            ent = xmlParseEntityRef(ctxt);
                   2574:            if ((ent != NULL) && 
                   2575:                (ctxt->replaceEntities != 0)) {
                   2576:                current = ent->content;
                   2577:                while (*current != 0) {
                   2578:                    *out++ = *current++;
                   2579:                    if (out - buffer > buffer_size - 10) {
                   2580:                        int index = out - buffer;
                   2581: 
                   2582:                        growBuffer(buffer);
                   2583:                        out = &buffer[index];
                   2584:                    }
                   2585:                }
                   2586:            } else if (ent != NULL) {
                   2587:                int i = xmlStrlen(ent->name);
                   2588:                const xmlChar *cur = ent->name;
                   2589: 
                   2590:                *out++ = '&';
                   2591:                if (out - buffer > buffer_size - i - 10) {
                   2592:                    int index = out - buffer;
                   2593: 
                   2594:                    growBuffer(buffer);
                   2595:                    out = &buffer[index];
                   2596:                }
                   2597:                for (;i > 0;i--)
                   2598:                    *out++ = *cur++;
                   2599:                *out++ = ';';
                   2600:            }
                   2601:        } else {
                   2602:            /*  invalid for UTF-8 , use COPY(out); !!!!!! */
                   2603:            if ((cur == 0x20) || (cur == 0xD) || (cur == 0xA) || (cur == 0x9)) {
1.130     daniel   2604:                *out++ = 0x20;
                   2605:                if (out - buffer > buffer_size - 10) {
                   2606:                  int index = out - buffer;
                   2607:                  
                   2608:                  growBuffer(buffer);
                   2609:                  out = &buffer[index];
1.129     daniel   2610:                }
                   2611:            } else {
                   2612:                *out++ = cur;
                   2613:                if (out - buffer > buffer_size - 10) {
                   2614:                  int index = out - buffer;
                   2615:                  
                   2616:                  growBuffer(buffer);
                   2617:                  out = &buffer[index];
                   2618:                }
                   2619:            }
                   2620:            NEXT;
                   2621:        }
                   2622:        cur = CUR;
                   2623:     }
                   2624:     *out++ = 0;
                   2625:     if (CUR == '<') {
                   2626:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   2627:            ctxt->sax->error(ctxt->userData,
                   2628:               "Unescaped '<' not allowed in attributes values\n");
                   2629:        ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
                   2630:        ctxt->wellFormed = 0;
                   2631:     } else if (CUR != limit) {
                   2632:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   2633:            ctxt->sax->error(ctxt->userData, "AttValue: ' expected\n");
                   2634:        ctxt->errNo = XML_ERR_ATTRIBUTE_NOT_FINISHED;
                   2635:        ctxt->wellFormed = 0;
                   2636:     } else
                   2637:        NEXT;
                   2638:     return(buffer);
1.29      daniel   2639: }
                   2640: 
1.50      daniel   2641: /**
                   2642:  * xmlParseSystemLiteral:
                   2643:  * @ctxt:  an XML parser context
                   2644:  * 
                   2645:  * parse an XML Literal
1.21      daniel   2646:  *
1.22      daniel   2647:  * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
1.68      daniel   2648:  *
                   2649:  * Returns the SystemLiteral parsed or NULL
1.21      daniel   2650:  */
                   2651: 
1.123     daniel   2652: xmlChar *
1.55      daniel   2653: xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
1.123     daniel   2654:     const xmlChar *q;
                   2655:     xmlChar *ret = NULL;
1.21      daniel   2656: 
1.91      daniel   2657:     SHRINK;
1.40      daniel   2658:     if (CUR == '"') {
                   2659:         NEXT;
                   2660:        q = CUR_PTR;
                   2661:        while ((IS_CHAR(CUR)) && (CUR != '"'))
                   2662:            NEXT;
                   2663:        if (!IS_CHAR(CUR)) {
1.55      daniel   2664:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2665:                ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n");
1.123     daniel   2666:            ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
1.59      daniel   2667:            ctxt->wellFormed = 0;
1.21      daniel   2668:        } else {
1.40      daniel   2669:            ret = xmlStrndup(q, CUR_PTR - q);
                   2670:            NEXT;
1.21      daniel   2671:         }
1.40      daniel   2672:     } else if (CUR == '\'') {
                   2673:         NEXT;
                   2674:        q = CUR_PTR;
                   2675:        while ((IS_CHAR(CUR)) && (CUR != '\''))
                   2676:            NEXT;
                   2677:        if (!IS_CHAR(CUR)) {
1.55      daniel   2678:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2679:                ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n");
1.123     daniel   2680:            ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
1.59      daniel   2681:            ctxt->wellFormed = 0;
1.21      daniel   2682:        } else {
1.40      daniel   2683:            ret = xmlStrndup(q, CUR_PTR - q);
                   2684:            NEXT;
1.21      daniel   2685:         }
                   2686:     } else {
1.55      daniel   2687:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   2688:            ctxt->sax->error(ctxt->userData,
                   2689:                             "SystemLiteral \" or ' expected\n");
1.123     daniel   2690:        ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
1.59      daniel   2691:        ctxt->wellFormed = 0;
1.21      daniel   2692:     }
                   2693:     
                   2694:     return(ret);
                   2695: }
                   2696: 
1.50      daniel   2697: /**
                   2698:  * xmlParsePubidLiteral:
                   2699:  * @ctxt:  an XML parser context
1.21      daniel   2700:  *
1.50      daniel   2701:  * parse an XML public literal
1.68      daniel   2702:  *
                   2703:  * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
                   2704:  *
                   2705:  * Returns the PubidLiteral parsed or NULL.
1.21      daniel   2706:  */
                   2707: 
1.123     daniel   2708: xmlChar *
1.55      daniel   2709: xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
1.123     daniel   2710:     const xmlChar *q;
                   2711:     xmlChar *ret = NULL;
1.125     daniel   2712: 
1.91      daniel   2713:     SHRINK;
1.40      daniel   2714:     if (CUR == '"') {
                   2715:         NEXT;
                   2716:        q = CUR_PTR;
                   2717:        while (IS_PUBIDCHAR(CUR)) NEXT;
                   2718:        if (CUR != '"') {
1.55      daniel   2719:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2720:                ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n");
1.123     daniel   2721:            ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
1.59      daniel   2722:            ctxt->wellFormed = 0;
1.21      daniel   2723:        } else {
1.40      daniel   2724:            ret = xmlStrndup(q, CUR_PTR - q);
                   2725:            NEXT;
1.21      daniel   2726:        }
1.40      daniel   2727:     } else if (CUR == '\'') {
                   2728:         NEXT;
                   2729:        q = CUR_PTR;
1.125     daniel   2730:        while (IS_PUBIDCHAR(CUR)) NEXT;
                   2731:        if (CUR != '\'') {
                   2732:           if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2733:                ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n");
1.123     daniel   2734:            ctxt->errNo = XML_ERR_LITERAL_NOT_FINISHED;
1.59      daniel   2735:            ctxt->wellFormed = 0;
1.21      daniel   2736:        } else {
1.40      daniel   2737:            ret = xmlStrndup(q, CUR_PTR - q);
                   2738:            NEXT;
1.21      daniel   2739:        }
                   2740:     } else {
1.55      daniel   2741:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   2742:            ctxt->sax->error(ctxt->userData,
                   2743:                             "SystemLiteral \" or ' expected\n");
1.123     daniel   2744:        ctxt->errNo = XML_ERR_LITERAL_NOT_STARTED;
1.59      daniel   2745:        ctxt->wellFormed = 0;
1.21      daniel   2746:     }
                   2747:     
                   2748:     return(ret);
                   2749: }
                   2750: 
1.50      daniel   2751: /**
                   2752:  * xmlParseCharData:
                   2753:  * @ctxt:  an XML parser context
                   2754:  * @cdata:  int indicating whether we are within a CDATA section
                   2755:  *
                   2756:  * parse a CharData section.
                   2757:  * if we are within a CDATA section ']]>' marks an end of section.
1.27      daniel   2758:  *
                   2759:  * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
                   2760:  */
                   2761: 
1.55      daniel   2762: void
                   2763: xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
1.123     daniel   2764:     xmlChar buf[1000];
1.91      daniel   2765:     int nbchar = 0;
1.123     daniel   2766:     xmlChar cur;
1.27      daniel   2767: 
1.91      daniel   2768:     SHRINK;
1.97      daniel   2769:     /*
                   2770:      * !!!!!!!!!!!!
                   2771:      * NOTE: NXT(0) is used here to avoid breaking on &lt; or &amp;
                   2772:      *       entities substitutions.
                   2773:      */
                   2774:     cur = CUR;
                   2775:     while ((IS_CHAR(cur)) && (cur != '<') &&
                   2776:            (cur != '&')) {
                   2777:        if ((cur == ']') && (NXT(1) == ']') &&
1.59      daniel   2778:            (NXT(2) == '>')) {
                   2779:            if (cdata) break;
                   2780:            else {
                   2781:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2782:                    ctxt->sax->error(ctxt->userData,
1.59      daniel   2783:                       "Sequence ']]>' not allowed in content\n");
1.123     daniel   2784:                ctxt->errNo = XML_ERR_MISPLACED_CDATA_END;
1.59      daniel   2785:                ctxt->wellFormed = 0;
                   2786:            }
                   2787:        }
1.91      daniel   2788:        buf[nbchar++] = CUR;
                   2789:        if (nbchar == 1000) {
                   2790:            /*
                   2791:             * Ok the segment is to be consumed as chars.
                   2792:             */
                   2793:            if (ctxt->sax != NULL) {
                   2794:                if (areBlanks(ctxt, buf, nbchar)) {
                   2795:                    if (ctxt->sax->ignorableWhitespace != NULL)
                   2796:                        ctxt->sax->ignorableWhitespace(ctxt->userData,
                   2797:                                                       buf, nbchar);
                   2798:                } else {
                   2799:                    if (ctxt->sax->characters != NULL)
                   2800:                        ctxt->sax->characters(ctxt->userData, buf, nbchar);
                   2801:                }
                   2802:            }
                   2803:            nbchar = 0;
                   2804:        }
1.40      daniel   2805:         NEXT;
1.97      daniel   2806:        cur = CUR;
1.27      daniel   2807:     }
1.91      daniel   2808:     if (nbchar != 0) {
                   2809:        /*
                   2810:         * Ok the segment is to be consumed as chars.
                   2811:         */
                   2812:        if (ctxt->sax != NULL) {
                   2813:            if (areBlanks(ctxt, buf, nbchar)) {
                   2814:                if (ctxt->sax->ignorableWhitespace != NULL)
                   2815:                    ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
                   2816:            } else {
                   2817:                if (ctxt->sax->characters != NULL)
                   2818:                    ctxt->sax->characters(ctxt->userData, buf, nbchar);
                   2819:            }
                   2820:        }
1.45      daniel   2821:     }
1.27      daniel   2822: }
                   2823: 
1.50      daniel   2824: /**
                   2825:  * xmlParseExternalID:
                   2826:  * @ctxt:  an XML parser context
1.123     daniel   2827:  * @publicID:  a xmlChar** receiving PubidLiteral
1.67      daniel   2828:  * @strict: indicate whether we should restrict parsing to only
                   2829:  *          production [75], see NOTE below
1.50      daniel   2830:  *
1.67      daniel   2831:  * Parse an External ID or a Public ID
                   2832:  *
                   2833:  * NOTE: Productions [75] and [83] interract badly since [75] can generate
                   2834:  *       'PUBLIC' S PubidLiteral S SystemLiteral
1.22      daniel   2835:  *
                   2836:  * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
                   2837:  *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
1.67      daniel   2838:  *
                   2839:  * [83] PublicID ::= 'PUBLIC' S PubidLiteral
                   2840:  *
1.68      daniel   2841:  * Returns the function returns SystemLiteral and in the second
1.67      daniel   2842:  *                case publicID receives PubidLiteral, is strict is off
                   2843:  *                it is possible to return NULL and have publicID set.
1.22      daniel   2844:  */
                   2845: 
1.123     daniel   2846: xmlChar *
                   2847: xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
                   2848:     xmlChar *URI = NULL;
1.22      daniel   2849: 
1.91      daniel   2850:     SHRINK;
1.40      daniel   2851:     if ((CUR == 'S') && (NXT(1) == 'Y') &&
                   2852:          (NXT(2) == 'S') && (NXT(3) == 'T') &&
                   2853:         (NXT(4) == 'E') && (NXT(5) == 'M')) {
                   2854:         SKIP(6);
1.59      daniel   2855:        if (!IS_BLANK(CUR)) {
                   2856:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2857:                ctxt->sax->error(ctxt->userData,
1.59      daniel   2858:                    "Space required after 'SYSTEM'\n");
1.123     daniel   2859:            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   2860:            ctxt->wellFormed = 0;
                   2861:        }
1.42      daniel   2862:         SKIP_BLANKS;
1.39      daniel   2863:        URI = xmlParseSystemLiteral(ctxt);
1.59      daniel   2864:        if (URI == NULL) {
1.55      daniel   2865:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2866:                ctxt->sax->error(ctxt->userData,
1.39      daniel   2867:                  "xmlParseExternalID: SYSTEM, no URI\n");
1.123     daniel   2868:            ctxt->errNo = XML_ERR_URI_REQUIRED;
1.59      daniel   2869:            ctxt->wellFormed = 0;
                   2870:         }
1.40      daniel   2871:     } else if ((CUR == 'P') && (NXT(1) == 'U') &&
                   2872:               (NXT(2) == 'B') && (NXT(3) == 'L') &&
                   2873:               (NXT(4) == 'I') && (NXT(5) == 'C')) {
                   2874:         SKIP(6);
1.59      daniel   2875:        if (!IS_BLANK(CUR)) {
                   2876:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2877:                ctxt->sax->error(ctxt->userData,
1.59      daniel   2878:                    "Space required after 'PUBLIC'\n");
1.123     daniel   2879:            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   2880:            ctxt->wellFormed = 0;
                   2881:        }
1.42      daniel   2882:         SKIP_BLANKS;
1.39      daniel   2883:        *publicID = xmlParsePubidLiteral(ctxt);
1.59      daniel   2884:        if (*publicID == NULL) {
1.55      daniel   2885:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2886:                ctxt->sax->error(ctxt->userData, 
1.39      daniel   2887:                  "xmlParseExternalID: PUBLIC, no Public Identifier\n");
1.123     daniel   2888:            ctxt->errNo = XML_ERR_PUBID_REQUIRED;
1.59      daniel   2889:            ctxt->wellFormed = 0;
                   2890:        }
1.67      daniel   2891:        if (strict) {
                   2892:            /*
                   2893:             * We don't handle [83] so "S SystemLiteral" is required.
                   2894:             */
                   2895:            if (!IS_BLANK(CUR)) {
                   2896:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2897:                    ctxt->sax->error(ctxt->userData,
1.67      daniel   2898:                        "Space required after the Public Identifier\n");
1.123     daniel   2899:                ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.67      daniel   2900:                ctxt->wellFormed = 0;
                   2901:            }
                   2902:        } else {
                   2903:            /*
                   2904:             * We handle [83] so we return immediately, if 
                   2905:             * "S SystemLiteral" is not detected. From a purely parsing
                   2906:             * point of view that's a nice mess.
                   2907:             */
1.123     daniel   2908:            const xmlChar *ptr = CUR_PTR;
1.67      daniel   2909:            if (!IS_BLANK(*ptr)) return(NULL);
                   2910:            
                   2911:            while (IS_BLANK(*ptr)) ptr++;
                   2912:            if ((*ptr != '\'') || (*ptr != '"')) return(NULL);
1.59      daniel   2913:        }
1.42      daniel   2914:         SKIP_BLANKS;
1.39      daniel   2915:        URI = xmlParseSystemLiteral(ctxt);
1.59      daniel   2916:        if (URI == NULL) {
1.55      daniel   2917:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2918:                ctxt->sax->error(ctxt->userData, 
1.39      daniel   2919:                   "xmlParseExternalID: PUBLIC, no URI\n");
1.123     daniel   2920:            ctxt->errNo = XML_ERR_URI_REQUIRED;
1.59      daniel   2921:            ctxt->wellFormed = 0;
                   2922:         }
1.22      daniel   2923:     }
1.39      daniel   2924:     return(URI);
1.22      daniel   2925: }
                   2926: 
1.50      daniel   2927: /**
                   2928:  * xmlParseComment:
1.69      daniel   2929:  * @ctxt:  an XML parser context
1.50      daniel   2930:  *
1.3       veillard 2931:  * Skip an XML (SGML) comment <!-- .... -->
1.38      daniel   2932:  *  The spec says that "For compatibility, the string "--" (double-hyphen)
                   2933:  *  must not occur within comments. "
1.22      daniel   2934:  *
                   2935:  * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
1.3       veillard 2936:  */
1.72      daniel   2937: void
1.114     daniel   2938: xmlParseComment(xmlParserCtxtPtr ctxt) {
1.123     daniel   2939:     const xmlChar *q, *start;
                   2940:     const xmlChar *r;
                   2941:     xmlChar *val;
1.3       veillard 2942: 
                   2943:     /*
1.22      daniel   2944:      * Check that there is a comment right here.
1.3       veillard 2945:      */
1.40      daniel   2946:     if ((CUR != '<') || (NXT(1) != '!') ||
1.72      daniel   2947:         (NXT(2) != '-') || (NXT(3) != '-')) return;
1.3       veillard 2948: 
1.97      daniel   2949:     ctxt->instate = XML_PARSER_COMMENT;
1.91      daniel   2950:     SHRINK;
1.40      daniel   2951:     SKIP(4);
                   2952:     start = q = CUR_PTR;
                   2953:     NEXT;
                   2954:     r = CUR_PTR;
                   2955:     NEXT;
                   2956:     while (IS_CHAR(CUR) &&
                   2957:            ((CUR == ':') || (CUR != '>') ||
1.16      daniel   2958:            (*r != '-') || (*q != '-'))) {
1.59      daniel   2959:        if ((*r == '-') && (*q == '-')) {
1.55      daniel   2960:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2961:                ctxt->sax->error(ctxt->userData,
1.38      daniel   2962:               "Comment must not contain '--' (double-hyphen)`\n");
1.123     daniel   2963:            ctxt->errNo = XML_ERR_HYPHEN_IN_COMMENT;
1.59      daniel   2964:            ctxt->wellFormed = 0;
                   2965:        }
1.40      daniel   2966:         NEXT;r++;q++;
1.3       veillard 2967:     }
1.40      daniel   2968:     if (!IS_CHAR(CUR)) {
1.55      daniel   2969:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   2970:            ctxt->sax->error(ctxt->userData,
                   2971:                             "Comment not terminated \n<!--%.50s\n", start);
1.123     daniel   2972:        ctxt->errNo = XML_ERR_COMMENT_NOT_FINISHED;
1.59      daniel   2973:        ctxt->wellFormed = 0;
1.3       veillard 2974:     } else {
1.40      daniel   2975:         NEXT;
1.114     daniel   2976:        val = xmlStrndup(start, q - start);
                   2977:        if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL))
                   2978:            ctxt->sax->comment(ctxt->userData, val);
1.119     daniel   2979:        xmlFree(val);
1.3       veillard 2980:     }
                   2981: }
                   2982: 
1.50      daniel   2983: /**
                   2984:  * xmlParsePITarget:
                   2985:  * @ctxt:  an XML parser context
                   2986:  * 
                   2987:  * parse the name of a PI
1.22      daniel   2988:  *
                   2989:  * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
1.68      daniel   2990:  *
                   2991:  * Returns the PITarget name or NULL
1.22      daniel   2992:  */
                   2993: 
1.123     daniel   2994: xmlChar *
1.55      daniel   2995: xmlParsePITarget(xmlParserCtxtPtr ctxt) {
1.123     daniel   2996:     xmlChar *name;
1.22      daniel   2997: 
                   2998:     name = xmlParseName(ctxt);
                   2999:     if ((name != NULL) && (name[3] == 0) &&
                   3000:         ((name[0] == 'x') || (name[0] == 'X')) &&
1.31      daniel   3001:         ((name[1] == 'm') || (name[1] == 'M')) &&
                   3002:         ((name[2] == 'l') || (name[2] == 'L'))) {
1.122     daniel   3003:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) {
                   3004:            ctxt->sax->error(ctxt->userData,
                   3005:                 "xmlParsePItarget: invalid name prefix 'xml'\n");
1.123     daniel   3006:            ctxt->errNo = XML_ERR_RESERVED_XML_NAME;
1.122     daniel   3007:            /* ctxt->wellFormed = 0; !!! ? */
                   3008:        }
1.22      daniel   3009:        return(NULL);
                   3010:     }
                   3011:     return(name);
                   3012: }
                   3013: 
1.50      daniel   3014: /**
                   3015:  * xmlParsePI:
                   3016:  * @ctxt:  an XML parser context
                   3017:  * 
                   3018:  * parse an XML Processing Instruction.
1.22      daniel   3019:  *
                   3020:  * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
1.68      daniel   3021:  *
1.69      daniel   3022:  * The processing is transfered to SAX once parsed.
1.3       veillard 3023:  */
                   3024: 
1.55      daniel   3025: void
                   3026: xmlParsePI(xmlParserCtxtPtr ctxt) {
1.123     daniel   3027:     xmlChar *target;
1.22      daniel   3028: 
1.40      daniel   3029:     if ((CUR == '<') && (NXT(1) == '?')) {
1.3       veillard 3030:        /*
                   3031:         * this is a Processing Instruction.
                   3032:         */
1.40      daniel   3033:        SKIP(2);
1.91      daniel   3034:        SHRINK;
1.3       veillard 3035: 
                   3036:        /*
1.22      daniel   3037:         * Parse the target name and check for special support like
                   3038:         * namespace.
1.3       veillard 3039:         */
1.22      daniel   3040:         target = xmlParsePITarget(ctxt);
                   3041:        if (target != NULL) {
1.123     daniel   3042:            const xmlChar *q;
1.72      daniel   3043: 
1.114     daniel   3044:            if (!IS_BLANK(CUR)) {
                   3045:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   3046:                    ctxt->sax->error(ctxt->userData,
                   3047:                      "xmlParsePI: PI %s space expected\n", target);
1.123     daniel   3048:                ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.114     daniel   3049:                ctxt->wellFormed = 0;
                   3050:            }
                   3051:             SKIP_BLANKS;
                   3052:            q = CUR_PTR;
1.72      daniel   3053:            while (IS_CHAR(CUR) &&
                   3054:                   ((CUR != '?') || (NXT(1) != '>')))
                   3055:                NEXT;
                   3056:            if (!IS_CHAR(CUR)) {
                   3057:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3058:                    ctxt->sax->error(ctxt->userData,
1.72      daniel   3059:                      "xmlParsePI: PI %s never end ...\n", target);
1.123     daniel   3060:                ctxt->errNo = XML_ERR_PI_NOT_FINISHED;
1.72      daniel   3061:                ctxt->wellFormed = 0;
1.22      daniel   3062:            } else {
1.123     daniel   3063:                xmlChar *data;
1.44      daniel   3064: 
1.72      daniel   3065:                data = xmlStrndup(q, CUR_PTR - q);
                   3066:                SKIP(2);
1.44      daniel   3067: 
1.72      daniel   3068:                /*
                   3069:                 * SAX: PI detected.
                   3070:                 */
                   3071:                if ((ctxt->sax) &&
                   3072:                    (ctxt->sax->processingInstruction != NULL))
1.99      daniel   3073:                    ctxt->sax->processingInstruction(ctxt->userData,
                   3074:                                                     target, data);
1.119     daniel   3075:                xmlFree(data);
1.22      daniel   3076:            }
1.119     daniel   3077:            xmlFree(target);
1.3       veillard 3078:        } else {
1.55      daniel   3079:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.99      daniel   3080:                ctxt->sax->error(ctxt->userData,
                   3081:                       "xmlParsePI : no target name\n");
1.123     daniel   3082:            ctxt->errNo = XML_ERR_PI_NOT_STARTED;
1.59      daniel   3083:            ctxt->wellFormed = 0;
1.22      daniel   3084:        }
                   3085:     }
                   3086: }
                   3087: 
1.50      daniel   3088: /**
                   3089:  * xmlParseNotationDecl:
                   3090:  * @ctxt:  an XML parser context
                   3091:  *
                   3092:  * parse a notation declaration
1.22      daniel   3093:  *
                   3094:  * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
                   3095:  *
                   3096:  * Hence there is actually 3 choices:
                   3097:  *     'PUBLIC' S PubidLiteral
                   3098:  *     'PUBLIC' S PubidLiteral S SystemLiteral
                   3099:  * and 'SYSTEM' S SystemLiteral
1.50      daniel   3100:  *
1.67      daniel   3101:  * See the NOTE on xmlParseExternalID().
1.22      daniel   3102:  */
                   3103: 
1.55      daniel   3104: void
                   3105: xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
1.123     daniel   3106:     xmlChar *name;
                   3107:     xmlChar *Pubid;
                   3108:     xmlChar *Systemid;
1.22      daniel   3109:     
1.40      daniel   3110:     if ((CUR == '<') && (NXT(1) == '!') &&
                   3111:         (NXT(2) == 'N') && (NXT(3) == 'O') &&
                   3112:         (NXT(4) == 'T') && (NXT(5) == 'A') &&
                   3113:         (NXT(6) == 'T') && (NXT(7) == 'I') &&
1.67      daniel   3114:         (NXT(8) == 'O') && (NXT(9) == 'N')) {
1.91      daniel   3115:        SHRINK;
1.40      daniel   3116:        SKIP(10);
1.67      daniel   3117:        if (!IS_BLANK(CUR)) {
                   3118:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   3119:                ctxt->sax->error(ctxt->userData,
                   3120:                                 "Space required after '<!NOTATION'\n");
1.123     daniel   3121:            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.67      daniel   3122:            ctxt->wellFormed = 0;
                   3123:            return;
                   3124:        }
                   3125:        SKIP_BLANKS;
1.22      daniel   3126: 
                   3127:         name = xmlParseName(ctxt);
                   3128:        if (name == NULL) {
1.55      daniel   3129:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   3130:                ctxt->sax->error(ctxt->userData,
                   3131:                                 "NOTATION: Name expected here\n");
1.123     daniel   3132:            ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
1.67      daniel   3133:            ctxt->wellFormed = 0;
                   3134:            return;
                   3135:        }
                   3136:        if (!IS_BLANK(CUR)) {
                   3137:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3138:                ctxt->sax->error(ctxt->userData, 
1.67      daniel   3139:                     "Space required after the NOTATION name'\n");
1.123     daniel   3140:            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   3141:            ctxt->wellFormed = 0;
1.22      daniel   3142:            return;
                   3143:        }
1.42      daniel   3144:        SKIP_BLANKS;
1.67      daniel   3145: 
1.22      daniel   3146:        /*
1.67      daniel   3147:         * Parse the IDs.
1.22      daniel   3148:         */
1.67      daniel   3149:        Systemid = xmlParseExternalID(ctxt, &Pubid, 1);
                   3150:        SKIP_BLANKS;
                   3151: 
                   3152:        if (CUR == '>') {
1.40      daniel   3153:            NEXT;
1.72      daniel   3154:            if ((ctxt->sax != NULL) && (ctxt->sax->notationDecl != NULL))
1.74      daniel   3155:                ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
1.67      daniel   3156:        } else {
                   3157:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3158:                ctxt->sax->error(ctxt->userData,
1.67      daniel   3159:                       "'>' required to close NOTATION declaration\n");
1.123     daniel   3160:            ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
1.67      daniel   3161:            ctxt->wellFormed = 0;
                   3162:        }
1.119     daniel   3163:        xmlFree(name);
                   3164:        if (Systemid != NULL) xmlFree(Systemid);
                   3165:        if (Pubid != NULL) xmlFree(Pubid);
1.22      daniel   3166:     }
                   3167: }
                   3168: 
1.50      daniel   3169: /**
                   3170:  * xmlParseEntityDecl:
                   3171:  * @ctxt:  an XML parser context
                   3172:  *
                   3173:  * parse <!ENTITY declarations
1.22      daniel   3174:  *
                   3175:  * [70] EntityDecl ::= GEDecl | PEDecl
                   3176:  *
                   3177:  * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
                   3178:  *
                   3179:  * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
                   3180:  *
                   3181:  * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
                   3182:  *
                   3183:  * [74] PEDef ::= EntityValue | ExternalID
1.24      daniel   3184:  *
                   3185:  * [76] NDataDecl ::= S 'NDATA' S Name
1.99      daniel   3186:  *
                   3187:  * [ VC: Notation Declared ]
1.116     daniel   3188:  * The Name must match the declared name of a notation.
1.22      daniel   3189:  */
                   3190: 
1.55      daniel   3191: void
                   3192: xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
1.123     daniel   3193:     xmlChar *name = NULL;
                   3194:     xmlChar *value = NULL;
                   3195:     xmlChar *URI = NULL, *literal = NULL;
                   3196:     xmlChar *ndata = NULL;
1.39      daniel   3197:     int isParameter = 0;
1.123     daniel   3198:     xmlChar *orig = NULL;
1.22      daniel   3199:     
1.94      daniel   3200:     GROW;
1.40      daniel   3201:     if ((CUR == '<') && (NXT(1) == '!') &&
                   3202:         (NXT(2) == 'E') && (NXT(3) == 'N') &&
                   3203:         (NXT(4) == 'T') && (NXT(5) == 'I') &&
1.59      daniel   3204:         (NXT(6) == 'T') && (NXT(7) == 'Y')) {
1.96      daniel   3205:        ctxt->instate = XML_PARSER_ENTITY_DECL;
1.91      daniel   3206:        SHRINK;
1.40      daniel   3207:        SKIP(8);
1.59      daniel   3208:        if (!IS_BLANK(CUR)) {
                   3209:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   3210:                ctxt->sax->error(ctxt->userData,
                   3211:                                 "Space required after '<!ENTITY'\n");
1.123     daniel   3212:            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   3213:            ctxt->wellFormed = 0;
                   3214:        }
                   3215:        SKIP_BLANKS;
1.40      daniel   3216: 
                   3217:        if (CUR == '%') {
                   3218:            NEXT;
1.59      daniel   3219:            if (!IS_BLANK(CUR)) {
                   3220:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   3221:                    ctxt->sax->error(ctxt->userData,
                   3222:                                     "Space required after '%'\n");
1.123     daniel   3223:                ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   3224:                ctxt->wellFormed = 0;
                   3225:            }
1.42      daniel   3226:            SKIP_BLANKS;
1.39      daniel   3227:            isParameter = 1;
1.22      daniel   3228:        }
                   3229: 
                   3230:         name = xmlParseName(ctxt);
1.24      daniel   3231:        if (name == NULL) {
1.55      daniel   3232:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3233:                ctxt->sax->error(ctxt->userData, "xmlParseEntityDecl: no name\n");
1.123     daniel   3234:            ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59      daniel   3235:            ctxt->wellFormed = 0;
1.24      daniel   3236:             return;
                   3237:        }
1.59      daniel   3238:        if (!IS_BLANK(CUR)) {
                   3239:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3240:                ctxt->sax->error(ctxt->userData,
1.59      daniel   3241:                     "Space required after the entity name\n");
1.123     daniel   3242:            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   3243:            ctxt->wellFormed = 0;
                   3244:        }
1.42      daniel   3245:         SKIP_BLANKS;
1.24      daniel   3246: 
1.22      daniel   3247:        /*
1.68      daniel   3248:         * handle the various case of definitions...
1.22      daniel   3249:         */
1.39      daniel   3250:        if (isParameter) {
1.40      daniel   3251:            if ((CUR == '"') || (CUR == '\''))
1.78      daniel   3252:                value = xmlParseEntityValue(ctxt, &orig);
1.39      daniel   3253:                if (value) {
1.72      daniel   3254:                    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74      daniel   3255:                        ctxt->sax->entityDecl(ctxt->userData, name,
1.39      daniel   3256:                                    XML_INTERNAL_PARAMETER_ENTITY,
                   3257:                                    NULL, NULL, value);
                   3258:                }
1.24      daniel   3259:            else {
1.67      daniel   3260:                URI = xmlParseExternalID(ctxt, &literal, 1);
1.39      daniel   3261:                if (URI) {
1.72      daniel   3262:                    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74      daniel   3263:                        ctxt->sax->entityDecl(ctxt->userData, name,
1.39      daniel   3264:                                    XML_EXTERNAL_PARAMETER_ENTITY,
                   3265:                                    literal, URI, NULL);
                   3266:                }
1.24      daniel   3267:            }
                   3268:        } else {
1.40      daniel   3269:            if ((CUR == '"') || (CUR == '\'')) {
1.78      daniel   3270:                value = xmlParseEntityValue(ctxt, &orig);
1.72      daniel   3271:                if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74      daniel   3272:                    ctxt->sax->entityDecl(ctxt->userData, name,
1.39      daniel   3273:                                XML_INTERNAL_GENERAL_ENTITY,
                   3274:                                NULL, NULL, value);
                   3275:            } else {
1.67      daniel   3276:                URI = xmlParseExternalID(ctxt, &literal, 1);
1.59      daniel   3277:                if ((CUR != '>') && (!IS_BLANK(CUR))) {
                   3278:                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3279:                        ctxt->sax->error(ctxt->userData,
1.59      daniel   3280:                            "Space required before 'NDATA'\n");
1.123     daniel   3281:                    ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   3282:                    ctxt->wellFormed = 0;
                   3283:                }
1.42      daniel   3284:                SKIP_BLANKS;
1.40      daniel   3285:                if ((CUR == 'N') && (NXT(1) == 'D') &&
                   3286:                    (NXT(2) == 'A') && (NXT(3) == 'T') &&
                   3287:                    (NXT(4) == 'A')) {
                   3288:                    SKIP(5);
1.59      daniel   3289:                    if (!IS_BLANK(CUR)) {
                   3290:                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3291:                            ctxt->sax->error(ctxt->userData,
1.59      daniel   3292:                                "Space required after 'NDATA'\n");
1.123     daniel   3293:                        ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   3294:                        ctxt->wellFormed = 0;
                   3295:                    }
1.42      daniel   3296:                    SKIP_BLANKS;
1.24      daniel   3297:                    ndata = xmlParseName(ctxt);
1.116     daniel   3298:                    if ((ctxt->sax != NULL) &&
                   3299:                        (ctxt->sax->unparsedEntityDecl != NULL))
                   3300:                        ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
1.39      daniel   3301:                                    literal, URI, ndata);
                   3302:                } else {
1.72      daniel   3303:                    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74      daniel   3304:                        ctxt->sax->entityDecl(ctxt->userData, name,
1.39      daniel   3305:                                    XML_EXTERNAL_GENERAL_PARSED_ENTITY,
                   3306:                                    literal, URI, NULL);
1.24      daniel   3307:                }
                   3308:            }
                   3309:        }
1.42      daniel   3310:        SKIP_BLANKS;
1.40      daniel   3311:        if (CUR != '>') {
1.55      daniel   3312:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3313:                ctxt->sax->error(ctxt->userData, 
1.31      daniel   3314:                    "xmlParseEntityDecl: entity %s not terminated\n", name);
1.123     daniel   3315:            ctxt->errNo = XML_ERR_ENTITY_NOT_FINISHED;
1.59      daniel   3316:            ctxt->wellFormed = 0;
1.24      daniel   3317:        } else
1.40      daniel   3318:            NEXT;
1.78      daniel   3319:        if (orig != NULL) {
                   3320:            /*
1.98      daniel   3321:             * Ugly mechanism to save the raw entity value.
1.78      daniel   3322:             */
                   3323:            xmlEntityPtr cur = NULL;
                   3324: 
1.98      daniel   3325:            if (isParameter) {
                   3326:                if ((ctxt->sax != NULL) &&
                   3327:                    (ctxt->sax->getParameterEntity != NULL))
1.120     daniel   3328:                    cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
1.98      daniel   3329:            } else {
                   3330:                if ((ctxt->sax != NULL) &&
                   3331:                    (ctxt->sax->getEntity != NULL))
1.120     daniel   3332:                    cur = ctxt->sax->getEntity(ctxt->userData, name);
1.98      daniel   3333:            }
                   3334:             if (cur != NULL) {
                   3335:                if (cur->orig != NULL)
1.119     daniel   3336:                    xmlFree(orig);
1.98      daniel   3337:                else
                   3338:                    cur->orig = orig;
                   3339:            } else
1.119     daniel   3340:                xmlFree(orig);
1.78      daniel   3341:        }
1.119     daniel   3342:        if (name != NULL) xmlFree(name);
                   3343:        if (value != NULL) xmlFree(value);
                   3344:        if (URI != NULL) xmlFree(URI);
                   3345:        if (literal != NULL) xmlFree(literal);
                   3346:        if (ndata != NULL) xmlFree(ndata);
1.22      daniel   3347:     }
                   3348: }
                   3349: 
1.50      daniel   3350: /**
1.59      daniel   3351:  * xmlParseDefaultDecl:
                   3352:  * @ctxt:  an XML parser context
                   3353:  * @value:  Receive a possible fixed default value for the attribute
                   3354:  *
                   3355:  * Parse an attribute default declaration
                   3356:  *
                   3357:  * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
                   3358:  *
1.99      daniel   3359:  * [ VC: Required Attribute ]
1.117     daniel   3360:  * if the default declaration is the keyword #REQUIRED, then the
                   3361:  * attribute must be specified for all elements of the type in the
                   3362:  * attribute-list declaration.
1.99      daniel   3363:  *
                   3364:  * [ VC: Attribute Default Legal ]
1.102     daniel   3365:  * The declared default value must meet the lexical constraints of
                   3366:  * the declared attribute type c.f. xmlValidateAttributeDecl()
1.99      daniel   3367:  *
                   3368:  * [ VC: Fixed Attribute Default ]
1.117     daniel   3369:  * if an attribute has a default value declared with the #FIXED
                   3370:  * keyword, instances of that attribute must match the default value. 
1.99      daniel   3371:  *
                   3372:  * [ WFC: No < in Attribute Values ]
                   3373:  * handled in xmlParseAttValue()
                   3374:  *
1.59      daniel   3375:  * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
                   3376:  *          or XML_ATTRIBUTE_FIXED. 
                   3377:  */
                   3378: 
                   3379: int
1.123     daniel   3380: xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
1.59      daniel   3381:     int val;
1.123     daniel   3382:     xmlChar *ret;
1.59      daniel   3383: 
                   3384:     *value = NULL;
                   3385:     if ((CUR == '#') && (NXT(1) == 'R') &&
                   3386:         (NXT(2) == 'E') && (NXT(3) == 'Q') &&
                   3387:         (NXT(4) == 'U') && (NXT(5) == 'I') &&
                   3388:         (NXT(6) == 'R') && (NXT(7) == 'E') &&
                   3389:         (NXT(8) == 'D')) {
                   3390:        SKIP(9);
                   3391:        return(XML_ATTRIBUTE_REQUIRED);
                   3392:     }
                   3393:     if ((CUR == '#') && (NXT(1) == 'I') &&
                   3394:         (NXT(2) == 'M') && (NXT(3) == 'P') &&
                   3395:         (NXT(4) == 'L') && (NXT(5) == 'I') &&
                   3396:         (NXT(6) == 'E') && (NXT(7) == 'D')) {
                   3397:        SKIP(8);
                   3398:        return(XML_ATTRIBUTE_IMPLIED);
                   3399:     }
                   3400:     val = XML_ATTRIBUTE_NONE;
                   3401:     if ((CUR == '#') && (NXT(1) == 'F') &&
                   3402:         (NXT(2) == 'I') && (NXT(3) == 'X') &&
                   3403:         (NXT(4) == 'E') && (NXT(5) == 'D')) {
                   3404:        SKIP(6);
                   3405:        val = XML_ATTRIBUTE_FIXED;
                   3406:        if (!IS_BLANK(CUR)) {
                   3407:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   3408:                ctxt->sax->error(ctxt->userData,
                   3409:                                 "Space required after '#FIXED'\n");
1.123     daniel   3410:            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   3411:            ctxt->wellFormed = 0;
                   3412:        }
                   3413:        SKIP_BLANKS;
                   3414:     }
                   3415:     ret = xmlParseAttValue(ctxt);
1.96      daniel   3416:     ctxt->instate = XML_PARSER_DTD;
1.59      daniel   3417:     if (ret == NULL) {
                   3418:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3419:            ctxt->sax->error(ctxt->userData,
1.59      daniel   3420:               "Attribute default value declaration error\n");
                   3421:        ctxt->wellFormed = 0;
                   3422:     } else
                   3423:         *value = ret;
                   3424:     return(val);
                   3425: }
                   3426: 
                   3427: /**
1.66      daniel   3428:  * xmlParseNotationType:
                   3429:  * @ctxt:  an XML parser context
                   3430:  *
                   3431:  * parse an Notation attribute type.
                   3432:  *
1.99      daniel   3433:  * Note: the leading 'NOTATION' S part has already being parsed...
                   3434:  *
1.66      daniel   3435:  * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
                   3436:  *
1.99      daniel   3437:  * [ VC: Notation Attributes ]
1.117     daniel   3438:  * Values of this type must match one of the notation names included
1.99      daniel   3439:  * in the declaration; all notation names in the declaration must be declared. 
1.66      daniel   3440:  *
                   3441:  * Returns: the notation attribute tree built while parsing
                   3442:  */
                   3443: 
                   3444: xmlEnumerationPtr
                   3445: xmlParseNotationType(xmlParserCtxtPtr ctxt) {
1.123     daniel   3446:     xmlChar *name;
1.66      daniel   3447:     xmlEnumerationPtr ret = NULL, last = NULL, cur;
                   3448: 
                   3449:     if (CUR != '(') {
                   3450:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   3451:            ctxt->sax->error(ctxt->userData,
                   3452:                             "'(' required to start 'NOTATION'\n");
1.123     daniel   3453:        ctxt->errNo = XML_ERR_NOTATION_NOT_STARTED;
1.66      daniel   3454:        ctxt->wellFormed = 0;
                   3455:        return(NULL);
                   3456:     }
1.91      daniel   3457:     SHRINK;
1.66      daniel   3458:     do {
                   3459:         NEXT;
                   3460:        SKIP_BLANKS;
                   3461:         name = xmlParseName(ctxt);
                   3462:        if (name == NULL) {
                   3463:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3464:                ctxt->sax->error(ctxt->userData, 
1.66      daniel   3465:                                 "Name expected in NOTATION declaration\n");
1.123     daniel   3466:            ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.66      daniel   3467:            ctxt->wellFormed = 0;
                   3468:            return(ret);
                   3469:        }
                   3470:        cur = xmlCreateEnumeration(name);
1.119     daniel   3471:        xmlFree(name);
1.66      daniel   3472:        if (cur == NULL) return(ret);
                   3473:        if (last == NULL) ret = last = cur;
                   3474:        else {
                   3475:            last->next = cur;
                   3476:            last = cur;
                   3477:        }
                   3478:        SKIP_BLANKS;
                   3479:     } while (CUR == '|');
                   3480:     if (CUR != ')') {
                   3481:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3482:            ctxt->sax->error(ctxt->userData,
1.66      daniel   3483:                             "')' required to finish NOTATION declaration\n");
1.123     daniel   3484:        ctxt->errNo = XML_ERR_NOTATION_NOT_FINISHED;
1.66      daniel   3485:        ctxt->wellFormed = 0;
                   3486:        return(ret);
                   3487:     }
                   3488:     NEXT;
                   3489:     return(ret);
                   3490: }
                   3491: 
                   3492: /**
                   3493:  * xmlParseEnumerationType:
                   3494:  * @ctxt:  an XML parser context
                   3495:  *
                   3496:  * parse an Enumeration attribute type.
                   3497:  *
                   3498:  * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
                   3499:  *
1.99      daniel   3500:  * [ VC: Enumeration ]
1.117     daniel   3501:  * Values of this type must match one of the Nmtoken tokens in
1.99      daniel   3502:  * the declaration
                   3503:  *
1.66      daniel   3504:  * Returns: the enumeration attribute tree built while parsing
                   3505:  */
                   3506: 
                   3507: xmlEnumerationPtr
                   3508: xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
1.123     daniel   3509:     xmlChar *name;
1.66      daniel   3510:     xmlEnumerationPtr ret = NULL, last = NULL, cur;
                   3511: 
                   3512:     if (CUR != '(') {
                   3513:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3514:            ctxt->sax->error(ctxt->userData,
1.66      daniel   3515:                             "'(' required to start ATTLIST enumeration\n");
1.123     daniel   3516:        ctxt->errNo = XML_ERR_ATTLIST_NOT_STARTED;
1.66      daniel   3517:        ctxt->wellFormed = 0;
                   3518:        return(NULL);
                   3519:     }
1.91      daniel   3520:     SHRINK;
1.66      daniel   3521:     do {
                   3522:         NEXT;
                   3523:        SKIP_BLANKS;
                   3524:         name = xmlParseNmtoken(ctxt);
                   3525:        if (name == NULL) {
                   3526:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3527:                ctxt->sax->error(ctxt->userData, 
1.66      daniel   3528:                                 "NmToken expected in ATTLIST enumeration\n");
1.123     daniel   3529:            ctxt->errNo = XML_ERR_NMTOKEN_REQUIRED;
1.66      daniel   3530:            ctxt->wellFormed = 0;
                   3531:            return(ret);
                   3532:        }
                   3533:        cur = xmlCreateEnumeration(name);
1.119     daniel   3534:        xmlFree(name);
1.66      daniel   3535:        if (cur == NULL) return(ret);
                   3536:        if (last == NULL) ret = last = cur;
                   3537:        else {
                   3538:            last->next = cur;
                   3539:            last = cur;
                   3540:        }
                   3541:        SKIP_BLANKS;
                   3542:     } while (CUR == '|');
                   3543:     if (CUR != ')') {
                   3544:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3545:            ctxt->sax->error(ctxt->userData,
1.66      daniel   3546:                             "')' required to finish ATTLIST enumeration\n");
1.123     daniel   3547:        ctxt->errNo = XML_ERR_ATTLIST_NOT_FINISHED;
1.66      daniel   3548:        ctxt->wellFormed = 0;
                   3549:        return(ret);
                   3550:     }
                   3551:     NEXT;
                   3552:     return(ret);
                   3553: }
                   3554: 
                   3555: /**
1.50      daniel   3556:  * xmlParseEnumeratedType:
                   3557:  * @ctxt:  an XML parser context
1.66      daniel   3558:  * @tree:  the enumeration tree built while parsing
1.50      daniel   3559:  *
1.66      daniel   3560:  * parse an Enumerated attribute type.
1.22      daniel   3561:  *
                   3562:  * [57] EnumeratedType ::= NotationType | Enumeration
                   3563:  *
                   3564:  * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
                   3565:  *
1.50      daniel   3566:  *
1.66      daniel   3567:  * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
1.22      daniel   3568:  */
                   3569: 
1.66      daniel   3570: int
                   3571: xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
                   3572:     if ((CUR == 'N') && (NXT(1) == 'O') &&
                   3573:         (NXT(2) == 'T') && (NXT(3) == 'A') &&
                   3574:         (NXT(4) == 'T') && (NXT(5) == 'I') &&
                   3575:        (NXT(6) == 'O') && (NXT(7) == 'N')) {
                   3576:        SKIP(8);
                   3577:        if (!IS_BLANK(CUR)) {
                   3578:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   3579:                ctxt->sax->error(ctxt->userData,
                   3580:                                 "Space required after 'NOTATION'\n");
1.123     daniel   3581:            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.66      daniel   3582:            ctxt->wellFormed = 0;
                   3583:            return(0);
                   3584:        }
                   3585:         SKIP_BLANKS;
                   3586:        *tree = xmlParseNotationType(ctxt);
                   3587:        if (*tree == NULL) return(0);
                   3588:        return(XML_ATTRIBUTE_NOTATION);
                   3589:     }
                   3590:     *tree = xmlParseEnumerationType(ctxt);
                   3591:     if (*tree == NULL) return(0);
                   3592:     return(XML_ATTRIBUTE_ENUMERATION);
1.22      daniel   3593: }
                   3594: 
1.50      daniel   3595: /**
                   3596:  * xmlParseAttributeType:
                   3597:  * @ctxt:  an XML parser context
1.66      daniel   3598:  * @tree:  the enumeration tree built while parsing
1.50      daniel   3599:  *
1.59      daniel   3600:  * parse the Attribute list def for an element
1.22      daniel   3601:  *
                   3602:  * [54] AttType ::= StringType | TokenizedType | EnumeratedType
                   3603:  *
                   3604:  * [55] StringType ::= 'CDATA'
                   3605:  *
                   3606:  * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
                   3607:  *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
1.50      daniel   3608:  *
1.102     daniel   3609:  * Validity constraints for attribute values syntax are checked in
                   3610:  * xmlValidateAttributeValue()
                   3611:  *
1.99      daniel   3612:  * [ VC: ID ]
1.117     daniel   3613:  * Values of type ID must match the Name production. A name must not
1.99      daniel   3614:  * appear more than once in an XML document as a value of this type;
                   3615:  * i.e., ID values must uniquely identify the elements which bear them.
                   3616:  *
                   3617:  * [ VC: One ID per Element Type ]
1.117     daniel   3618:  * No element type may have more than one ID attribute specified.
1.99      daniel   3619:  *
                   3620:  * [ VC: ID Attribute Default ]
1.117     daniel   3621:  * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
1.99      daniel   3622:  *
                   3623:  * [ VC: IDREF ]
1.102     daniel   3624:  * Values of type IDREF must match the Name production, and values
1.117     daniel   3625:  * of type IDREFS must match Names; TODO each IDREF Name must match the value
                   3626:  * of an ID attribute on some element in the XML document; i.e. IDREF
1.99      daniel   3627:  * values must match the value of some ID attribute.
                   3628:  *
                   3629:  * [ VC: Entity Name ]
1.102     daniel   3630:  * Values of type ENTITY must match the Name production, values
1.117     daniel   3631:  * of type ENTITIES must match Names; TODO each Entity Name must match the
                   3632:  * name of an unparsed entity declared in the DTD.  
1.99      daniel   3633:  *
                   3634:  * [ VC: Name Token ]
1.102     daniel   3635:  * Values of type NMTOKEN must match the Nmtoken production; values
1.99      daniel   3636:  * of type NMTOKENS must match Nmtokens. 
                   3637:  *
1.69      daniel   3638:  * Returns the attribute type
1.22      daniel   3639:  */
1.59      daniel   3640: int 
1.66      daniel   3641: xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
1.91      daniel   3642:     SHRINK;
1.40      daniel   3643:     if ((CUR == 'C') && (NXT(1) == 'D') &&
                   3644:         (NXT(2) == 'A') && (NXT(3) == 'T') &&
                   3645:         (NXT(4) == 'A')) {
                   3646:        SKIP(5);
1.66      daniel   3647:        return(XML_ATTRIBUTE_CDATA);
1.40      daniel   3648:      } else if ((CUR == 'I') && (NXT(1) == 'D') &&
                   3649:         (NXT(2) == 'R') && (NXT(3) == 'E') &&
1.97      daniel   3650:         (NXT(4) == 'F') && (NXT(5) == 'S')) {
                   3651:        SKIP(6);
                   3652:        return(XML_ATTRIBUTE_IDREFS);
                   3653:      } else if ((CUR == 'I') && (NXT(1) == 'D') &&
                   3654:         (NXT(2) == 'R') && (NXT(3) == 'E') &&
1.40      daniel   3655:         (NXT(4) == 'F')) {
                   3656:        SKIP(5);
1.59      daniel   3657:        return(XML_ATTRIBUTE_IDREF);
1.66      daniel   3658:      } else if ((CUR == 'I') && (NXT(1) == 'D')) {
                   3659:         SKIP(2);
                   3660:        return(XML_ATTRIBUTE_ID);
1.40      daniel   3661:      } else if ((CUR == 'E') && (NXT(1) == 'N') &&
                   3662:         (NXT(2) == 'T') && (NXT(3) == 'I') &&
                   3663:         (NXT(4) == 'T') && (NXT(5) == 'Y')) {
                   3664:        SKIP(6);
1.59      daniel   3665:        return(XML_ATTRIBUTE_ENTITY);
1.40      daniel   3666:      } else if ((CUR == 'E') && (NXT(1) == 'N') &&
                   3667:         (NXT(2) == 'T') && (NXT(3) == 'I') &&
                   3668:         (NXT(4) == 'T') && (NXT(5) == 'I') &&
                   3669:         (NXT(6) == 'E') && (NXT(7) == 'S')) {
                   3670:        SKIP(8);
1.59      daniel   3671:        return(XML_ATTRIBUTE_ENTITIES);
1.40      daniel   3672:      } else if ((CUR == 'N') && (NXT(1) == 'M') &&
                   3673:         (NXT(2) == 'T') && (NXT(3) == 'O') &&
                   3674:         (NXT(4) == 'K') && (NXT(5) == 'E') &&
1.66      daniel   3675:         (NXT(6) == 'N') && (NXT(7) == 'S')) {
                   3676:        SKIP(8);
                   3677:        return(XML_ATTRIBUTE_NMTOKENS);
                   3678:      } else if ((CUR == 'N') && (NXT(1) == 'M') &&
                   3679:         (NXT(2) == 'T') && (NXT(3) == 'O') &&
                   3680:         (NXT(4) == 'K') && (NXT(5) == 'E') &&
1.40      daniel   3681:         (NXT(6) == 'N')) {
                   3682:        SKIP(7);
1.59      daniel   3683:        return(XML_ATTRIBUTE_NMTOKEN);
1.22      daniel   3684:      }
1.66      daniel   3685:      return(xmlParseEnumeratedType(ctxt, tree));
1.22      daniel   3686: }
                   3687: 
1.50      daniel   3688: /**
                   3689:  * xmlParseAttributeListDecl:
                   3690:  * @ctxt:  an XML parser context
                   3691:  *
                   3692:  * : parse the Attribute list def for an element
1.22      daniel   3693:  *
                   3694:  * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
                   3695:  *
                   3696:  * [53] AttDef ::= S Name S AttType S DefaultDecl
1.50      daniel   3697:  *
1.22      daniel   3698:  */
1.55      daniel   3699: void
                   3700: xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
1.123     daniel   3701:     xmlChar *elemName;
                   3702:     xmlChar *attrName;
1.103     daniel   3703:     xmlEnumerationPtr tree;
1.22      daniel   3704: 
1.40      daniel   3705:     if ((CUR == '<') && (NXT(1) == '!') &&
                   3706:         (NXT(2) == 'A') && (NXT(3) == 'T') &&
                   3707:         (NXT(4) == 'T') && (NXT(5) == 'L') &&
                   3708:         (NXT(6) == 'I') && (NXT(7) == 'S') &&
1.59      daniel   3709:         (NXT(8) == 'T')) {
1.40      daniel   3710:        SKIP(9);
1.59      daniel   3711:        if (!IS_BLANK(CUR)) {
                   3712:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   3713:                ctxt->sax->error(ctxt->userData,
                   3714:                                 "Space required after '<!ATTLIST'\n");
1.123     daniel   3715:            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   3716:            ctxt->wellFormed = 0;
                   3717:        }
1.42      daniel   3718:         SKIP_BLANKS;
1.59      daniel   3719:         elemName = xmlParseName(ctxt);
                   3720:        if (elemName == NULL) {
1.55      daniel   3721:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   3722:                ctxt->sax->error(ctxt->userData,
                   3723:                                 "ATTLIST: no name for Element\n");
1.123     daniel   3724:            ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59      daniel   3725:            ctxt->wellFormed = 0;
1.22      daniel   3726:            return;
                   3727:        }
1.42      daniel   3728:        SKIP_BLANKS;
1.40      daniel   3729:        while (CUR != '>') {
1.123     daniel   3730:            const xmlChar *check = CUR_PTR;
1.59      daniel   3731:            int type;
                   3732:            int def;
1.123     daniel   3733:            xmlChar *defaultValue = NULL;
1.59      daniel   3734: 
1.103     daniel   3735:             tree = NULL;
1.59      daniel   3736:            attrName = xmlParseName(ctxt);
                   3737:            if (attrName == NULL) {
                   3738:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   3739:                    ctxt->sax->error(ctxt->userData,
                   3740:                                     "ATTLIST: no name for Attribute\n");
1.123     daniel   3741:                ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59      daniel   3742:                ctxt->wellFormed = 0;
                   3743:                break;
                   3744:            }
1.97      daniel   3745:            GROW;
1.59      daniel   3746:            if (!IS_BLANK(CUR)) {
                   3747:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3748:                    ctxt->sax->error(ctxt->userData, 
1.59      daniel   3749:                        "Space required after the attribute name\n");
1.123     daniel   3750:                ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   3751:                ctxt->wellFormed = 0;
                   3752:                break;
                   3753:            }
                   3754:            SKIP_BLANKS;
                   3755: 
1.66      daniel   3756:            type = xmlParseAttributeType(ctxt, &tree);
1.59      daniel   3757:            if (type <= 0) break;
1.22      daniel   3758: 
1.97      daniel   3759:            GROW;
1.59      daniel   3760:            if (!IS_BLANK(CUR)) {
                   3761:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3762:                    ctxt->sax->error(ctxt->userData, 
1.59      daniel   3763:                        "Space required after the attribute type\n");
1.123     daniel   3764:                ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   3765:                ctxt->wellFormed = 0;
                   3766:                break;
                   3767:            }
1.42      daniel   3768:            SKIP_BLANKS;
1.59      daniel   3769: 
                   3770:            def = xmlParseDefaultDecl(ctxt, &defaultValue);
                   3771:            if (def <= 0) break;
                   3772: 
1.97      daniel   3773:            GROW;
1.59      daniel   3774:             if (CUR != '>') {
                   3775:                if (!IS_BLANK(CUR)) {
                   3776:                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3777:                        ctxt->sax->error(ctxt->userData, 
1.59      daniel   3778:                        "Space required after the attribute default value\n");
1.123     daniel   3779:                    ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   3780:                    ctxt->wellFormed = 0;
                   3781:                    break;
                   3782:                }
                   3783:                SKIP_BLANKS;
                   3784:            }
1.40      daniel   3785:            if (check == CUR_PTR) {
1.55      daniel   3786:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3787:                    ctxt->sax->error(ctxt->userData, 
1.59      daniel   3788:                    "xmlParseAttributeListDecl: detected internal error\n");
1.123     daniel   3789:                ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.22      daniel   3790:                break;
                   3791:            }
1.72      daniel   3792:            if ((ctxt->sax != NULL) && (ctxt->sax->attributeDecl != NULL))
1.74      daniel   3793:                ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
1.66      daniel   3794:                                type, def, defaultValue, tree);
1.59      daniel   3795:            if (attrName != NULL)
1.119     daniel   3796:                xmlFree(attrName);
1.59      daniel   3797:            if (defaultValue != NULL)
1.119     daniel   3798:                xmlFree(defaultValue);
1.97      daniel   3799:            GROW;
1.22      daniel   3800:        }
1.40      daniel   3801:        if (CUR == '>')
                   3802:            NEXT;
1.22      daniel   3803: 
1.119     daniel   3804:        xmlFree(elemName);
1.22      daniel   3805:     }
                   3806: }
                   3807: 
1.50      daniel   3808: /**
1.61      daniel   3809:  * xmlParseElementMixedContentDecl:
                   3810:  * @ctxt:  an XML parser context
                   3811:  *
                   3812:  * parse the declaration for a Mixed Element content
                   3813:  * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
                   3814:  * 
                   3815:  * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
                   3816:  *                '(' S? '#PCDATA' S? ')'
                   3817:  *
1.99      daniel   3818:  * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
                   3819:  *
                   3820:  * [ VC: No Duplicate Types ]
1.117     daniel   3821:  * The same name must not appear more than once in a single
                   3822:  * mixed-content declaration. 
1.99      daniel   3823:  *
1.61      daniel   3824:  * returns: the list of the xmlElementContentPtr describing the element choices
                   3825:  */
                   3826: xmlElementContentPtr
1.62      daniel   3827: xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt) {
1.64      daniel   3828:     xmlElementContentPtr ret = NULL, cur = NULL, n;
1.123     daniel   3829:     xmlChar *elem = NULL;
1.61      daniel   3830: 
1.97      daniel   3831:     GROW;
1.61      daniel   3832:     if ((CUR == '#') && (NXT(1) == 'P') &&
                   3833:         (NXT(2) == 'C') && (NXT(3) == 'D') &&
                   3834:         (NXT(4) == 'A') && (NXT(5) == 'T') &&
                   3835:         (NXT(6) == 'A')) {
                   3836:        SKIP(7);
                   3837:        SKIP_BLANKS;
1.91      daniel   3838:        SHRINK;
1.63      daniel   3839:        if (CUR == ')') {
                   3840:            NEXT;
                   3841:            ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
                   3842:            return(ret);
                   3843:        }
1.61      daniel   3844:        if ((CUR == '(') || (CUR == '|')) {
                   3845:            ret = cur = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
                   3846:            if (ret == NULL) return(NULL);
1.99      daniel   3847:        }
1.61      daniel   3848:        while (CUR == '|') {
1.64      daniel   3849:            NEXT;
1.61      daniel   3850:            if (elem == NULL) {
                   3851:                ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
                   3852:                if (ret == NULL) return(NULL);
                   3853:                ret->c1 = cur;
1.64      daniel   3854:                cur = ret;
1.61      daniel   3855:            } else {
1.64      daniel   3856:                n = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
                   3857:                if (n == NULL) return(NULL);
                   3858:                n->c1 = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
                   3859:                cur->c2 = n;
                   3860:                cur = n;
1.119     daniel   3861:                xmlFree(elem);
1.61      daniel   3862:            }
                   3863:            SKIP_BLANKS;
                   3864:            elem = xmlParseName(ctxt);
                   3865:            if (elem == NULL) {
                   3866:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3867:                    ctxt->sax->error(ctxt->userData, 
1.61      daniel   3868:                        "xmlParseElementMixedContentDecl : Name expected\n");
1.123     daniel   3869:                ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.61      daniel   3870:                ctxt->wellFormed = 0;
                   3871:                xmlFreeElementContent(cur);
                   3872:                return(NULL);
                   3873:            }
                   3874:            SKIP_BLANKS;
1.97      daniel   3875:            GROW;
1.61      daniel   3876:        }
1.63      daniel   3877:        if ((CUR == ')') && (NXT(1) == '*')) {
1.66      daniel   3878:            if (elem != NULL) {
1.61      daniel   3879:                cur->c2 = xmlNewElementContent(elem,
                   3880:                                               XML_ELEMENT_CONTENT_ELEMENT);
1.119     daniel   3881:                xmlFree(elem);
1.66      daniel   3882:             }
1.65      daniel   3883:            ret->ocur = XML_ELEMENT_CONTENT_MULT;
1.64      daniel   3884:            SKIP(2);
1.61      daniel   3885:        } else {
1.119     daniel   3886:            if (elem != NULL) xmlFree(elem);
1.61      daniel   3887:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3888:                ctxt->sax->error(ctxt->userData, 
1.63      daniel   3889:                    "xmlParseElementMixedContentDecl : '|' or ')*' expected\n");
1.123     daniel   3890:            ctxt->errNo = XML_ERR_MIXED_NOT_STARTED;
1.61      daniel   3891:            ctxt->wellFormed = 0;
                   3892:            xmlFreeElementContent(ret);
                   3893:            return(NULL);
                   3894:        }
                   3895: 
                   3896:     } else {
                   3897:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3898:            ctxt->sax->error(ctxt->userData, 
1.61      daniel   3899:                "xmlParseElementMixedContentDecl : '#PCDATA' expected\n");
1.123     daniel   3900:        ctxt->errNo = XML_ERR_PCDATA_REQUIRED;
1.61      daniel   3901:        ctxt->wellFormed = 0;
                   3902:     }
                   3903:     return(ret);
                   3904: }
                   3905: 
                   3906: /**
                   3907:  * xmlParseElementChildrenContentDecl:
1.50      daniel   3908:  * @ctxt:  an XML parser context
                   3909:  *
1.61      daniel   3910:  * parse the declaration for a Mixed Element content
                   3911:  * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
1.22      daniel   3912:  * 
1.61      daniel   3913:  *
1.22      daniel   3914:  * [47] children ::= (choice | seq) ('?' | '*' | '+')?
                   3915:  *
                   3916:  * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
                   3917:  *
                   3918:  * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
                   3919:  *
                   3920:  * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
                   3921:  *
1.99      daniel   3922:  * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
                   3923:  * TODO Parameter-entity replacement text must be properly nested
                   3924:  *     with parenthetized groups. That is to say, if either of the
                   3925:  *     opening or closing parentheses in a choice, seq, or Mixed
                   3926:  *     construct is contained in the replacement text for a parameter
                   3927:  *     entity, both must be contained in the same replacement text. For
                   3928:  *     interoperability, if a parameter-entity reference appears in a
                   3929:  *     choice, seq, or Mixed construct, its replacement text should not
                   3930:  *     be empty, and neither the first nor last non-blank character of
                   3931:  *     the replacement text should be a connector (| or ,).
                   3932:  *
1.62      daniel   3933:  * returns: the tree of xmlElementContentPtr describing the element 
1.61      daniel   3934:  *          hierarchy.
                   3935:  */
                   3936: xmlElementContentPtr
1.62      daniel   3937: xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt) {
1.63      daniel   3938:     xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
1.123     daniel   3939:     xmlChar *elem;
                   3940:     xmlChar type = 0;
1.62      daniel   3941: 
                   3942:     SKIP_BLANKS;
1.94      daniel   3943:     GROW;
1.62      daniel   3944:     if (CUR == '(') {
1.63      daniel   3945:         /* Recurse on first child */
1.62      daniel   3946:        NEXT;
                   3947:        SKIP_BLANKS;
                   3948:         cur = ret = xmlParseElementChildrenContentDecl(ctxt);
                   3949:        SKIP_BLANKS;
1.101     daniel   3950:        GROW;
1.62      daniel   3951:     } else {
                   3952:        elem = xmlParseName(ctxt);
                   3953:        if (elem == NULL) {
                   3954:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3955:                ctxt->sax->error(ctxt->userData, 
1.62      daniel   3956:                "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
1.123     daniel   3957:            ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
1.62      daniel   3958:            ctxt->wellFormed = 0;
                   3959:            return(NULL);
                   3960:        }
                   3961:         cur = ret = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
1.101     daniel   3962:        GROW;
1.62      daniel   3963:        if (CUR == '?') {
1.104     daniel   3964:            cur->ocur = XML_ELEMENT_CONTENT_OPT;
1.62      daniel   3965:            NEXT;
                   3966:        } else if (CUR == '*') {
1.104     daniel   3967:            cur->ocur = XML_ELEMENT_CONTENT_MULT;
1.62      daniel   3968:            NEXT;
                   3969:        } else if (CUR == '+') {
1.104     daniel   3970:            cur->ocur = XML_ELEMENT_CONTENT_PLUS;
1.62      daniel   3971:            NEXT;
                   3972:        } else {
1.104     daniel   3973:            cur->ocur = XML_ELEMENT_CONTENT_ONCE;
1.62      daniel   3974:        }
1.119     daniel   3975:        xmlFree(elem);
1.101     daniel   3976:        GROW;
1.62      daniel   3977:     }
                   3978:     SKIP_BLANKS;
1.91      daniel   3979:     SHRINK;
1.62      daniel   3980:     while (CUR != ')') {
1.63      daniel   3981:         /*
                   3982:         * Each loop we parse one separator and one element.
                   3983:         */
1.62      daniel   3984:         if (CUR == ',') {
                   3985:            if (type == 0) type = CUR;
                   3986: 
                   3987:            /*
                   3988:             * Detect "Name | Name , Name" error
                   3989:             */
                   3990:            else if (type != CUR) {
                   3991:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3992:                    ctxt->sax->error(ctxt->userData, 
1.62      daniel   3993:                    "xmlParseElementChildrenContentDecl : '%c' expected\n",
                   3994:                    type);
1.123     daniel   3995:                ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
1.62      daniel   3996:                ctxt->wellFormed = 0;
                   3997:                xmlFreeElementContent(ret);
                   3998:                return(NULL);
                   3999:            }
1.64      daniel   4000:            NEXT;
1.62      daniel   4001: 
1.63      daniel   4002:            op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_SEQ);
                   4003:            if (op == NULL) {
                   4004:                xmlFreeElementContent(ret);
                   4005:                return(NULL);
                   4006:            }
                   4007:            if (last == NULL) {
                   4008:                op->c1 = ret;
1.65      daniel   4009:                ret = cur = op;
1.63      daniel   4010:            } else {
                   4011:                cur->c2 = op;
                   4012:                op->c1 = last;
                   4013:                cur =op;
1.65      daniel   4014:                last = NULL;
1.63      daniel   4015:            }
1.62      daniel   4016:        } else if (CUR == '|') {
                   4017:            if (type == 0) type = CUR;
                   4018: 
                   4019:            /*
1.63      daniel   4020:             * Detect "Name , Name | Name" error
1.62      daniel   4021:             */
                   4022:            else if (type != CUR) {
                   4023:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4024:                    ctxt->sax->error(ctxt->userData, 
1.62      daniel   4025:                    "xmlParseElementChildrenContentDecl : '%c' expected\n",
                   4026:                    type);
1.123     daniel   4027:                ctxt->errNo = XML_ERR_SEPARATOR_REQUIRED;
1.62      daniel   4028:                ctxt->wellFormed = 0;
                   4029:                xmlFreeElementContent(ret);
                   4030:                return(NULL);
                   4031:            }
1.64      daniel   4032:            NEXT;
1.62      daniel   4033: 
1.63      daniel   4034:            op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
                   4035:            if (op == NULL) {
                   4036:                xmlFreeElementContent(ret);
                   4037:                return(NULL);
                   4038:            }
                   4039:            if (last == NULL) {
                   4040:                op->c1 = ret;
1.65      daniel   4041:                ret = cur = op;
1.63      daniel   4042:            } else {
                   4043:                cur->c2 = op;
                   4044:                op->c1 = last;
                   4045:                cur =op;
1.65      daniel   4046:                last = NULL;
1.63      daniel   4047:            }
1.62      daniel   4048:        } else {
                   4049:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4050:                ctxt->sax->error(ctxt->userData, 
1.62      daniel   4051:            "xmlParseElementChildrenContentDecl : ',' '|' or ')' expected\n");
                   4052:            ctxt->wellFormed = 0;
1.123     daniel   4053:            ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_FINISHED;
1.62      daniel   4054:            xmlFreeElementContent(ret);
                   4055:            return(NULL);
                   4056:        }
1.101     daniel   4057:        GROW;
1.62      daniel   4058:        SKIP_BLANKS;
1.101     daniel   4059:        GROW;
1.62      daniel   4060:        if (CUR == '(') {
1.63      daniel   4061:            /* Recurse on second child */
1.62      daniel   4062:            NEXT;
                   4063:            SKIP_BLANKS;
1.65      daniel   4064:            last = xmlParseElementChildrenContentDecl(ctxt);
1.62      daniel   4065:            SKIP_BLANKS;
                   4066:        } else {
                   4067:            elem = xmlParseName(ctxt);
                   4068:            if (elem == NULL) {
                   4069:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4070:                    ctxt->sax->error(ctxt->userData, 
1.122     daniel   4071:                "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
1.123     daniel   4072:                ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
1.62      daniel   4073:                ctxt->wellFormed = 0;
                   4074:                return(NULL);
                   4075:            }
1.65      daniel   4076:            last = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
1.119     daniel   4077:            xmlFree(elem);
1.105     daniel   4078:            if (CUR == '?') {
                   4079:                last->ocur = XML_ELEMENT_CONTENT_OPT;
                   4080:                NEXT;
                   4081:            } else if (CUR == '*') {
                   4082:                last->ocur = XML_ELEMENT_CONTENT_MULT;
                   4083:                NEXT;
                   4084:            } else if (CUR == '+') {
                   4085:                last->ocur = XML_ELEMENT_CONTENT_PLUS;
                   4086:                NEXT;
                   4087:            } else {
                   4088:                last->ocur = XML_ELEMENT_CONTENT_ONCE;
                   4089:            }
1.63      daniel   4090:        }
                   4091:        SKIP_BLANKS;
1.97      daniel   4092:        GROW;
1.64      daniel   4093:     }
1.65      daniel   4094:     if ((cur != NULL) && (last != NULL)) {
                   4095:         cur->c2 = last;
1.62      daniel   4096:     }
                   4097:     NEXT;
                   4098:     if (CUR == '?') {
                   4099:         ret->ocur = XML_ELEMENT_CONTENT_OPT;
                   4100:        NEXT;
                   4101:     } else if (CUR == '*') {
                   4102:         ret->ocur = XML_ELEMENT_CONTENT_MULT;
                   4103:        NEXT;
                   4104:     } else if (CUR == '+') {
                   4105:         ret->ocur = XML_ELEMENT_CONTENT_PLUS;
                   4106:        NEXT;
                   4107:     }
                   4108:     return(ret);
1.61      daniel   4109: }
                   4110: 
                   4111: /**
                   4112:  * xmlParseElementContentDecl:
                   4113:  * @ctxt:  an XML parser context
                   4114:  * @name:  the name of the element being defined.
                   4115:  * @result:  the Element Content pointer will be stored here if any
1.22      daniel   4116:  *
1.61      daniel   4117:  * parse the declaration for an Element content either Mixed or Children,
                   4118:  * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
                   4119:  * 
                   4120:  * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
1.50      daniel   4121:  *
1.61      daniel   4122:  * returns: the type of element content XML_ELEMENT_TYPE_xxx
1.22      daniel   4123:  */
                   4124: 
1.61      daniel   4125: int
1.123     daniel   4126: xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, xmlChar *name,
1.61      daniel   4127:                            xmlElementContentPtr *result) {
                   4128: 
                   4129:     xmlElementContentPtr tree = NULL;
                   4130:     int res;
                   4131: 
                   4132:     *result = NULL;
                   4133: 
                   4134:     if (CUR != '(') {
                   4135:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4136:            ctxt->sax->error(ctxt->userData, 
1.61      daniel   4137:                "xmlParseElementContentDecl : '(' expected\n");
1.123     daniel   4138:        ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
1.61      daniel   4139:        ctxt->wellFormed = 0;
                   4140:        return(-1);
                   4141:     }
                   4142:     NEXT;
1.97      daniel   4143:     GROW;
1.61      daniel   4144:     SKIP_BLANKS;
                   4145:     if ((CUR == '#') && (NXT(1) == 'P') &&
                   4146:         (NXT(2) == 'C') && (NXT(3) == 'D') &&
                   4147:         (NXT(4) == 'A') && (NXT(5) == 'T') &&
                   4148:         (NXT(6) == 'A')) {
1.62      daniel   4149:         tree = xmlParseElementMixedContentDecl(ctxt);
1.61      daniel   4150:        res = XML_ELEMENT_TYPE_MIXED;
                   4151:     } else {
1.62      daniel   4152:         tree = xmlParseElementChildrenContentDecl(ctxt);
1.61      daniel   4153:        res = XML_ELEMENT_TYPE_ELEMENT;
                   4154:     }
                   4155:     SKIP_BLANKS;
1.63      daniel   4156:     /****************************
1.61      daniel   4157:     if (CUR != ')') {
                   4158:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4159:            ctxt->sax->error(ctxt->userData, 
1.61      daniel   4160:                "xmlParseElementContentDecl : ')' expected\n");
                   4161:        ctxt->wellFormed = 0;
                   4162:        return(-1);
                   4163:     }
1.63      daniel   4164:      ****************************/
                   4165:     *result = tree;
1.61      daniel   4166:     return(res);
1.22      daniel   4167: }
                   4168: 
1.50      daniel   4169: /**
                   4170:  * xmlParseElementDecl:
                   4171:  * @ctxt:  an XML parser context
                   4172:  *
                   4173:  * parse an Element declaration.
1.22      daniel   4174:  *
                   4175:  * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
                   4176:  *
1.99      daniel   4177:  * [ VC: Unique Element Type Declaration ]
1.117     daniel   4178:  * No element type may be declared more than once
1.69      daniel   4179:  *
                   4180:  * Returns the type of the element, or -1 in case of error
1.22      daniel   4181:  */
1.59      daniel   4182: int
1.55      daniel   4183: xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
1.123     daniel   4184:     xmlChar *name;
1.59      daniel   4185:     int ret = -1;
1.61      daniel   4186:     xmlElementContentPtr content  = NULL;
1.22      daniel   4187: 
1.97      daniel   4188:     GROW;
1.40      daniel   4189:     if ((CUR == '<') && (NXT(1) == '!') &&
                   4190:         (NXT(2) == 'E') && (NXT(3) == 'L') &&
                   4191:         (NXT(4) == 'E') && (NXT(5) == 'M') &&
                   4192:         (NXT(6) == 'E') && (NXT(7) == 'N') &&
1.59      daniel   4193:         (NXT(8) == 'T')) {
1.40      daniel   4194:        SKIP(9);
1.59      daniel   4195:        if (!IS_BLANK(CUR)) {
                   4196:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4197:                ctxt->sax->error(ctxt->userData, 
1.59      daniel   4198:                    "Space required after 'ELEMENT'\n");
1.123     daniel   4199:            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   4200:            ctxt->wellFormed = 0;
                   4201:        }
1.42      daniel   4202:         SKIP_BLANKS;
1.22      daniel   4203:         name = xmlParseName(ctxt);
                   4204:        if (name == NULL) {
1.55      daniel   4205:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4206:                ctxt->sax->error(ctxt->userData,
1.59      daniel   4207:                   "xmlParseElementDecl: no name for Element\n");
1.123     daniel   4208:            ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59      daniel   4209:            ctxt->wellFormed = 0;
                   4210:            return(-1);
                   4211:        }
                   4212:        if (!IS_BLANK(CUR)) {
                   4213:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4214:                ctxt->sax->error(ctxt->userData, 
1.59      daniel   4215:                    "Space required after the element name\n");
1.123     daniel   4216:            ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   4217:            ctxt->wellFormed = 0;
1.22      daniel   4218:        }
1.42      daniel   4219:         SKIP_BLANKS;
1.40      daniel   4220:        if ((CUR == 'E') && (NXT(1) == 'M') &&
                   4221:            (NXT(2) == 'P') && (NXT(3) == 'T') &&
                   4222:            (NXT(4) == 'Y')) {
                   4223:            SKIP(5);
1.22      daniel   4224:            /*
                   4225:             * Element must always be empty.
                   4226:             */
1.59      daniel   4227:            ret = XML_ELEMENT_TYPE_EMPTY;
1.40      daniel   4228:        } else if ((CUR == 'A') && (NXT(1) == 'N') &&
                   4229:                   (NXT(2) == 'Y')) {
                   4230:            SKIP(3);
1.22      daniel   4231:            /*
                   4232:             * Element is a generic container.
                   4233:             */
1.59      daniel   4234:            ret = XML_ELEMENT_TYPE_ANY;
1.61      daniel   4235:        } else if (CUR == '(') {
                   4236:            ret = xmlParseElementContentDecl(ctxt, name, &content);
1.22      daniel   4237:        } else {
1.98      daniel   4238:            /*
                   4239:             * [ WFC: PEs in Internal Subset ] error handling.
                   4240:             */
                   4241:            if ((CUR == '%') && (ctxt->external == 0) &&
                   4242:                (ctxt->inputNr == 1)) {
                   4243:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   4244:                    ctxt->sax->error(ctxt->userData, 
                   4245:          "PEReference: forbidden within markup decl in internal subset\n");
1.123     daniel   4246:                ctxt->errNo = XML_ERR_PEREF_IN_INT_SUBSET;
1.98      daniel   4247:            } else {
                   4248:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   4249:                    ctxt->sax->error(ctxt->userData, 
                   4250:                      "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
1.123     daniel   4251:                ctxt->errNo = XML_ERR_ELEMCONTENT_NOT_STARTED;
1.98      daniel   4252:             }
1.61      daniel   4253:            ctxt->wellFormed = 0;
1.119     daniel   4254:            if (name != NULL) xmlFree(name);
1.61      daniel   4255:            return(-1);
1.22      daniel   4256:        }
1.42      daniel   4257:        SKIP_BLANKS;
1.40      daniel   4258:        if (CUR != '>') {
1.55      daniel   4259:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4260:                ctxt->sax->error(ctxt->userData, 
1.31      daniel   4261:                  "xmlParseElementDecl: expected '>' at the end\n");
1.123     daniel   4262:            ctxt->errNo = XML_ERR_GT_REQUIRED;
1.59      daniel   4263:            ctxt->wellFormed = 0;
1.61      daniel   4264:        } else {
1.40      daniel   4265:            NEXT;
1.72      daniel   4266:            if ((ctxt->sax != NULL) && (ctxt->sax->elementDecl != NULL))
1.76      daniel   4267:                ctxt->sax->elementDecl(ctxt->userData, name, ret,
                   4268:                                       content);
1.61      daniel   4269:        }
1.84      daniel   4270:        if (content != NULL) {
                   4271:            xmlFreeElementContent(content);
                   4272:        }
1.61      daniel   4273:        if (name != NULL) {
1.119     daniel   4274:            xmlFree(name);
1.61      daniel   4275:        }
1.22      daniel   4276:     }
1.59      daniel   4277:     return(ret);
1.22      daniel   4278: }
                   4279: 
1.50      daniel   4280: /**
                   4281:  * xmlParseMarkupDecl:
                   4282:  * @ctxt:  an XML parser context
                   4283:  * 
                   4284:  * parse Markup declarations
1.22      daniel   4285:  *
                   4286:  * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
                   4287:  *                     NotationDecl | PI | Comment
                   4288:  *
1.98      daniel   4289:  * [ VC: Proper Declaration/PE Nesting ]
                   4290:  * TODO Parameter-entity replacement text must be properly nested with
                   4291:  * markup declarations. That is to say, if either the first character
                   4292:  * or the last character of a markup declaration (markupdecl above) is
                   4293:  * contained in the replacement text for a parameter-entity reference,
                   4294:  * both must be contained in the same replacement text.
                   4295:  *
                   4296:  * [ WFC: PEs in Internal Subset ]
                   4297:  * In the internal DTD subset, parameter-entity references can occur
                   4298:  * only where markup declarations can occur, not within markup declarations.
                   4299:  * (This does not apply to references that occur in external parameter
                   4300:  * entities or to the external subset.) 
1.22      daniel   4301:  */
1.55      daniel   4302: void
                   4303: xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
1.94      daniel   4304:     GROW;
1.22      daniel   4305:     xmlParseElementDecl(ctxt);
                   4306:     xmlParseAttributeListDecl(ctxt);
                   4307:     xmlParseEntityDecl(ctxt);
                   4308:     xmlParseNotationDecl(ctxt);
                   4309:     xmlParsePI(ctxt);
1.114     daniel   4310:     xmlParseComment(ctxt);
1.98      daniel   4311:     /*
                   4312:      * This is only for internal subset. On external entities,
                   4313:      * the replacement is done before parsing stage
                   4314:      */
                   4315:     if ((ctxt->external == 0) && (ctxt->inputNr == 1))
                   4316:        xmlParsePEReference(ctxt);
1.97      daniel   4317:     ctxt->instate = XML_PARSER_DTD;
1.22      daniel   4318: }
                   4319: 
1.50      daniel   4320: /**
1.76      daniel   4321:  * xmlParseTextDecl:
                   4322:  * @ctxt:  an XML parser context
                   4323:  * 
                   4324:  * parse an XML declaration header for external entities
                   4325:  *
                   4326:  * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
                   4327:  *
                   4328:  * Returns the only valuable info for an external parsed entity, the encoding
                   4329:  */
                   4330: 
1.123     daniel   4331: xmlChar *
1.76      daniel   4332: xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
1.123     daniel   4333:     xmlChar *version;
                   4334:     xmlChar *encoding = NULL;
1.76      daniel   4335: 
                   4336:     /*
                   4337:      * We know that '<?xml' is here.
                   4338:      */
                   4339:     SKIP(5);
                   4340: 
                   4341:     if (!IS_BLANK(CUR)) {
                   4342:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   4343:            ctxt->sax->error(ctxt->userData,
                   4344:                             "Space needed after '<?xml'\n");
1.123     daniel   4345:        ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.76      daniel   4346:        ctxt->wellFormed = 0;
                   4347:     }
                   4348:     SKIP_BLANKS;
                   4349: 
                   4350:     /*
                   4351:      * We may have the VersionInfo here.
                   4352:      */
                   4353:     version = xmlParseVersionInfo(ctxt);
                   4354:     if (version == NULL)
                   4355:        version = xmlCharStrdup(XML_DEFAULT_VERSION);
                   4356:     ctxt->version = xmlStrdup(version);
1.119     daniel   4357:     xmlFree(version);
1.76      daniel   4358: 
                   4359:     /*
                   4360:      * We must have the encoding declaration
                   4361:      */
                   4362:     if (!IS_BLANK(CUR)) {
                   4363:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   4364:            ctxt->sax->error(ctxt->userData, "Space needed here\n");
1.123     daniel   4365:        ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.76      daniel   4366:        ctxt->wellFormed = 0;
                   4367:     }
                   4368:     encoding = xmlParseEncodingDecl(ctxt);
                   4369: 
                   4370:     SKIP_BLANKS;
                   4371:     if ((CUR == '?') && (NXT(1) == '>')) {
                   4372:         SKIP(2);
                   4373:     } else if (CUR == '>') {
                   4374:         /* Deprecated old WD ... */
                   4375:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   4376:            ctxt->sax->error(ctxt->userData,
                   4377:                             "XML declaration must end-up with '?>'\n");
1.123     daniel   4378:        ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
1.76      daniel   4379:        ctxt->wellFormed = 0;
                   4380:        NEXT;
                   4381:     } else {
                   4382:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   4383:            ctxt->sax->error(ctxt->userData,
                   4384:                             "parsing XML declaration: '?>' expected\n");
1.123     daniel   4385:        ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
1.76      daniel   4386:        ctxt->wellFormed = 0;
                   4387:        MOVETO_ENDTAG(CUR_PTR);
                   4388:        NEXT;
                   4389:     }
                   4390:     return(encoding);
                   4391: }
                   4392: 
                   4393: /*
                   4394:  * xmlParseConditionalSections
                   4395:  * @ctxt:  an XML parser context
                   4396:  *
                   4397:  * TODO : Conditionnal section are not yet supported !
                   4398:  *
                   4399:  * [61] conditionalSect ::= includeSect | ignoreSect 
                   4400:  * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>' 
                   4401:  * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
                   4402:  * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
                   4403:  * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
                   4404:  */
                   4405: 
                   4406: void
                   4407: xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
                   4408:     if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
                   4409:        ctxt->sax->warning(ctxt->userData,
                   4410:                            "XML conditional section not supported\n");
                   4411:     /*
                   4412:      * Skip up to the end of the conditionnal section.
                   4413:      */
                   4414:     while ((CUR != 0) && ((CUR != ']') || (NXT(1) != ']') || (NXT(2) != '>')))
                   4415:        NEXT;
                   4416:     if (CUR == 0) {
                   4417:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   4418:            ctxt->sax->error(ctxt->userData,
                   4419:                "XML conditional section not closed\n");
1.123     daniel   4420:        ctxt->errNo = XML_ERR_CONDSEC_NOT_FINISHED;
1.76      daniel   4421:        ctxt->wellFormed = 0;
                   4422:     }
                   4423: }
                   4424: 
                   4425: /**
1.124     daniel   4426:  * xmlParseExternalSubset:
1.76      daniel   4427:  * @ctxt:  an XML parser context
1.124     daniel   4428:  * @ExternalID: the external identifier
                   4429:  * @SystemID: the system identifier (or URL)
1.76      daniel   4430:  * 
                   4431:  * parse Markup declarations from an external subset
                   4432:  *
                   4433:  * [30] extSubset ::= textDecl? extSubsetDecl
                   4434:  *
                   4435:  * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
                   4436:  */
                   4437: void
1.123     daniel   4438: xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
                   4439:                        const xmlChar *SystemID) {
1.132     daniel   4440:     GROW;
1.76      daniel   4441:     if ((CUR == '<') && (NXT(1) == '?') &&
                   4442:         (NXT(2) == 'x') && (NXT(3) == 'm') &&
                   4443:        (NXT(4) == 'l')) {
                   4444:        xmlParseTextDecl(ctxt);
                   4445:     }
1.79      daniel   4446:     if (ctxt->myDoc == NULL) {
1.116     daniel   4447:         ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
1.79      daniel   4448:     }
                   4449:     if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
                   4450:         xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
                   4451: 
1.96      daniel   4452:     ctxt->instate = XML_PARSER_DTD;
1.101     daniel   4453:     ctxt->external = 1;
1.76      daniel   4454:     while (((CUR == '<') && (NXT(1) == '?')) ||
                   4455:            ((CUR == '<') && (NXT(1) == '!')) ||
                   4456:            IS_BLANK(CUR)) {
1.123     daniel   4457:        const xmlChar *check = CUR_PTR;
1.115     daniel   4458:        int cons = ctxt->input->consumed;
                   4459: 
1.76      daniel   4460:         if ((CUR == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
                   4461:            xmlParseConditionalSections(ctxt);
                   4462:        } else if (IS_BLANK(CUR)) {
                   4463:            NEXT;
                   4464:        } else if (CUR == '%') {
                   4465:             xmlParsePEReference(ctxt);
                   4466:        } else
                   4467:            xmlParseMarkupDecl(ctxt);
1.77      daniel   4468: 
                   4469:        /*
                   4470:         * Pop-up of finished entities.
                   4471:         */
                   4472:        while ((CUR == 0) && (ctxt->inputNr > 1))
                   4473:            xmlPopInput(ctxt);
                   4474: 
1.115     daniel   4475:        if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
                   4476:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   4477:                ctxt->sax->error(ctxt->userData,
                   4478:                    "Content error in the external subset\n");
                   4479:            ctxt->wellFormed = 0;
1.123     daniel   4480:            ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
1.115     daniel   4481:            break;
                   4482:        }
1.76      daniel   4483:     }
                   4484:     
                   4485:     if (CUR != 0) {
                   4486:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   4487:            ctxt->sax->error(ctxt->userData,
                   4488:                "Extra content at the end of the document\n");
1.123     daniel   4489:        ctxt->errNo = XML_ERR_EXT_SUBSET_NOT_FINISHED;
1.76      daniel   4490:        ctxt->wellFormed = 0;
                   4491:     }
                   4492: 
                   4493: }
                   4494: 
                   4495: /**
1.77      daniel   4496:  * xmlParseReference:
                   4497:  * @ctxt:  an XML parser context
                   4498:  * 
                   4499:  * parse and handle entity references in content, depending on the SAX
                   4500:  * interface, this may end-up in a call to character() if this is a
1.79      daniel   4501:  * CharRef, a predefined entity, if there is no reference() callback.
                   4502:  * or if the parser was asked to switch to that mode.
1.77      daniel   4503:  *
                   4504:  * [67] Reference ::= EntityRef | CharRef
                   4505:  */
                   4506: void
                   4507: xmlParseReference(xmlParserCtxtPtr ctxt) {
                   4508:     xmlEntityPtr ent;
1.123     daniel   4509:     xmlChar *val;
1.77      daniel   4510:     if (CUR != '&') return;
                   4511: 
1.113     daniel   4512:     if (ctxt->inputNr > 1) {
1.123     daniel   4513:         xmlChar cur[2] = { '&' , 0 } ;
1.113     daniel   4514: 
                   4515:        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
                   4516:            ctxt->sax->characters(ctxt->userData, cur, 1);
                   4517:        if (ctxt->token == '&')
                   4518:            ctxt->token = 0;
                   4519:         else {
                   4520:            SKIP(1);
                   4521:        }
                   4522:        return;
                   4523:     }
1.77      daniel   4524:     if (NXT(1) == '#') {
1.123     daniel   4525:        xmlChar out[2];
1.77      daniel   4526:        int val = xmlParseCharRef(ctxt);
1.117     daniel   4527:        /* invalid for UTF-8 variable encoding !!!!! */
1.77      daniel   4528:        out[0] = val;
                   4529:        out[1] = 0;
                   4530:        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
                   4531:            ctxt->sax->characters(ctxt->userData, out, 1);
                   4532:     } else {
                   4533:        ent = xmlParseEntityRef(ctxt);
                   4534:        if (ent == NULL) return;
                   4535:        if ((ent->name != NULL) && 
1.113     daniel   4536:            (ent->type != XML_INTERNAL_PREDEFINED_ENTITY)) {
                   4537:            if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
                   4538:                (ctxt->replaceEntities == 0)) {
                   4539:                /*
                   4540:                 * Create a node.
                   4541:                 */
                   4542:                ctxt->sax->reference(ctxt->userData, ent->name);
                   4543:                return;
                   4544:            } else if (ctxt->replaceEntities) {
                   4545:                xmlParserInputPtr input;
1.79      daniel   4546: 
1.113     daniel   4547:                input = xmlNewEntityInputStream(ctxt, ent);
                   4548:                xmlPushInput(ctxt, input);
                   4549:                return;
                   4550:            }
1.77      daniel   4551:        }
                   4552:        val = ent->content;
                   4553:        if (val == NULL) return;
                   4554:        /*
                   4555:         * inline the entity.
                   4556:         */
                   4557:        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
                   4558:            ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
                   4559:     }
1.24      daniel   4560: }
                   4561: 
1.50      daniel   4562: /**
                   4563:  * xmlParseEntityRef:
                   4564:  * @ctxt:  an XML parser context
                   4565:  *
                   4566:  * parse ENTITY references declarations
1.24      daniel   4567:  *
                   4568:  * [68] EntityRef ::= '&' Name ';'
1.68      daniel   4569:  *
1.98      daniel   4570:  * [ WFC: Entity Declared ]
                   4571:  * In a document without any DTD, a document with only an internal DTD
                   4572:  * subset which contains no parameter entity references, or a document
                   4573:  * with "standalone='yes'", the Name given in the entity reference
                   4574:  * must match that in an entity declaration, except that well-formed
                   4575:  * documents need not declare any of the following entities: amp, lt,
                   4576:  * gt, apos, quot.  The declaration of a parameter entity must precede
                   4577:  * any reference to it.  Similarly, the declaration of a general entity
                   4578:  * must precede any reference to it which appears in a default value in an
                   4579:  * attribute-list declaration. Note that if entities are declared in the
                   4580:  * external subset or in external parameter entities, a non-validating
                   4581:  * processor is not obligated to read and process their declarations;
                   4582:  * for such documents, the rule that an entity must be declared is a
                   4583:  * well-formedness constraint only if standalone='yes'.
                   4584:  *
                   4585:  * [ WFC: Parsed Entity ]
                   4586:  * An entity reference must not contain the name of an unparsed entity
                   4587:  *
1.77      daniel   4588:  * Returns the xmlEntityPtr if found, or NULL otherwise.
1.24      daniel   4589:  */
1.77      daniel   4590: xmlEntityPtr
1.55      daniel   4591: xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
1.123     daniel   4592:     xmlChar *name;
1.72      daniel   4593:     xmlEntityPtr ent = NULL;
1.24      daniel   4594: 
1.91      daniel   4595:     GROW;
1.111     daniel   4596:     
1.40      daniel   4597:     if (CUR == '&') {
                   4598:         NEXT;
1.24      daniel   4599:         name = xmlParseName(ctxt);
                   4600:        if (name == NULL) {
1.55      daniel   4601:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.98      daniel   4602:                ctxt->sax->error(ctxt->userData,
                   4603:                                 "xmlParseEntityRef: no name\n");
1.123     daniel   4604:            ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59      daniel   4605:            ctxt->wellFormed = 0;
1.24      daniel   4606:        } else {
1.40      daniel   4607:            if (CUR == ';') {
                   4608:                NEXT;
1.24      daniel   4609:                /*
1.77      daniel   4610:                 * Ask first SAX for entity resolution, otherwise try the
                   4611:                 * predefined set.
                   4612:                 */
                   4613:                if (ctxt->sax != NULL) {
                   4614:                    if (ctxt->sax->getEntity != NULL)
                   4615:                        ent = ctxt->sax->getEntity(ctxt->userData, name);
                   4616:                    if (ent == NULL)
                   4617:                        ent = xmlGetPredefinedEntity(name);
                   4618:                }
                   4619:                /*
1.98      daniel   4620:                 * [ WFC: Entity Declared ]
                   4621:                 * In a document without any DTD, a document with only an
                   4622:                 * internal DTD subset which contains no parameter entity
                   4623:                 * references, or a document with "standalone='yes'", the
                   4624:                 * Name given in the entity reference must match that in an
                   4625:                 * entity declaration, except that well-formed documents
                   4626:                 * need not declare any of the following entities: amp, lt,
                   4627:                 * gt, apos, quot.
                   4628:                 * The declaration of a parameter entity must precede any
                   4629:                 * reference to it.
                   4630:                 * Similarly, the declaration of a general entity must
                   4631:                 * precede any reference to it which appears in a default
                   4632:                 * value in an attribute-list declaration. Note that if
                   4633:                 * entities are declared in the external subset or in
                   4634:                 * external parameter entities, a non-validating processor
                   4635:                 * is not obligated to read and process their declarations;
                   4636:                 * for such documents, the rule that an entity must be
                   4637:                 * declared is a well-formedness constraint only if
                   4638:                 * standalone='yes'. 
1.59      daniel   4639:                 */
1.77      daniel   4640:                if (ent == NULL) {
1.98      daniel   4641:                    if ((ctxt->standalone == 1) ||
                   4642:                        ((ctxt->hasExternalSubset == 0) &&
                   4643:                         (ctxt->hasPErefs == 0))) {
                   4644:                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.77      daniel   4645:                            ctxt->sax->error(ctxt->userData, 
                   4646:                                 "Entity '%s' not defined\n", name);
1.123     daniel   4647:                        ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
1.77      daniel   4648:                        ctxt->wellFormed = 0;
                   4649:                    } else {
1.98      daniel   4650:                        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
                   4651:                            ctxt->sax->warning(ctxt->userData, 
                   4652:                                 "Entity '%s' not defined\n", name);
1.123     daniel   4653:                        ctxt->errNo = XML_WAR_UNDECLARED_ENTITY;
1.59      daniel   4654:                    }
1.77      daniel   4655:                }
1.59      daniel   4656: 
                   4657:                /*
1.98      daniel   4658:                 * [ WFC: Parsed Entity ]
                   4659:                 * An entity reference must not contain the name of an
                   4660:                 * unparsed entity
                   4661:                 */
                   4662:                else if (ent->type == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
                   4663:                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   4664:                        ctxt->sax->error(ctxt->userData, 
                   4665:                             "Entity reference to unparsed entity %s\n", name);
1.123     daniel   4666:                    ctxt->errNo = XML_ERR_UNPARSED_ENTITY;
1.98      daniel   4667:                    ctxt->wellFormed = 0;
                   4668:                }
                   4669: 
                   4670:                /*
                   4671:                 * [ WFC: No External Entity References ]
                   4672:                 * Attribute values cannot contain direct or indirect
                   4673:                 * entity references to external entities.
                   4674:                 */
                   4675:                else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
                   4676:                         (ent->type == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
                   4677:                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   4678:                        ctxt->sax->error(ctxt->userData, 
                   4679:                     "Attribute references external entity '%s'\n", name);
1.123     daniel   4680:                    ctxt->errNo = XML_ERR_ENTITY_IS_EXTERNAL;
1.98      daniel   4681:                    ctxt->wellFormed = 0;
                   4682:                }
                   4683:                /*
                   4684:                 * [ WFC: No < in Attribute Values ]
                   4685:                 * The replacement text of any entity referred to directly or
                   4686:                 * indirectly in an attribute value (other than "&lt;") must
                   4687:                 * not contain a <. 
1.59      daniel   4688:                 */
1.98      daniel   4689:                else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
1.116     daniel   4690:                         (ent != NULL) &&
                   4691:                         (xmlStrcmp(ent->name, BAD_CAST "lt")) &&
1.98      daniel   4692:                         (ent->content != NULL) &&
                   4693:                         (xmlStrchr(ent->content, '<'))) {
                   4694:                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   4695:                        ctxt->sax->error(ctxt->userData, 
                   4696:         "'<' in entity '%s' is not allowed in attributes values\n", name);
1.123     daniel   4697:                    ctxt->errNo = XML_ERR_LT_IN_ATTRIBUTE;
1.98      daniel   4698:                    ctxt->wellFormed = 0;
                   4699:                }
                   4700: 
                   4701:                /*
                   4702:                 * Internal check, no parameter entities here ...
                   4703:                 */
                   4704:                else {
1.59      daniel   4705:                    switch (ent->type) {
                   4706:                        case XML_INTERNAL_PARAMETER_ENTITY:
                   4707:                        case XML_EXTERNAL_PARAMETER_ENTITY:
                   4708:                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4709:                            ctxt->sax->error(ctxt->userData, 
1.59      daniel   4710:                     "Attempt to reference the parameter entity '%s'\n", name);
1.123     daniel   4711:                        ctxt->errNo = XML_ERR_ENTITY_IS_PARAMETER;
1.59      daniel   4712:                        ctxt->wellFormed = 0;
                   4713:                        break;
                   4714:                    }
                   4715:                }
                   4716: 
                   4717:                /*
1.98      daniel   4718:                 * [ WFC: No Recursion ]
1.117     daniel   4719:                 * TODO A parsed entity must not contain a recursive reference
                   4720:                 * to itself, either directly or indirectly. 
1.59      daniel   4721:                 */
1.77      daniel   4722: 
1.24      daniel   4723:            } else {
1.55      daniel   4724:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4725:                    ctxt->sax->error(ctxt->userData,
1.59      daniel   4726:                                     "xmlParseEntityRef: expecting ';'\n");
1.123     daniel   4727:                ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
1.59      daniel   4728:                ctxt->wellFormed = 0;
1.24      daniel   4729:            }
1.119     daniel   4730:            xmlFree(name);
1.24      daniel   4731:        }
                   4732:     }
1.77      daniel   4733:     return(ent);
1.24      daniel   4734: }
                   4735: 
1.50      daniel   4736: /**
                   4737:  * xmlParsePEReference:
                   4738:  * @ctxt:  an XML parser context
                   4739:  *
                   4740:  * parse PEReference declarations
1.77      daniel   4741:  * The entity content is handled directly by pushing it's content as
                   4742:  * a new input stream.
1.22      daniel   4743:  *
                   4744:  * [69] PEReference ::= '%' Name ';'
1.68      daniel   4745:  *
1.98      daniel   4746:  * [ WFC: No Recursion ]
                   4747:  * TODO A parsed entity must not contain a recursive
                   4748:  * reference to itself, either directly or indirectly. 
                   4749:  *
                   4750:  * [ WFC: Entity Declared ]
                   4751:  * In a document without any DTD, a document with only an internal DTD
                   4752:  * subset which contains no parameter entity references, or a document
                   4753:  * with "standalone='yes'", ...  ... The declaration of a parameter
                   4754:  * entity must precede any reference to it...
                   4755:  *
                   4756:  * [ VC: Entity Declared ]
                   4757:  * In a document with an external subset or external parameter entities
                   4758:  * with "standalone='no'", ...  ... The declaration of a parameter entity
                   4759:  * must precede any reference to it...
                   4760:  *
                   4761:  * [ WFC: In DTD ]
                   4762:  * Parameter-entity references may only appear in the DTD.
                   4763:  * NOTE: misleading but this is handled.
1.22      daniel   4764:  */
1.77      daniel   4765: void
1.55      daniel   4766: xmlParsePEReference(xmlParserCtxtPtr ctxt) {
1.123     daniel   4767:     xmlChar *name;
1.72      daniel   4768:     xmlEntityPtr entity = NULL;
1.50      daniel   4769:     xmlParserInputPtr input;
1.22      daniel   4770: 
1.40      daniel   4771:     if (CUR == '%') {
                   4772:         NEXT;
1.22      daniel   4773:         name = xmlParseName(ctxt);
                   4774:        if (name == NULL) {
1.55      daniel   4775:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   4776:                ctxt->sax->error(ctxt->userData,
                   4777:                                 "xmlParsePEReference: no name\n");
1.123     daniel   4778:            ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59      daniel   4779:            ctxt->wellFormed = 0;
1.22      daniel   4780:        } else {
1.40      daniel   4781:            if (CUR == ';') {
                   4782:                NEXT;
1.98      daniel   4783:                if ((ctxt->sax != NULL) &&
                   4784:                    (ctxt->sax->getParameterEntity != NULL))
                   4785:                    entity = ctxt->sax->getParameterEntity(ctxt->userData,
                   4786:                                                           name);
1.45      daniel   4787:                if (entity == NULL) {
1.98      daniel   4788:                    /*
                   4789:                     * [ WFC: Entity Declared ]
                   4790:                     * In a document without any DTD, a document with only an
                   4791:                     * internal DTD subset which contains no parameter entity
                   4792:                     * references, or a document with "standalone='yes'", ...
                   4793:                     * ... The declaration of a parameter entity must precede
                   4794:                     * any reference to it...
                   4795:                     */
                   4796:                    if ((ctxt->standalone == 1) ||
                   4797:                        ((ctxt->hasExternalSubset == 0) &&
                   4798:                         (ctxt->hasPErefs == 0))) {
                   4799:                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   4800:                            ctxt->sax->error(ctxt->userData,
                   4801:                             "PEReference: %%%s; not found\n", name);
1.123     daniel   4802:                        ctxt->errNo = XML_ERR_UNDECLARED_ENTITY;
1.98      daniel   4803:                        ctxt->wellFormed = 0;
                   4804:                    } else {
                   4805:                        /*
                   4806:                         * [ VC: Entity Declared ]
                   4807:                         * In a document with an external subset or external
                   4808:                         * parameter entities with "standalone='no'", ...
                   4809:                         * ... The declaration of a parameter entity must precede
                   4810:                         * any reference to it...
                   4811:                         */
                   4812:                        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
                   4813:                            ctxt->sax->warning(ctxt->userData,
                   4814:                             "PEReference: %%%s; not found\n", name);
                   4815:                        ctxt->valid = 0;
                   4816:                    }
1.50      daniel   4817:                } else {
1.98      daniel   4818:                    /*
                   4819:                     * Internal checking in case the entity quest barfed
                   4820:                     */
                   4821:                    if ((entity->type != XML_INTERNAL_PARAMETER_ENTITY) &&
                   4822:                        (entity->type != XML_EXTERNAL_PARAMETER_ENTITY)) {
                   4823:                        if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
                   4824:                            ctxt->sax->warning(ctxt->userData,
                   4825:                         "Internal: %%%s; is not a parameter entity\n", name);
                   4826:                    } else {
                   4827:                        input = xmlNewEntityInputStream(ctxt, entity);
                   4828:                        xmlPushInput(ctxt, input);
                   4829:                    }
1.45      daniel   4830:                }
1.98      daniel   4831:                ctxt->hasPErefs = 1;
1.22      daniel   4832:            } else {
1.55      daniel   4833:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4834:                    ctxt->sax->error(ctxt->userData,
1.59      daniel   4835:                                     "xmlParsePEReference: expecting ';'\n");
1.123     daniel   4836:                ctxt->errNo = XML_ERR_ENTITYREF_SEMICOL_MISSING;
1.59      daniel   4837:                ctxt->wellFormed = 0;
1.22      daniel   4838:            }
1.119     daniel   4839:            xmlFree(name);
1.3       veillard 4840:        }
                   4841:     }
                   4842: }
                   4843: 
1.50      daniel   4844: /**
                   4845:  * xmlParseDocTypeDecl :
                   4846:  * @ctxt:  an XML parser context
                   4847:  *
                   4848:  * parse a DOCTYPE declaration
1.21      daniel   4849:  *
1.22      daniel   4850:  * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? 
                   4851:  *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
1.98      daniel   4852:  *
                   4853:  * [ VC: Root Element Type ]
1.99      daniel   4854:  * The Name in the document type declaration must match the element
1.98      daniel   4855:  * type of the root element. 
1.21      daniel   4856:  */
                   4857: 
1.55      daniel   4858: void
                   4859: xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
1.123     daniel   4860:     xmlChar *name;
                   4861:     xmlChar *ExternalID = NULL;
                   4862:     xmlChar *URI = NULL;
1.21      daniel   4863: 
                   4864:     /*
                   4865:      * We know that '<!DOCTYPE' has been detected.
                   4866:      */
1.40      daniel   4867:     SKIP(9);
1.21      daniel   4868: 
1.42      daniel   4869:     SKIP_BLANKS;
1.21      daniel   4870: 
                   4871:     /*
                   4872:      * Parse the DOCTYPE name.
                   4873:      */
                   4874:     name = xmlParseName(ctxt);
                   4875:     if (name == NULL) {
1.55      daniel   4876:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   4877:            ctxt->sax->error(ctxt->userData, 
                   4878:                "xmlParseDocTypeDecl : no DOCTYPE name !\n");
1.59      daniel   4879:        ctxt->wellFormed = 0;
1.123     daniel   4880:        ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.21      daniel   4881:     }
                   4882: 
1.42      daniel   4883:     SKIP_BLANKS;
1.21      daniel   4884: 
                   4885:     /*
1.22      daniel   4886:      * Check for SystemID and ExternalID
                   4887:      */
1.67      daniel   4888:     URI = xmlParseExternalID(ctxt, &ExternalID, 1);
1.98      daniel   4889: 
                   4890:     if ((URI != NULL) || (ExternalID != NULL)) {
                   4891:         ctxt->hasExternalSubset = 1;
                   4892:     }
                   4893: 
1.42      daniel   4894:     SKIP_BLANKS;
1.36      daniel   4895: 
1.76      daniel   4896:     /*
                   4897:      * NOTE: the SAX callback may try to fetch the external subset
                   4898:      *       entity and fill it up !
                   4899:      */
1.72      daniel   4900:     if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL))
1.74      daniel   4901:        ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
1.22      daniel   4902: 
                   4903:     /*
                   4904:      * Is there any DTD definition ?
                   4905:      */
1.40      daniel   4906:     if (CUR == '[') {
1.96      daniel   4907:         ctxt->instate = XML_PARSER_DTD;
1.40      daniel   4908:         NEXT;
1.22      daniel   4909:        /*
                   4910:         * Parse the succession of Markup declarations and 
                   4911:         * PEReferences.
                   4912:         * Subsequence (markupdecl | PEReference | S)*
                   4913:         */
1.40      daniel   4914:        while (CUR != ']') {
1.123     daniel   4915:            const xmlChar *check = CUR_PTR;
1.115     daniel   4916:            int cons = ctxt->input->consumed;
1.22      daniel   4917: 
1.42      daniel   4918:            SKIP_BLANKS;
1.22      daniel   4919:            xmlParseMarkupDecl(ctxt);
1.50      daniel   4920:            xmlParsePEReference(ctxt);
1.22      daniel   4921: 
1.115     daniel   4922:            /*
                   4923:             * Pop-up of finished entities.
                   4924:             */
                   4925:            while ((CUR == 0) && (ctxt->inputNr > 1))
                   4926:                xmlPopInput(ctxt);
                   4927: 
1.118     daniel   4928:            if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
1.55      daniel   4929:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4930:                    ctxt->sax->error(ctxt->userData, 
1.31      daniel   4931:                 "xmlParseDocTypeDecl: error detected in Markup declaration\n");
1.59      daniel   4932:                ctxt->wellFormed = 0;
1.123     daniel   4933:                ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.22      daniel   4934:                break;
                   4935:            }
                   4936:        }
1.40      daniel   4937:        if (CUR == ']') NEXT;
1.22      daniel   4938:     }
                   4939: 
                   4940:     /*
                   4941:      * We should be at the end of the DOCTYPE declaration.
1.21      daniel   4942:      */
1.40      daniel   4943:     if (CUR != '>') {
1.55      daniel   4944:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4945:            ctxt->sax->error(ctxt->userData, "DOCTYPE unproperly terminated\n");
1.59      daniel   4946:        ctxt->wellFormed = 0;
1.123     daniel   4947:        ctxt->errNo = XML_ERR_DOCTYPE_NOT_FINISHED;
1.21      daniel   4948:     }
1.40      daniel   4949:     NEXT;
1.22      daniel   4950: 
                   4951:     /*
1.99      daniel   4952:      * Cleanup
1.22      daniel   4953:      */
1.119     daniel   4954:     if (URI != NULL) xmlFree(URI);
                   4955:     if (ExternalID != NULL) xmlFree(ExternalID);
                   4956:     if (name != NULL) xmlFree(name);
1.21      daniel   4957: }
                   4958: 
1.50      daniel   4959: /**
                   4960:  * xmlParseAttribute:
                   4961:  * @ctxt:  an XML parser context
1.123     daniel   4962:  * @value:  a xmlChar ** used to store the value of the attribute
1.50      daniel   4963:  *
                   4964:  * parse an attribute
1.3       veillard 4965:  *
1.22      daniel   4966:  * [41] Attribute ::= Name Eq AttValue
                   4967:  *
1.98      daniel   4968:  * [ WFC: No External Entity References ]
                   4969:  * Attribute values cannot contain direct or indirect entity references
                   4970:  * to external entities.
                   4971:  *
                   4972:  * [ WFC: No < in Attribute Values ]
                   4973:  * The replacement text of any entity referred to directly or indirectly in
                   4974:  * an attribute value (other than "&lt;") must not contain a <. 
                   4975:  * 
                   4976:  * [ VC: Attribute Value Type ]
1.117     daniel   4977:  * The attribute must have been declared; the value must be of the type
1.99      daniel   4978:  * declared for it.
1.98      daniel   4979:  *
1.22      daniel   4980:  * [25] Eq ::= S? '=' S?
                   4981:  *
1.29      daniel   4982:  * With namespace:
                   4983:  *
                   4984:  * [NS 11] Attribute ::= QName Eq AttValue
1.43      daniel   4985:  *
                   4986:  * Also the case QName == xmlns:??? is handled independently as a namespace
                   4987:  * definition.
1.69      daniel   4988:  *
1.72      daniel   4989:  * Returns the attribute name, and the value in *value.
1.3       veillard 4990:  */
                   4991: 
1.123     daniel   4992: xmlChar *
                   4993: xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
                   4994:     xmlChar *name, *val;
1.3       veillard 4995: 
1.72      daniel   4996:     *value = NULL;
                   4997:     name = xmlParseName(ctxt);
1.22      daniel   4998:     if (name == NULL) {
1.55      daniel   4999:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5000:            ctxt->sax->error(ctxt->userData, "error parsing attribute name\n");
1.59      daniel   5001:        ctxt->wellFormed = 0;
1.123     daniel   5002:        ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.52      daniel   5003:         return(NULL);
1.3       veillard 5004:     }
                   5005: 
                   5006:     /*
1.29      daniel   5007:      * read the value
1.3       veillard 5008:      */
1.42      daniel   5009:     SKIP_BLANKS;
1.40      daniel   5010:     if (CUR == '=') {
                   5011:         NEXT;
1.42      daniel   5012:        SKIP_BLANKS;
1.72      daniel   5013:        val = xmlParseAttValue(ctxt);
1.96      daniel   5014:        ctxt->instate = XML_PARSER_CONTENT;
1.29      daniel   5015:     } else {
1.55      daniel   5016:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5017:            ctxt->sax->error(ctxt->userData,
1.59      daniel   5018:               "Specification mandate value for attribute %s\n", name);
1.123     daniel   5019:        ctxt->errNo = XML_ERR_ATTRIBUTE_WITHOUT_VALUE;
1.59      daniel   5020:        ctxt->wellFormed = 0;
1.52      daniel   5021:        return(NULL);
1.43      daniel   5022:     }
                   5023: 
1.72      daniel   5024:     *value = val;
                   5025:     return(name);
1.3       veillard 5026: }
                   5027: 
1.50      daniel   5028: /**
                   5029:  * xmlParseStartTag:
                   5030:  * @ctxt:  an XML parser context
                   5031:  * 
                   5032:  * parse a start of tag either for rule element or
                   5033:  * EmptyElement. In both case we don't parse the tag closing chars.
1.27      daniel   5034:  *
                   5035:  * [40] STag ::= '<' Name (S Attribute)* S? '>'
                   5036:  *
1.98      daniel   5037:  * [ WFC: Unique Att Spec ]
                   5038:  * No attribute name may appear more than once in the same start-tag or
                   5039:  * empty-element tag. 
                   5040:  *
1.29      daniel   5041:  * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
                   5042:  *
1.98      daniel   5043:  * [ WFC: Unique Att Spec ]
                   5044:  * No attribute name may appear more than once in the same start-tag or
                   5045:  * empty-element tag. 
                   5046:  *
1.29      daniel   5047:  * With namespace:
                   5048:  *
                   5049:  * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
                   5050:  *
                   5051:  * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
1.83      daniel   5052:  *
1.129     daniel   5053:  * Returne the element name parsed
1.2       veillard 5054:  */
                   5055: 
1.123     daniel   5056: xmlChar *
1.69      daniel   5057: xmlParseStartTag(xmlParserCtxtPtr ctxt) {
1.123     daniel   5058:     xmlChar *name;
                   5059:     xmlChar *attname;
                   5060:     xmlChar *attvalue;
                   5061:     const xmlChar **atts = NULL;
1.72      daniel   5062:     int nbatts = 0;
                   5063:     int maxatts = 0;
                   5064:     int i;
1.2       veillard 5065: 
1.83      daniel   5066:     if (CUR != '<') return(NULL);
1.40      daniel   5067:     NEXT;
1.3       veillard 5068: 
1.72      daniel   5069:     name = xmlParseName(ctxt);
1.59      daniel   5070:     if (name == NULL) {
                   5071:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5072:            ctxt->sax->error(ctxt->userData, 
1.59      daniel   5073:             "xmlParseStartTag: invalid element name\n");
1.123     daniel   5074:        ctxt->errNo = XML_ERR_NAME_REQUIRED;
1.59      daniel   5075:        ctxt->wellFormed = 0;
1.83      daniel   5076:         return(NULL);
1.50      daniel   5077:     }
                   5078: 
                   5079:     /*
1.3       veillard 5080:      * Now parse the attributes, it ends up with the ending
                   5081:      *
                   5082:      * (S Attribute)* S?
                   5083:      */
1.42      daniel   5084:     SKIP_BLANKS;
1.91      daniel   5085:     GROW;
1.40      daniel   5086:     while ((IS_CHAR(CUR)) &&
                   5087:            (CUR != '>') && 
                   5088:           ((CUR != '/') || (NXT(1) != '>'))) {
1.123     daniel   5089:        const xmlChar *q = CUR_PTR;
1.91      daniel   5090:        int cons = ctxt->input->consumed;
1.29      daniel   5091: 
1.72      daniel   5092:        attname = xmlParseAttribute(ctxt, &attvalue);
                   5093:         if ((attname != NULL) && (attvalue != NULL)) {
                   5094:            /*
1.98      daniel   5095:             * [ WFC: Unique Att Spec ]
                   5096:             * No attribute name may appear more than once in the same
                   5097:             * start-tag or empty-element tag. 
1.72      daniel   5098:             */
                   5099:            for (i = 0; i < nbatts;i += 2) {
                   5100:                if (!xmlStrcmp(atts[i], attname)) {
                   5101:                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.98      daniel   5102:                        ctxt->sax->error(ctxt->userData,
                   5103:                                "Attribute %s redefined\n",
                   5104:                                         attname);
1.72      daniel   5105:                    ctxt->wellFormed = 0;
1.123     daniel   5106:                    ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
1.119     daniel   5107:                    xmlFree(attname);
                   5108:                    xmlFree(attvalue);
1.98      daniel   5109:                    goto failed;
1.72      daniel   5110:                }
                   5111:            }
                   5112: 
                   5113:            /*
                   5114:             * Add the pair to atts
                   5115:             */
                   5116:            if (atts == NULL) {
                   5117:                maxatts = 10;
1.123     daniel   5118:                atts = (const xmlChar **) xmlMalloc(maxatts * sizeof(xmlChar *));
1.72      daniel   5119:                if (atts == NULL) {
1.86      daniel   5120:                    fprintf(stderr, "malloc of %ld byte failed\n",
1.123     daniel   5121:                            maxatts * (long)sizeof(xmlChar *));
1.83      daniel   5122:                    return(NULL);
1.72      daniel   5123:                }
1.127     daniel   5124:            } else if (nbatts + 4 > maxatts) {
1.72      daniel   5125:                maxatts *= 2;
1.123     daniel   5126:                atts = (const xmlChar **) xmlRealloc(atts,
                   5127:                                                  maxatts * sizeof(xmlChar *));
1.72      daniel   5128:                if (atts == NULL) {
1.86      daniel   5129:                    fprintf(stderr, "realloc of %ld byte failed\n",
1.123     daniel   5130:                            maxatts * (long)sizeof(xmlChar *));
1.83      daniel   5131:                    return(NULL);
1.72      daniel   5132:                }
                   5133:            }
                   5134:            atts[nbatts++] = attname;
                   5135:            atts[nbatts++] = attvalue;
                   5136:            atts[nbatts] = NULL;
                   5137:            atts[nbatts + 1] = NULL;
                   5138:        }
                   5139: 
1.116     daniel   5140: failed:     
1.42      daniel   5141:        SKIP_BLANKS;
1.91      daniel   5142:         if ((cons == ctxt->input->consumed) && (q == CUR_PTR)) {
1.55      daniel   5143:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5144:                ctxt->sax->error(ctxt->userData, 
1.31      daniel   5145:                 "xmlParseStartTag: problem parsing attributes\n");
1.123     daniel   5146:            ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.59      daniel   5147:            ctxt->wellFormed = 0;
1.29      daniel   5148:            break;
1.3       veillard 5149:        }
1.91      daniel   5150:         GROW;
1.3       veillard 5151:     }
                   5152: 
1.43      daniel   5153:     /*
1.72      daniel   5154:      * SAX: Start of Element !
1.43      daniel   5155:      */
1.72      daniel   5156:     if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
1.74      daniel   5157:         ctxt->sax->startElement(ctxt->userData, name, atts);
1.43      daniel   5158: 
1.72      daniel   5159:     if (atts != NULL) {
1.123     daniel   5160:         for (i = 0;i < nbatts;i++) xmlFree((xmlChar *) atts[i]);
1.119     daniel   5161:        xmlFree(atts);
1.72      daniel   5162:     }
1.83      daniel   5163:     return(name);
1.3       veillard 5164: }
                   5165: 
1.50      daniel   5166: /**
                   5167:  * xmlParseEndTag:
                   5168:  * @ctxt:  an XML parser context
1.83      daniel   5169:  * @tagname:  the tag name as parsed in the opening tag.
1.50      daniel   5170:  *
                   5171:  * parse an end of tag
1.27      daniel   5172:  *
                   5173:  * [42] ETag ::= '</' Name S? '>'
1.29      daniel   5174:  *
                   5175:  * With namespace
                   5176:  *
1.72      daniel   5177:  * [NS 9] ETag ::= '</' QName S? '>'
1.7       veillard 5178:  */
                   5179: 
1.55      daniel   5180: void
1.123     daniel   5181: xmlParseEndTag(xmlParserCtxtPtr ctxt, xmlChar *tagname) {
                   5182:     xmlChar *name;
1.7       veillard 5183: 
1.91      daniel   5184:     GROW;
1.40      daniel   5185:     if ((CUR != '<') || (NXT(1) != '/')) {
1.55      daniel   5186:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5187:            ctxt->sax->error(ctxt->userData, "xmlParseEndTag: '</' not found\n");
1.59      daniel   5188:        ctxt->wellFormed = 0;
1.123     daniel   5189:        ctxt->errNo = XML_ERR_LTSLASH_REQUIRED;
1.27      daniel   5190:        return;
                   5191:     }
1.40      daniel   5192:     SKIP(2);
1.7       veillard 5193: 
1.72      daniel   5194:     name = xmlParseName(ctxt);
1.7       veillard 5195: 
                   5196:     /*
                   5197:      * We should definitely be at the ending "S? '>'" part
                   5198:      */
1.91      daniel   5199:     GROW;
1.42      daniel   5200:     SKIP_BLANKS;
1.40      daniel   5201:     if ((!IS_CHAR(CUR)) || (CUR != '>')) {
1.55      daniel   5202:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5203:            ctxt->sax->error(ctxt->userData, "End tag : expected '>'\n");
1.123     daniel   5204:        ctxt->errNo = XML_ERR_GT_REQUIRED;
1.59      daniel   5205:        ctxt->wellFormed = 0;
1.7       veillard 5206:     } else
1.40      daniel   5207:        NEXT;
1.7       veillard 5208: 
1.72      daniel   5209:     /*
1.98      daniel   5210:      * [ WFC: Element Type Match ]
                   5211:      * The Name in an element's end-tag must match the element type in the
                   5212:      * start-tag. 
                   5213:      *
1.83      daniel   5214:      */
                   5215:     if (xmlStrcmp(name, tagname)) {
                   5216:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   5217:            ctxt->sax->error(ctxt->userData,
                   5218:             "Opening and ending tag mismatch: %s and %s\n", tagname, name);
1.122     daniel   5219: 
1.123     daniel   5220:        ctxt->errNo = XML_ERR_TAG_NAME_MISMATCH;
1.83      daniel   5221:        ctxt->wellFormed = 0;
                   5222:     }
                   5223: 
                   5224:     /*
1.72      daniel   5225:      * SAX: End of Tag
                   5226:      */
                   5227:     if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
1.74      daniel   5228:         ctxt->sax->endElement(ctxt->userData, name);
1.72      daniel   5229: 
                   5230:     if (name != NULL)
1.119     daniel   5231:        xmlFree(name);
1.72      daniel   5232: 
1.7       veillard 5233:     return;
                   5234: }
                   5235: 
1.50      daniel   5236: /**
                   5237:  * xmlParseCDSect:
                   5238:  * @ctxt:  an XML parser context
                   5239:  * 
                   5240:  * Parse escaped pure raw content.
1.29      daniel   5241:  *
                   5242:  * [18] CDSect ::= CDStart CData CDEnd
                   5243:  *
                   5244:  * [19] CDStart ::= '<![CDATA['
                   5245:  *
                   5246:  * [20] Data ::= (Char* - (Char* ']]>' Char*))
                   5247:  *
                   5248:  * [21] CDEnd ::= ']]>'
1.3       veillard 5249:  */
1.55      daniel   5250: void
                   5251: xmlParseCDSect(xmlParserCtxtPtr ctxt) {
1.123     daniel   5252:     const xmlChar *base;
                   5253:     xmlChar r, s;
                   5254:     xmlChar cur;
1.3       veillard 5255: 
1.106     daniel   5256:     if ((NXT(0) == '<') && (NXT(1) == '!') &&
1.40      daniel   5257:        (NXT(2) == '[') && (NXT(3) == 'C') &&
                   5258:        (NXT(4) == 'D') && (NXT(5) == 'A') &&
                   5259:        (NXT(6) == 'T') && (NXT(7) == 'A') &&
                   5260:        (NXT(8) == '[')) {
                   5261:        SKIP(9);
1.29      daniel   5262:     } else
1.45      daniel   5263:         return;
1.109     daniel   5264: 
                   5265:     ctxt->instate = XML_PARSER_CDATA_SECTION;
1.40      daniel   5266:     base = CUR_PTR;
                   5267:     if (!IS_CHAR(CUR)) {
1.55      daniel   5268:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   5269:            ctxt->sax->error(ctxt->userData,
                   5270:                             "CData section not finished\n%.50s\n", base);
1.59      daniel   5271:        ctxt->wellFormed = 0;
1.123     daniel   5272:        ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
1.109     daniel   5273:        ctxt->instate = XML_PARSER_CONTENT;
1.45      daniel   5274:         return;
1.3       veillard 5275:     }
1.110     daniel   5276:     r = CUR;
1.91      daniel   5277:     NEXT;
1.40      daniel   5278:     if (!IS_CHAR(CUR)) {
1.55      daniel   5279:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   5280:            ctxt->sax->error(ctxt->userData,
                   5281:                             "CData section not finished\n%.50s\n", base);
1.123     daniel   5282:        ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
1.59      daniel   5283:        ctxt->wellFormed = 0;
1.109     daniel   5284:        ctxt->instate = XML_PARSER_CONTENT;
1.45      daniel   5285:         return;
1.3       veillard 5286:     }
1.110     daniel   5287:     s = CUR;
1.91      daniel   5288:     NEXT;
1.108     veillard 5289:     cur = CUR;
                   5290:     while (IS_CHAR(cur) &&
1.110     daniel   5291:            ((r != ']') || (s != ']') || (cur != '>'))) {
                   5292:        r = s;
                   5293:        s = cur;
                   5294:         NEXT;
1.108     veillard 5295:        cur = CUR;
1.3       veillard 5296:     }
1.109     daniel   5297:     ctxt->instate = XML_PARSER_CONTENT;
1.40      daniel   5298:     if (!IS_CHAR(CUR)) {
1.55      daniel   5299:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   5300:            ctxt->sax->error(ctxt->userData,
                   5301:                             "CData section not finished\n%.50s\n", base);
1.123     daniel   5302:        ctxt->errNo = XML_ERR_CDATA_NOT_FINISHED;
1.59      daniel   5303:        ctxt->wellFormed = 0;
1.45      daniel   5304:         return;
1.3       veillard 5305:     }
1.107     daniel   5306:     NEXT;
1.16      daniel   5307: 
1.45      daniel   5308:     /*
                   5309:      * Ok the segment [base CUR_PTR] is to be consumed as chars.
                   5310:      */
                   5311:     if (ctxt->sax != NULL) {
1.107     daniel   5312:        if (ctxt->sax->cdataBlock != NULL)
1.110     daniel   5313:            ctxt->sax->cdataBlock(ctxt->userData, base, (CUR_PTR - base) - 3);
1.45      daniel   5314:     }
1.2       veillard 5315: }
                   5316: 
1.50      daniel   5317: /**
                   5318:  * xmlParseContent:
                   5319:  * @ctxt:  an XML parser context
                   5320:  *
                   5321:  * Parse a content:
1.2       veillard 5322:  *
1.27      daniel   5323:  * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
1.2       veillard 5324:  */
                   5325: 
1.55      daniel   5326: void
                   5327: xmlParseContent(xmlParserCtxtPtr ctxt) {
1.97      daniel   5328:     GROW;
1.40      daniel   5329:     while ((CUR != '<') || (NXT(1) != '/')) {
1.123     daniel   5330:        const xmlChar *test = CUR_PTR;
1.91      daniel   5331:        int cons = ctxt->input->consumed;
1.123     daniel   5332:        xmlChar tok = ctxt->token;
1.27      daniel   5333: 
                   5334:        /*
                   5335:         * First case : a Processing Instruction.
                   5336:         */
1.40      daniel   5337:        if ((CUR == '<') && (NXT(1) == '?')) {
1.27      daniel   5338:            xmlParsePI(ctxt);
                   5339:        }
1.72      daniel   5340: 
1.27      daniel   5341:        /*
                   5342:         * Second case : a CDSection
                   5343:         */
1.40      daniel   5344:        else if ((CUR == '<') && (NXT(1) == '!') &&
                   5345:            (NXT(2) == '[') && (NXT(3) == 'C') &&
                   5346:            (NXT(4) == 'D') && (NXT(5) == 'A') &&
                   5347:            (NXT(6) == 'T') && (NXT(7) == 'A') &&
                   5348:            (NXT(8) == '[')) {
1.45      daniel   5349:            xmlParseCDSect(ctxt);
1.27      daniel   5350:        }
1.72      daniel   5351: 
1.27      daniel   5352:        /*
                   5353:         * Third case :  a comment
                   5354:         */
1.40      daniel   5355:        else if ((CUR == '<') && (NXT(1) == '!') &&
                   5356:                 (NXT(2) == '-') && (NXT(3) == '-')) {
1.114     daniel   5357:            xmlParseComment(ctxt);
1.97      daniel   5358:            ctxt->instate = XML_PARSER_CONTENT;
1.27      daniel   5359:        }
1.72      daniel   5360: 
1.27      daniel   5361:        /*
                   5362:         * Fourth case :  a sub-element.
                   5363:         */
1.40      daniel   5364:        else if (CUR == '<') {
1.72      daniel   5365:            xmlParseElement(ctxt);
1.45      daniel   5366:        }
1.72      daniel   5367: 
1.45      daniel   5368:        /*
1.50      daniel   5369:         * Fifth case : a reference. If if has not been resolved,
                   5370:         *    parsing returns it's Name, create the node 
1.45      daniel   5371:         */
1.97      daniel   5372: 
1.45      daniel   5373:        else if (CUR == '&') {
1.77      daniel   5374:            xmlParseReference(ctxt);
1.27      daniel   5375:        }
1.72      daniel   5376: 
1.27      daniel   5377:        /*
                   5378:         * Last case, text. Note that References are handled directly.
                   5379:         */
                   5380:        else {
1.45      daniel   5381:            xmlParseCharData(ctxt, 0);
1.3       veillard 5382:        }
1.14      veillard 5383: 
1.91      daniel   5384:        GROW;
1.14      veillard 5385:        /*
1.45      daniel   5386:         * Pop-up of finished entities.
1.14      veillard 5387:         */
1.69      daniel   5388:        while ((CUR == 0) && (ctxt->inputNr > 1))
                   5389:            xmlPopInput(ctxt);
1.45      daniel   5390: 
1.113     daniel   5391:        if ((cons == ctxt->input->consumed) && (test == CUR_PTR) &&
                   5392:            (tok == ctxt->token)) {
1.55      daniel   5393:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5394:                ctxt->sax->error(ctxt->userData,
1.59      daniel   5395:                     "detected an error in element content\n");
1.123     daniel   5396:            ctxt->errNo = XML_ERR_INTERNAL_ERROR;
1.59      daniel   5397:            ctxt->wellFormed = 0;
1.29      daniel   5398:             break;
                   5399:        }
1.3       veillard 5400:     }
1.2       veillard 5401: }
                   5402: 
1.50      daniel   5403: /**
                   5404:  * xmlParseElement:
                   5405:  * @ctxt:  an XML parser context
                   5406:  *
                   5407:  * parse an XML element, this is highly recursive
1.26      daniel   5408:  *
                   5409:  * [39] element ::= EmptyElemTag | STag content ETag
                   5410:  *
1.98      daniel   5411:  * [ WFC: Element Type Match ]
                   5412:  * The Name in an element's end-tag must match the element type in the
                   5413:  * start-tag. 
                   5414:  *
                   5415:  * [ VC: Element Valid ]
1.117     daniel   5416:  * An element is valid if there is a declaration matching elementdecl
1.99      daniel   5417:  * where the Name matches the element type and one of the following holds:
                   5418:  *  - The declaration matches EMPTY and the element has no content.
                   5419:  *  - The declaration matches children and the sequence of child elements
                   5420:  *    belongs to the language generated by the regular expression in the
                   5421:  *    content model, with optional white space (characters matching the
                   5422:  *    nonterminal S) between each pair of child elements. 
                   5423:  *  - The declaration matches Mixed and the content consists of character
                   5424:  *    data and child elements whose types match names in the content model. 
                   5425:  *  - The declaration matches ANY, and the types of any child elements have
                   5426:  *    been declared.
1.2       veillard 5427:  */
1.26      daniel   5428: 
1.72      daniel   5429: void
1.69      daniel   5430: xmlParseElement(xmlParserCtxtPtr ctxt) {
1.123     daniel   5431:     const xmlChar *openTag = CUR_PTR;
                   5432:     xmlChar *name;
1.32      daniel   5433:     xmlParserNodeInfo node_info;
1.118     daniel   5434:     xmlNodePtr ret;
1.2       veillard 5435: 
1.32      daniel   5436:     /* Capture start position */
1.118     daniel   5437:     if (ctxt->record_info) {
                   5438:         node_info.begin_pos = ctxt->input->consumed +
                   5439:                           (CUR_PTR - ctxt->input->base);
                   5440:        node_info.begin_line = ctxt->input->line;
                   5441:     }
1.32      daniel   5442: 
1.83      daniel   5443:     name = xmlParseStartTag(ctxt);
                   5444:     if (name == NULL) {
                   5445:         return;
                   5446:     }
1.118     daniel   5447:     ret = ctxt->node;
1.2       veillard 5448: 
                   5449:     /*
1.99      daniel   5450:      * [ VC: Root Element Type ]
                   5451:      * The Name in the document type declaration must match the element
                   5452:      * type of the root element. 
                   5453:      */
1.105     daniel   5454:     if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
                   5455:         ctxt->node && (ctxt->node == ctxt->myDoc->root))
1.102     daniel   5456:         ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1.99      daniel   5457: 
                   5458:     /*
1.2       veillard 5459:      * Check for an Empty Element.
                   5460:      */
1.40      daniel   5461:     if ((CUR == '/') && (NXT(1) == '>')) {
                   5462:         SKIP(2);
1.72      daniel   5463:        if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
1.83      daniel   5464:            ctxt->sax->endElement(ctxt->userData, name);
1.119     daniel   5465:        xmlFree(name);
1.72      daniel   5466:        return;
1.2       veillard 5467:     }
1.91      daniel   5468:     if (CUR == '>') {
                   5469:         NEXT;
                   5470:     } else {
1.55      daniel   5471:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   5472:            ctxt->sax->error(ctxt->userData,
                   5473:                             "Couldn't find end of Start Tag\n%.30s\n",
1.57      daniel   5474:                             openTag);
1.59      daniel   5475:        ctxt->wellFormed = 0;
1.123     daniel   5476:        ctxt->errNo = XML_ERR_GT_REQUIRED;
1.45      daniel   5477: 
                   5478:        /*
                   5479:         * end of parsing of this node.
                   5480:         */
                   5481:        nodePop(ctxt);
1.119     daniel   5482:        xmlFree(name);
1.118     daniel   5483: 
                   5484:        /*
                   5485:         * Capture end position and add node
                   5486:         */
                   5487:        if ( ret != NULL && ctxt->record_info ) {
                   5488:           node_info.end_pos = ctxt->input->consumed +
                   5489:                              (CUR_PTR - ctxt->input->base);
                   5490:           node_info.end_line = ctxt->input->line;
                   5491:           node_info.node = ret;
                   5492:           xmlParserAddNodeInfo(ctxt, &node_info);
                   5493:        }
1.72      daniel   5494:        return;
1.2       veillard 5495:     }
                   5496: 
                   5497:     /*
                   5498:      * Parse the content of the element:
                   5499:      */
1.45      daniel   5500:     xmlParseContent(ctxt);
1.40      daniel   5501:     if (!IS_CHAR(CUR)) {
1.55      daniel   5502:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5503:            ctxt->sax->error(ctxt->userData,
1.57      daniel   5504:                 "Premature end of data in tag %.30s\n", openTag);
1.59      daniel   5505:        ctxt->wellFormed = 0;
1.123     daniel   5506:        ctxt->errNo = XML_ERR_TAG_NOT_FINISED;
1.45      daniel   5507: 
                   5508:        /*
                   5509:         * end of parsing of this node.
                   5510:         */
                   5511:        nodePop(ctxt);
1.119     daniel   5512:        xmlFree(name);
1.72      daniel   5513:        return;
1.2       veillard 5514:     }
                   5515: 
                   5516:     /*
1.27      daniel   5517:      * parse the end of tag: '</' should be here.
1.2       veillard 5518:      */
1.83      daniel   5519:     xmlParseEndTag(ctxt, name);
1.119     daniel   5520:     xmlFree(name);
1.118     daniel   5521: 
                   5522:     /*
                   5523:      * Capture end position and add node
                   5524:      */
                   5525:     if ( ret != NULL && ctxt->record_info ) {
                   5526:        node_info.end_pos = ctxt->input->consumed +
                   5527:                           (CUR_PTR - ctxt->input->base);
                   5528:        node_info.end_line = ctxt->input->line;
                   5529:        node_info.node = ret;
                   5530:        xmlParserAddNodeInfo(ctxt, &node_info);
                   5531:     }
1.2       veillard 5532: }
                   5533: 
1.50      daniel   5534: /**
                   5535:  * xmlParseVersionNum:
                   5536:  * @ctxt:  an XML parser context
                   5537:  *
                   5538:  * parse the XML version value.
1.29      daniel   5539:  *
                   5540:  * [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
1.68      daniel   5541:  *
                   5542:  * Returns the string giving the XML version number, or NULL
1.29      daniel   5543:  */
1.123     daniel   5544: xmlChar *
1.55      daniel   5545: xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
1.123     daniel   5546:     const xmlChar *q = CUR_PTR;
                   5547:     xmlChar *ret;
1.29      daniel   5548: 
1.40      daniel   5549:     while (IS_CHAR(CUR) &&
                   5550:            (((CUR >= 'a') && (CUR <= 'z')) ||
                   5551:             ((CUR >= 'A') && (CUR <= 'Z')) ||
                   5552:             ((CUR >= '0') && (CUR <= '9')) ||
                   5553:             (CUR == '_') || (CUR == '.') ||
                   5554:            (CUR == ':') || (CUR == '-'))) NEXT;
                   5555:     ret = xmlStrndup(q, CUR_PTR - q);
1.29      daniel   5556:     return(ret);
                   5557: }
                   5558: 
1.50      daniel   5559: /**
                   5560:  * xmlParseVersionInfo:
                   5561:  * @ctxt:  an XML parser context
                   5562:  * 
                   5563:  * parse the XML version.
1.29      daniel   5564:  *
                   5565:  * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
                   5566:  * 
                   5567:  * [25] Eq ::= S? '=' S?
1.50      daniel   5568:  *
1.68      daniel   5569:  * Returns the version string, e.g. "1.0"
1.29      daniel   5570:  */
                   5571: 
1.123     daniel   5572: xmlChar *
1.55      daniel   5573: xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
1.123     daniel   5574:     xmlChar *version = NULL;
                   5575:     const xmlChar *q;
1.29      daniel   5576: 
1.40      daniel   5577:     if ((CUR == 'v') && (NXT(1) == 'e') &&
                   5578:         (NXT(2) == 'r') && (NXT(3) == 's') &&
                   5579:        (NXT(4) == 'i') && (NXT(5) == 'o') &&
                   5580:        (NXT(6) == 'n')) {
                   5581:        SKIP(7);
1.42      daniel   5582:        SKIP_BLANKS;
1.40      daniel   5583:        if (CUR != '=') {
1.55      daniel   5584:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   5585:                ctxt->sax->error(ctxt->userData,
                   5586:                                 "xmlParseVersionInfo : expected '='\n");
1.59      daniel   5587:            ctxt->wellFormed = 0;
1.123     daniel   5588:            ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
1.31      daniel   5589:            return(NULL);
                   5590:         }
1.40      daniel   5591:        NEXT;
1.42      daniel   5592:        SKIP_BLANKS;
1.40      daniel   5593:        if (CUR == '"') {
                   5594:            NEXT;
                   5595:            q = CUR_PTR;
1.29      daniel   5596:            version = xmlParseVersionNum(ctxt);
1.55      daniel   5597:            if (CUR != '"') {
                   5598:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   5599:                    ctxt->sax->error(ctxt->userData, 
                   5600:                                     "String not closed\n%.50s\n", q);
1.59      daniel   5601:                ctxt->wellFormed = 0;
1.123     daniel   5602:                ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55      daniel   5603:            } else
1.40      daniel   5604:                NEXT;
                   5605:        } else if (CUR == '\''){
                   5606:            NEXT;
                   5607:            q = CUR_PTR;
1.29      daniel   5608:            version = xmlParseVersionNum(ctxt);
1.55      daniel   5609:            if (CUR != '\'') {
                   5610:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   5611:                    ctxt->sax->error(ctxt->userData,
                   5612:                                     "String not closed\n%.50s\n", q);
1.123     daniel   5613:                ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.59      daniel   5614:                ctxt->wellFormed = 0;
1.55      daniel   5615:            } else
1.40      daniel   5616:                NEXT;
1.31      daniel   5617:        } else {
1.55      daniel   5618:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5619:                ctxt->sax->error(ctxt->userData,
1.59      daniel   5620:                      "xmlParseVersionInfo : expected ' or \"\n");
1.122     daniel   5621:            ctxt->wellFormed = 0;
1.123     daniel   5622:            ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
1.29      daniel   5623:        }
                   5624:     }
                   5625:     return(version);
                   5626: }
                   5627: 
1.50      daniel   5628: /**
                   5629:  * xmlParseEncName:
                   5630:  * @ctxt:  an XML parser context
                   5631:  *
                   5632:  * parse the XML encoding name
1.29      daniel   5633:  *
                   5634:  * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
1.50      daniel   5635:  *
1.68      daniel   5636:  * Returns the encoding name value or NULL
1.29      daniel   5637:  */
1.123     daniel   5638: xmlChar *
1.55      daniel   5639: xmlParseEncName(xmlParserCtxtPtr ctxt) {
1.123     daniel   5640:     const xmlChar *q = CUR_PTR;
                   5641:     xmlChar *ret = NULL;
1.29      daniel   5642: 
1.40      daniel   5643:     if (((CUR >= 'a') && (CUR <= 'z')) ||
                   5644:         ((CUR >= 'A') && (CUR <= 'Z'))) {
                   5645:        NEXT;
                   5646:        while (IS_CHAR(CUR) &&
                   5647:               (((CUR >= 'a') && (CUR <= 'z')) ||
                   5648:                ((CUR >= 'A') && (CUR <= 'Z')) ||
                   5649:                ((CUR >= '0') && (CUR <= '9')) ||
                   5650:                (CUR == '-'))) NEXT;
                   5651:        ret = xmlStrndup(q, CUR_PTR - q);
1.29      daniel   5652:     } else {
1.55      daniel   5653:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5654:            ctxt->sax->error(ctxt->userData, "Invalid XML encoding name\n");
1.59      daniel   5655:        ctxt->wellFormed = 0;
1.123     daniel   5656:        ctxt->errNo = XML_ERR_ENCODING_NAME;
1.29      daniel   5657:     }
                   5658:     return(ret);
                   5659: }
                   5660: 
1.50      daniel   5661: /**
                   5662:  * xmlParseEncodingDecl:
                   5663:  * @ctxt:  an XML parser context
                   5664:  * 
                   5665:  * parse the XML encoding declaration
1.29      daniel   5666:  *
                   5667:  * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
1.50      daniel   5668:  *
                   5669:  * TODO: this should setup the conversion filters.
                   5670:  *
1.68      daniel   5671:  * Returns the encoding value or NULL
1.29      daniel   5672:  */
                   5673: 
1.123     daniel   5674: xmlChar *
1.55      daniel   5675: xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
1.123     daniel   5676:     xmlChar *encoding = NULL;
                   5677:     const xmlChar *q;
1.29      daniel   5678: 
1.42      daniel   5679:     SKIP_BLANKS;
1.40      daniel   5680:     if ((CUR == 'e') && (NXT(1) == 'n') &&
                   5681:         (NXT(2) == 'c') && (NXT(3) == 'o') &&
                   5682:        (NXT(4) == 'd') && (NXT(5) == 'i') &&
                   5683:        (NXT(6) == 'n') && (NXT(7) == 'g')) {
                   5684:        SKIP(8);
1.42      daniel   5685:        SKIP_BLANKS;
1.40      daniel   5686:        if (CUR != '=') {
1.55      daniel   5687:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   5688:                ctxt->sax->error(ctxt->userData,
                   5689:                                 "xmlParseEncodingDecl : expected '='\n");
1.59      daniel   5690:            ctxt->wellFormed = 0;
1.123     daniel   5691:            ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
1.31      daniel   5692:            return(NULL);
                   5693:         }
1.40      daniel   5694:        NEXT;
1.42      daniel   5695:        SKIP_BLANKS;
1.40      daniel   5696:        if (CUR == '"') {
                   5697:            NEXT;
                   5698:            q = CUR_PTR;
1.29      daniel   5699:            encoding = xmlParseEncName(ctxt);
1.55      daniel   5700:            if (CUR != '"') {
                   5701:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   5702:                    ctxt->sax->error(ctxt->userData, 
                   5703:                                     "String not closed\n%.50s\n", q);
1.59      daniel   5704:                ctxt->wellFormed = 0;
1.123     daniel   5705:                ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55      daniel   5706:            } else
1.40      daniel   5707:                NEXT;
                   5708:        } else if (CUR == '\''){
                   5709:            NEXT;
                   5710:            q = CUR_PTR;
1.29      daniel   5711:            encoding = xmlParseEncName(ctxt);
1.55      daniel   5712:            if (CUR != '\'') {
                   5713:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   5714:                    ctxt->sax->error(ctxt->userData,
                   5715:                                     "String not closed\n%.50s\n", q);
1.59      daniel   5716:                ctxt->wellFormed = 0;
1.123     daniel   5717:                ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55      daniel   5718:            } else
1.40      daniel   5719:                NEXT;
                   5720:        } else if (CUR == '"'){
1.55      daniel   5721:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5722:                ctxt->sax->error(ctxt->userData,
1.59      daniel   5723:                     "xmlParseEncodingDecl : expected ' or \"\n");
                   5724:            ctxt->wellFormed = 0;
1.123     daniel   5725:            ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
1.29      daniel   5726:        }
                   5727:     }
                   5728:     return(encoding);
                   5729: }
                   5730: 
1.50      daniel   5731: /**
                   5732:  * xmlParseSDDecl:
                   5733:  * @ctxt:  an XML parser context
                   5734:  *
                   5735:  * parse the XML standalone declaration
1.29      daniel   5736:  *
                   5737:  * [32] SDDecl ::= S 'standalone' Eq
                   5738:  *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"')) 
1.99      daniel   5739:  *
                   5740:  * [ VC: Standalone Document Declaration ]
                   5741:  * TODO The standalone document declaration must have the value "no"
                   5742:  * if any external markup declarations contain declarations of:
                   5743:  *  - attributes with default values, if elements to which these
                   5744:  *    attributes apply appear in the document without specifications
                   5745:  *    of values for these attributes, or
                   5746:  *  - entities (other than amp, lt, gt, apos, quot), if references
                   5747:  *    to those entities appear in the document, or
                   5748:  *  - attributes with values subject to normalization, where the
                   5749:  *    attribute appears in the document with a value which will change
                   5750:  *    as a result of normalization, or
                   5751:  *  - element types with element content, if white space occurs directly
                   5752:  *    within any instance of those types.
1.68      daniel   5753:  *
                   5754:  * Returns 1 if standalone, 0 otherwise
1.29      daniel   5755:  */
                   5756: 
1.55      daniel   5757: int
                   5758: xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
1.29      daniel   5759:     int standalone = -1;
                   5760: 
1.42      daniel   5761:     SKIP_BLANKS;
1.40      daniel   5762:     if ((CUR == 's') && (NXT(1) == 't') &&
                   5763:         (NXT(2) == 'a') && (NXT(3) == 'n') &&
                   5764:        (NXT(4) == 'd') && (NXT(5) == 'a') &&
                   5765:        (NXT(6) == 'l') && (NXT(7) == 'o') &&
                   5766:        (NXT(8) == 'n') && (NXT(9) == 'e')) {
                   5767:        SKIP(10);
1.81      daniel   5768:         SKIP_BLANKS;
1.40      daniel   5769:        if (CUR != '=') {
1.55      daniel   5770:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5771:                ctxt->sax->error(ctxt->userData,
1.59      daniel   5772:                    "XML standalone declaration : expected '='\n");
1.123     daniel   5773:            ctxt->errNo = XML_ERR_EQUAL_REQUIRED;
1.59      daniel   5774:            ctxt->wellFormed = 0;
1.32      daniel   5775:            return(standalone);
                   5776:         }
1.40      daniel   5777:        NEXT;
1.42      daniel   5778:        SKIP_BLANKS;
1.40      daniel   5779:         if (CUR == '\''){
                   5780:            NEXT;
                   5781:            if ((CUR == 'n') && (NXT(1) == 'o')) {
1.29      daniel   5782:                standalone = 0;
1.40      daniel   5783:                 SKIP(2);
                   5784:            } else if ((CUR == 'y') && (NXT(1) == 'e') &&
                   5785:                       (NXT(2) == 's')) {
1.29      daniel   5786:                standalone = 1;
1.40      daniel   5787:                SKIP(3);
1.29      daniel   5788:             } else {
1.55      daniel   5789:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   5790:                    ctxt->sax->error(ctxt->userData,
                   5791:                                     "standalone accepts only 'yes' or 'no'\n");
1.123     daniel   5792:                ctxt->errNo = XML_ERR_STANDALONE_VALUE;
1.59      daniel   5793:                ctxt->wellFormed = 0;
1.29      daniel   5794:            }
1.55      daniel   5795:            if (CUR != '\'') {
                   5796:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5797:                    ctxt->sax->error(ctxt->userData, "String not closed\n");
1.123     daniel   5798:                ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.59      daniel   5799:                ctxt->wellFormed = 0;
1.55      daniel   5800:            } else
1.40      daniel   5801:                NEXT;
                   5802:        } else if (CUR == '"'){
                   5803:            NEXT;
                   5804:            if ((CUR == 'n') && (NXT(1) == 'o')) {
1.29      daniel   5805:                standalone = 0;
1.40      daniel   5806:                SKIP(2);
                   5807:            } else if ((CUR == 'y') && (NXT(1) == 'e') &&
                   5808:                       (NXT(2) == 's')) {
1.29      daniel   5809:                standalone = 1;
1.40      daniel   5810:                 SKIP(3);
1.29      daniel   5811:             } else {
1.55      daniel   5812:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5813:                    ctxt->sax->error(ctxt->userData,
1.59      daniel   5814:                        "standalone accepts only 'yes' or 'no'\n");
1.123     daniel   5815:                ctxt->errNo = XML_ERR_STANDALONE_VALUE;
1.59      daniel   5816:                ctxt->wellFormed = 0;
1.29      daniel   5817:            }
1.55      daniel   5818:            if (CUR != '"') {
                   5819:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5820:                    ctxt->sax->error(ctxt->userData, "String not closed\n");
1.59      daniel   5821:                ctxt->wellFormed = 0;
1.123     daniel   5822:                ctxt->errNo = XML_ERR_STRING_NOT_CLOSED;
1.55      daniel   5823:            } else
1.40      daniel   5824:                NEXT;
1.37      daniel   5825:        } else {
1.55      daniel   5826:             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   5827:                ctxt->sax->error(ctxt->userData,
                   5828:                                 "Standalone value not found\n");
1.59      daniel   5829:            ctxt->wellFormed = 0;
1.123     daniel   5830:            ctxt->errNo = XML_ERR_STRING_NOT_STARTED;
1.37      daniel   5831:         }
1.29      daniel   5832:     }
                   5833:     return(standalone);
                   5834: }
                   5835: 
1.50      daniel   5836: /**
                   5837:  * xmlParseXMLDecl:
                   5838:  * @ctxt:  an XML parser context
                   5839:  * 
                   5840:  * parse an XML declaration header
1.29      daniel   5841:  *
                   5842:  * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
1.1       veillard 5843:  */
                   5844: 
1.55      daniel   5845: void
                   5846: xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
1.123     daniel   5847:     xmlChar *version;
1.1       veillard 5848: 
                   5849:     /*
1.19      daniel   5850:      * We know that '<?xml' is here.
1.1       veillard 5851:      */
1.40      daniel   5852:     SKIP(5);
1.1       veillard 5853: 
1.59      daniel   5854:     if (!IS_BLANK(CUR)) {
                   5855:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5856:            ctxt->sax->error(ctxt->userData, "Blank needed after '<?xml'\n");
1.123     daniel   5857:        ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   5858:        ctxt->wellFormed = 0;
                   5859:     }
1.42      daniel   5860:     SKIP_BLANKS;
1.1       veillard 5861: 
                   5862:     /*
1.29      daniel   5863:      * We should have the VersionInfo here.
1.1       veillard 5864:      */
1.29      daniel   5865:     version = xmlParseVersionInfo(ctxt);
                   5866:     if (version == NULL)
1.45      daniel   5867:        version = xmlCharStrdup(XML_DEFAULT_VERSION);
1.72      daniel   5868:     ctxt->version = xmlStrdup(version);
1.119     daniel   5869:     xmlFree(version);
1.29      daniel   5870: 
                   5871:     /*
                   5872:      * We may have the encoding declaration
                   5873:      */
1.59      daniel   5874:     if (!IS_BLANK(CUR)) {
                   5875:         if ((CUR == '?') && (NXT(1) == '>')) {
                   5876:            SKIP(2);
                   5877:            return;
                   5878:        }
                   5879:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5880:            ctxt->sax->error(ctxt->userData, "Blank needed here\n");
1.123     daniel   5881:        ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   5882:        ctxt->wellFormed = 0;
                   5883:     }
1.72      daniel   5884:     ctxt->encoding = xmlParseEncodingDecl(ctxt);
1.1       veillard 5885: 
                   5886:     /*
1.29      daniel   5887:      * We may have the standalone status.
1.1       veillard 5888:      */
1.72      daniel   5889:     if ((ctxt->encoding != NULL) && (!IS_BLANK(CUR))) {
1.59      daniel   5890:         if ((CUR == '?') && (NXT(1) == '>')) {
                   5891:            SKIP(2);
                   5892:            return;
                   5893:        }
                   5894:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5895:            ctxt->sax->error(ctxt->userData, "Blank needed here\n");
1.59      daniel   5896:        ctxt->wellFormed = 0;
1.123     daniel   5897:        ctxt->errNo = XML_ERR_SPACE_REQUIRED;
1.59      daniel   5898:     }
                   5899:     SKIP_BLANKS;
1.72      daniel   5900:     ctxt->standalone = xmlParseSDDecl(ctxt);
1.1       veillard 5901: 
1.42      daniel   5902:     SKIP_BLANKS;
1.40      daniel   5903:     if ((CUR == '?') && (NXT(1) == '>')) {
                   5904:         SKIP(2);
                   5905:     } else if (CUR == '>') {
1.31      daniel   5906:         /* Deprecated old WD ... */
1.55      daniel   5907:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   5908:            ctxt->sax->error(ctxt->userData, 
                   5909:                             "XML declaration must end-up with '?>'\n");
1.59      daniel   5910:        ctxt->wellFormed = 0;
1.123     daniel   5911:        ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
1.40      daniel   5912:        NEXT;
1.29      daniel   5913:     } else {
1.55      daniel   5914:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.122     daniel   5915:            ctxt->sax->error(ctxt->userData,
                   5916:                             "parsing XML declaration: '?>' expected\n");
1.59      daniel   5917:        ctxt->wellFormed = 0;
1.123     daniel   5918:        ctxt->errNo = XML_ERR_XMLDECL_NOT_FINISHED;
1.40      daniel   5919:        MOVETO_ENDTAG(CUR_PTR);
                   5920:        NEXT;
1.29      daniel   5921:     }
1.1       veillard 5922: }
                   5923: 
1.50      daniel   5924: /**
                   5925:  * xmlParseMisc:
                   5926:  * @ctxt:  an XML parser context
                   5927:  * 
                   5928:  * parse an XML Misc* optionnal field.
1.21      daniel   5929:  *
1.22      daniel   5930:  * [27] Misc ::= Comment | PI |  S
1.1       veillard 5931:  */
                   5932: 
1.55      daniel   5933: void
                   5934: xmlParseMisc(xmlParserCtxtPtr ctxt) {
1.40      daniel   5935:     while (((CUR == '<') && (NXT(1) == '?')) ||
                   5936:            ((CUR == '<') && (NXT(1) == '!') &&
                   5937:            (NXT(2) == '-') && (NXT(3) == '-')) ||
                   5938:            IS_BLANK(CUR)) {
                   5939:         if ((CUR == '<') && (NXT(1) == '?')) {
1.16      daniel   5940:            xmlParsePI(ctxt);
1.40      daniel   5941:        } else if (IS_BLANK(CUR)) {
                   5942:            NEXT;
1.1       veillard 5943:        } else
1.114     daniel   5944:            xmlParseComment(ctxt);
1.1       veillard 5945:     }
                   5946: }
                   5947: 
1.50      daniel   5948: /**
                   5949:  * xmlParseDocument :
                   5950:  * @ctxt:  an XML parser context
                   5951:  * 
                   5952:  * parse an XML document (and build a tree if using the standard SAX
                   5953:  * interface).
1.21      daniel   5954:  *
1.22      daniel   5955:  * [1] document ::= prolog element Misc*
1.29      daniel   5956:  *
                   5957:  * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
1.50      daniel   5958:  *
1.68      daniel   5959:  * Returns 0, -1 in case of error. the parser context is augmented
1.50      daniel   5960:  *                as a result of the parsing.
1.1       veillard 5961:  */
                   5962: 
1.55      daniel   5963: int
                   5964: xmlParseDocument(xmlParserCtxtPtr ctxt) {
1.45      daniel   5965:     xmlDefaultSAXHandlerInit();
                   5966: 
1.91      daniel   5967:     GROW;
                   5968: 
1.14      veillard 5969:     /*
1.44      daniel   5970:      * SAX: beginning of the document processing.
                   5971:      */
1.72      daniel   5972:     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
1.74      daniel   5973:         ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
1.44      daniel   5974: 
                   5975:     /*
1.117     daniel   5976:      * TODO We should check for encoding here and plug-in some
                   5977:      * conversion code !!!!
1.14      veillard 5978:      */
1.1       veillard 5979: 
                   5980:     /*
                   5981:      * Wipe out everything which is before the first '<'
                   5982:      */
1.59      daniel   5983:     if (IS_BLANK(CUR)) {
                   5984:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5985:            ctxt->sax->error(ctxt->userData,
1.59      daniel   5986:            "Extra spaces at the beginning of the document are not allowed\n");
1.123     daniel   5987:        ctxt->errNo = XML_ERR_DOCUMENT_START;
1.59      daniel   5988:        ctxt->wellFormed = 0;
                   5989:        SKIP_BLANKS;
                   5990:     }
                   5991: 
                   5992:     if (CUR == 0) {
                   5993:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5994:            ctxt->sax->error(ctxt->userData, "Document is empty\n");
1.123     daniel   5995:        ctxt->errNo = XML_ERR_DOCUMENT_EMPTY;
1.59      daniel   5996:        ctxt->wellFormed = 0;
                   5997:     }
1.1       veillard 5998: 
                   5999:     /*
                   6000:      * Check for the XMLDecl in the Prolog.
                   6001:      */
1.91      daniel   6002:     GROW;
1.40      daniel   6003:     if ((CUR == '<') && (NXT(1) == '?') &&
                   6004:         (NXT(2) == 'x') && (NXT(3) == 'm') &&
                   6005:        (NXT(4) == 'l')) {
1.19      daniel   6006:        xmlParseXMLDecl(ctxt);
                   6007:        /* SKIP_EOL(cur); */
1.42      daniel   6008:        SKIP_BLANKS;
1.40      daniel   6009:     } else if ((CUR == '<') && (NXT(1) == '?') &&
                   6010:         (NXT(2) == 'X') && (NXT(3) == 'M') &&
                   6011:        (NXT(4) == 'L')) {
1.19      daniel   6012:        /*
                   6013:         * The first drafts were using <?XML and the final W3C REC
                   6014:         * now use <?xml ...
                   6015:         */
1.16      daniel   6016:        xmlParseXMLDecl(ctxt);
1.1       veillard 6017:        /* SKIP_EOL(cur); */
1.42      daniel   6018:        SKIP_BLANKS;
1.1       veillard 6019:     } else {
1.72      daniel   6020:        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
1.1       veillard 6021:     }
1.72      daniel   6022:     if ((ctxt->sax) && (ctxt->sax->startDocument))
1.74      daniel   6023:         ctxt->sax->startDocument(ctxt->userData);
1.1       veillard 6024: 
                   6025:     /*
                   6026:      * The Misc part of the Prolog
                   6027:      */
1.91      daniel   6028:     GROW;
1.16      daniel   6029:     xmlParseMisc(ctxt);
1.1       veillard 6030: 
                   6031:     /*
1.29      daniel   6032:      * Then possibly doc type declaration(s) and more Misc
1.21      daniel   6033:      * (doctypedecl Misc*)?
                   6034:      */
1.91      daniel   6035:     GROW;
1.40      daniel   6036:     if ((CUR == '<') && (NXT(1) == '!') &&
                   6037:        (NXT(2) == 'D') && (NXT(3) == 'O') &&
                   6038:        (NXT(4) == 'C') && (NXT(5) == 'T') &&
                   6039:        (NXT(6) == 'Y') && (NXT(7) == 'P') &&
                   6040:        (NXT(8) == 'E')) {
1.22      daniel   6041:        xmlParseDocTypeDecl(ctxt);
1.96      daniel   6042:        ctxt->instate = XML_PARSER_PROLOG;
1.22      daniel   6043:        xmlParseMisc(ctxt);
1.21      daniel   6044:     }
                   6045: 
                   6046:     /*
                   6047:      * Time to start parsing the tree itself
1.1       veillard 6048:      */
1.91      daniel   6049:     GROW;
1.96      daniel   6050:     ctxt->instate = XML_PARSER_CONTENT;
1.72      daniel   6051:     xmlParseElement(ctxt);
1.96      daniel   6052:     ctxt->instate = XML_PARSER_EPILOG;
1.33      daniel   6053: 
                   6054:     /*
                   6055:      * The Misc part at the end
                   6056:      */
                   6057:     xmlParseMisc(ctxt);
1.16      daniel   6058: 
1.59      daniel   6059:     if (CUR != 0) {
                   6060:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   6061:            ctxt->sax->error(ctxt->userData,
1.59      daniel   6062:                "Extra content at the end of the document\n");
                   6063:        ctxt->wellFormed = 0;
1.123     daniel   6064:        ctxt->errNo = XML_ERR_DOCUMENT_END;
1.59      daniel   6065:     }
1.96      daniel   6066:     ctxt->instate = XML_PARSER_EOF;
1.59      daniel   6067: 
1.44      daniel   6068:     /*
                   6069:      * SAX: end of the document processing.
                   6070:      */
1.72      daniel   6071:     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
1.74      daniel   6072:         ctxt->sax->endDocument(ctxt->userData);
1.59      daniel   6073:     if (! ctxt->wellFormed) return(-1);
1.16      daniel   6074:     return(0);
                   6075: }
                   6076: 
1.98      daniel   6077: /************************************************************************
                   6078:  *                                                                     *
1.128     daniel   6079:  *             Progressive parsing interfaces                          *
                   6080:  *                                                                     *
                   6081:  ************************************************************************/
                   6082: 
                   6083: /**
                   6084:  * xmlParseLookupSequence:
                   6085:  * @ctxt:  an XML parser context
                   6086:  * @first:  the first char to lookup
                   6087:  * @next:  the next char to lookup
                   6088:  *
                   6089:  * Try to find if a sequence (first, next) or  just (first) if next
                   6090:  * is zero is available in the input stream.
                   6091:  * Since XML-1.0 is an LALR(2) grammar a sequence of 2 char should be
                   6092:  * enought. If this doesn't prove true this function call may change.
                   6093:  *
                   6094:  * Returns 1 if the full sequence is available, 0 otherwise.
                   6095:  */
                   6096: int
                   6097: xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first, xmlChar next) {
                   6098:     return(0);
                   6099: }
                   6100: 
                   6101: /**
                   6102:  * xmlParseTry:
                   6103:  * @ctxt:  an XML parser context
                   6104:  *
                   6105:  * Try to progress on parsing
                   6106:  *
                   6107:  * Returns zero if no parsing was possible
                   6108:  */
                   6109: int
                   6110: xmlParseTry(xmlParserCtxtPtr ctxt) {
                   6111:     int ret = 0;
                   6112: 
                   6113:     while (1) {
                   6114:         switch (ctxt->instate) {
                   6115:             case XML_PARSER_EOF:
                   6116:                return(0);
                   6117:             case XML_PARSER_PROLOG:
                   6118:             case XML_PARSER_CONTENT:
                   6119:             case XML_PARSER_ENTITY_DECL:
                   6120:             case XML_PARSER_ENTITY_VALUE:
                   6121:             case XML_PARSER_ATTRIBUTE_VALUE:
                   6122:             case XML_PARSER_DTD:
                   6123:             case XML_PARSER_EPILOG:
                   6124:             case XML_PARSER_COMMENT:
                   6125:             case XML_PARSER_CDATA_SECTION:
1.132     daniel   6126:                break;
1.128     daniel   6127:        }
                   6128:     }
                   6129:     return(ret);
                   6130: }
                   6131: 
                   6132: /**
                   6133:  * xmlParseChunk:
                   6134:  * @ctxt:  an XML parser context
                   6135:  * @chunk:  an char array
                   6136:  * @size:  the size in byte of the chunk
                   6137:  * @terminate:  last chunk indicator
                   6138:  *
                   6139:  * Parse a Chunk of memory
                   6140:  *
                   6141:  * Returns zero if no error, the xmlParserErrors otherwise.
                   6142:  */
                   6143: xmlParserErrors
                   6144: xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
                   6145:               int terminate) {
1.132     daniel   6146:     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
                   6147:         (ctxt->input->buf != NULL))  {       
                   6148:        xmlParserInputBufferPush(ctxt->input->buf, size, chunk);              
1.128     daniel   6149:     }
                   6150:     return((xmlParserErrors) ctxt->errNo);           
                   6151: }
                   6152: 
                   6153: /************************************************************************
                   6154:  *                                                                     *
1.98      daniel   6155:  *             I/O front end functions to the parser                   *
                   6156:  *                                                                     *
                   6157:  ************************************************************************/
                   6158: 
1.50      daniel   6159: /**
1.86      daniel   6160:  * xmlCreateDocParserCtxt :
1.123     daniel   6161:  * @cur:  a pointer to an array of xmlChar
1.50      daniel   6162:  *
1.69      daniel   6163:  * Create a parser context for an XML in-memory document.
                   6164:  *
                   6165:  * Returns the new parser context or NULL
1.16      daniel   6166:  */
1.69      daniel   6167: xmlParserCtxtPtr
1.123     daniel   6168: xmlCreateDocParserCtxt(xmlChar *cur) {
1.16      daniel   6169:     xmlParserCtxtPtr ctxt;
1.40      daniel   6170:     xmlParserInputPtr input;
1.75      daniel   6171:     xmlCharEncoding enc;
1.16      daniel   6172: 
1.97      daniel   6173:     ctxt = xmlNewParserCtxt();
1.16      daniel   6174:     if (ctxt == NULL) {
                   6175:        return(NULL);
                   6176:     }
1.96      daniel   6177:     input = xmlNewInputStream(ctxt);
1.40      daniel   6178:     if (input == NULL) {
1.97      daniel   6179:        xmlFreeParserCtxt(ctxt);
1.40      daniel   6180:        return(NULL);
                   6181:     }
                   6182: 
1.75      daniel   6183:     /*
                   6184:      * plug some encoding conversion routines here. !!!
                   6185:      */
                   6186:     enc = xmlDetectCharEncoding(cur);
                   6187:     xmlSwitchEncoding(ctxt, enc);
                   6188: 
1.40      daniel   6189:     input->base = cur;
                   6190:     input->cur = cur;
                   6191: 
                   6192:     inputPush(ctxt, input);
1.69      daniel   6193:     return(ctxt);
                   6194: }
                   6195: 
                   6196: /**
                   6197:  * xmlSAXParseDoc :
                   6198:  * @sax:  the SAX handler block
1.123     daniel   6199:  * @cur:  a pointer to an array of xmlChar
1.69      daniel   6200:  * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
                   6201:  *             documents
                   6202:  *
                   6203:  * parse an XML in-memory document and build a tree.
                   6204:  * It use the given SAX function block to handle the parsing callback.
                   6205:  * If sax is NULL, fallback to the default DOM tree building routines.
                   6206:  * 
                   6207:  * Returns the resulting document tree
                   6208:  */
                   6209: 
                   6210: xmlDocPtr
1.123     daniel   6211: xmlSAXParseDoc(xmlSAXHandlerPtr sax, xmlChar *cur, int recovery) {
1.69      daniel   6212:     xmlDocPtr ret;
                   6213:     xmlParserCtxtPtr ctxt;
                   6214: 
                   6215:     if (cur == NULL) return(NULL);
1.16      daniel   6216: 
                   6217: 
1.69      daniel   6218:     ctxt = xmlCreateDocParserCtxt(cur);
                   6219:     if (ctxt == NULL) return(NULL);
1.74      daniel   6220:     if (sax != NULL) { 
                   6221:         ctxt->sax = sax;
                   6222:         ctxt->userData = NULL;
                   6223:     }
1.69      daniel   6224: 
1.16      daniel   6225:     xmlParseDocument(ctxt);
1.72      daniel   6226:     if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
1.59      daniel   6227:     else {
                   6228:        ret = NULL;
1.72      daniel   6229:        xmlFreeDoc(ctxt->myDoc);
                   6230:        ctxt->myDoc = NULL;
1.59      daniel   6231:     }
1.86      daniel   6232:     if (sax != NULL) 
                   6233:        ctxt->sax = NULL;
1.69      daniel   6234:     xmlFreeParserCtxt(ctxt);
1.16      daniel   6235:     
1.1       veillard 6236:     return(ret);
                   6237: }
                   6238: 
1.50      daniel   6239: /**
1.55      daniel   6240:  * xmlParseDoc :
1.123     daniel   6241:  * @cur:  a pointer to an array of xmlChar
1.55      daniel   6242:  *
                   6243:  * parse an XML in-memory document and build a tree.
                   6244:  * 
1.68      daniel   6245:  * Returns the resulting document tree
1.55      daniel   6246:  */
                   6247: 
1.69      daniel   6248: xmlDocPtr
1.123     daniel   6249: xmlParseDoc(xmlChar *cur) {
1.59      daniel   6250:     return(xmlSAXParseDoc(NULL, cur, 0));
1.76      daniel   6251: }
                   6252: 
                   6253: /**
                   6254:  * xmlSAXParseDTD :
                   6255:  * @sax:  the SAX handler block
                   6256:  * @ExternalID:  a NAME* containing the External ID of the DTD
                   6257:  * @SystemID:  a NAME* containing the URL to the DTD
                   6258:  *
                   6259:  * Load and parse an external subset.
                   6260:  * 
                   6261:  * Returns the resulting xmlDtdPtr or NULL in case of error.
                   6262:  */
                   6263: 
                   6264: xmlDtdPtr
1.123     daniel   6265: xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
                   6266:                           const xmlChar *SystemID) {
1.76      daniel   6267:     xmlDtdPtr ret = NULL;
                   6268:     xmlParserCtxtPtr ctxt;
1.83      daniel   6269:     xmlParserInputPtr input = NULL;
1.76      daniel   6270:     xmlCharEncoding enc;
                   6271: 
                   6272:     if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
                   6273: 
1.97      daniel   6274:     ctxt = xmlNewParserCtxt();
1.76      daniel   6275:     if (ctxt == NULL) {
                   6276:        return(NULL);
                   6277:     }
                   6278: 
                   6279:     /*
                   6280:      * Set-up the SAX context
                   6281:      */
                   6282:     if (ctxt == NULL) return(NULL);
                   6283:     if (sax != NULL) { 
1.93      veillard 6284:        if (ctxt->sax != NULL)
1.119     daniel   6285:            xmlFree(ctxt->sax);
1.76      daniel   6286:         ctxt->sax = sax;
                   6287:         ctxt->userData = NULL;
                   6288:     }
                   6289: 
                   6290:     /*
                   6291:      * Ask the Entity resolver to load the damn thing
                   6292:      */
                   6293: 
                   6294:     if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
                   6295:        input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID, SystemID);
                   6296:     if (input == NULL) {
1.86      daniel   6297:         if (sax != NULL) ctxt->sax = NULL;
1.76      daniel   6298:        xmlFreeParserCtxt(ctxt);
                   6299:        return(NULL);
                   6300:     }
                   6301: 
                   6302:     /*
                   6303:      * plug some encoding conversion routines here. !!!
                   6304:      */
                   6305:     xmlPushInput(ctxt, input);
                   6306:     enc = xmlDetectCharEncoding(ctxt->input->cur);
                   6307:     xmlSwitchEncoding(ctxt, enc);
                   6308: 
1.95      veillard 6309:     if (input->filename == NULL)
1.116     daniel   6310:        input->filename = (char *) xmlStrdup(SystemID); /* !!!!!!! */
1.76      daniel   6311:     input->line = 1;
                   6312:     input->col = 1;
                   6313:     input->base = ctxt->input->cur;
                   6314:     input->cur = ctxt->input->cur;
                   6315:     input->free = NULL;
                   6316: 
                   6317:     /*
                   6318:      * let's parse that entity knowing it's an external subset.
                   6319:      */
1.79      daniel   6320:     xmlParseExternalSubset(ctxt, ExternalID, SystemID);
1.76      daniel   6321: 
                   6322:     if (ctxt->myDoc != NULL) {
                   6323:        if (ctxt->wellFormed) {
                   6324:            ret = ctxt->myDoc->intSubset;
                   6325:            ctxt->myDoc->intSubset = NULL;
                   6326:        } else {
                   6327:            ret = NULL;
                   6328:        }
                   6329:         xmlFreeDoc(ctxt->myDoc);
                   6330:         ctxt->myDoc = NULL;
                   6331:     }
1.86      daniel   6332:     if (sax != NULL) ctxt->sax = NULL;
1.76      daniel   6333:     xmlFreeParserCtxt(ctxt);
                   6334:     
                   6335:     return(ret);
                   6336: }
                   6337: 
                   6338: /**
                   6339:  * xmlParseDTD :
                   6340:  * @ExternalID:  a NAME* containing the External ID of the DTD
                   6341:  * @SystemID:  a NAME* containing the URL to the DTD
                   6342:  *
                   6343:  * Load and parse an external subset.
                   6344:  * 
                   6345:  * Returns the resulting xmlDtdPtr or NULL in case of error.
                   6346:  */
                   6347: 
                   6348: xmlDtdPtr
1.123     daniel   6349: xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
1.76      daniel   6350:     return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
1.59      daniel   6351: }
                   6352: 
                   6353: /**
                   6354:  * xmlRecoverDoc :
1.123     daniel   6355:  * @cur:  a pointer to an array of xmlChar
1.59      daniel   6356:  *
                   6357:  * parse an XML in-memory document and build a tree.
                   6358:  * In the case the document is not Well Formed, a tree is built anyway
                   6359:  * 
1.68      daniel   6360:  * Returns the resulting document tree
1.59      daniel   6361:  */
                   6362: 
1.69      daniel   6363: xmlDocPtr
1.123     daniel   6364: xmlRecoverDoc(xmlChar *cur) {
1.59      daniel   6365:     return(xmlSAXParseDoc(NULL, cur, 1));
1.55      daniel   6366: }
                   6367: 
                   6368: /**
1.69      daniel   6369:  * xmlCreateFileParserCtxt :
1.50      daniel   6370:  * @filename:  the filename
                   6371:  *
1.69      daniel   6372:  * Create a parser context for a file content. 
                   6373:  * Automatic support for ZLIB/Compress compressed document is provided
                   6374:  * by default if found at compile-time.
1.50      daniel   6375:  *
1.69      daniel   6376:  * Returns the new parser context or NULL
1.9       httpng   6377:  */
1.69      daniel   6378: xmlParserCtxtPtr
                   6379: xmlCreateFileParserCtxt(const char *filename)
                   6380: {
                   6381:     xmlParserCtxtPtr ctxt;
1.40      daniel   6382:     xmlParserInputPtr inputStream;
1.91      daniel   6383:     xmlParserInputBufferPtr buf;
1.111     daniel   6384:     char *directory = NULL;
1.9       httpng   6385: 
1.91      daniel   6386:     buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
                   6387:     if (buf == NULL) return(NULL);
1.9       httpng   6388: 
1.97      daniel   6389:     ctxt = xmlNewParserCtxt();
1.16      daniel   6390:     if (ctxt == NULL) {
                   6391:        return(NULL);
                   6392:     }
1.97      daniel   6393: 
1.96      daniel   6394:     inputStream = xmlNewInputStream(ctxt);
1.40      daniel   6395:     if (inputStream == NULL) {
1.97      daniel   6396:        xmlFreeParserCtxt(ctxt);
1.40      daniel   6397:        return(NULL);
                   6398:     }
                   6399: 
1.119     daniel   6400:     inputStream->filename = xmlMemStrdup(filename);
1.91      daniel   6401:     inputStream->buf = buf;
                   6402:     inputStream->base = inputStream->buf->buffer->content;
                   6403:     inputStream->cur = inputStream->buf->buffer->content;
1.16      daniel   6404: 
1.40      daniel   6405:     inputPush(ctxt, inputStream);
1.110     daniel   6406:     if ((ctxt->directory == NULL) && (directory == NULL))
1.106     daniel   6407:         directory = xmlParserGetDirectory(filename);
                   6408:     if ((ctxt->directory == NULL) && (directory != NULL))
1.110     daniel   6409:         ctxt->directory = directory;
1.106     daniel   6410: 
1.69      daniel   6411:     return(ctxt);
                   6412: }
                   6413: 
                   6414: /**
                   6415:  * xmlSAXParseFile :
                   6416:  * @sax:  the SAX handler block
                   6417:  * @filename:  the filename
                   6418:  * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
                   6419:  *             documents
                   6420:  *
                   6421:  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
                   6422:  * compressed document is provided by default if found at compile-time.
                   6423:  * It use the given SAX function block to handle the parsing callback.
                   6424:  * If sax is NULL, fallback to the default DOM tree building routines.
                   6425:  *
                   6426:  * Returns the resulting document tree
                   6427:  */
                   6428: 
1.79      daniel   6429: xmlDocPtr
                   6430: xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
1.69      daniel   6431:                           int recovery) {
                   6432:     xmlDocPtr ret;
                   6433:     xmlParserCtxtPtr ctxt;
1.111     daniel   6434:     char *directory = NULL;
1.69      daniel   6435: 
                   6436:     ctxt = xmlCreateFileParserCtxt(filename);
                   6437:     if (ctxt == NULL) return(NULL);
1.74      daniel   6438:     if (sax != NULL) {
1.93      veillard 6439:        if (ctxt->sax != NULL)
1.119     daniel   6440:            xmlFree(ctxt->sax);
1.74      daniel   6441:         ctxt->sax = sax;
                   6442:         ctxt->userData = NULL;
                   6443:     }
1.106     daniel   6444: 
1.110     daniel   6445:     if ((ctxt->directory == NULL) && (directory == NULL))
1.106     daniel   6446:         directory = xmlParserGetDirectory(filename);
                   6447:     if ((ctxt->directory == NULL) && (directory != NULL))
1.123     daniel   6448:         ctxt->directory = (char *) xmlStrdup((xmlChar *) directory); /* !!!!!!! */
1.16      daniel   6449: 
                   6450:     xmlParseDocument(ctxt);
1.40      daniel   6451: 
1.72      daniel   6452:     if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
1.59      daniel   6453:     else {
                   6454:        ret = NULL;
1.72      daniel   6455:        xmlFreeDoc(ctxt->myDoc);
                   6456:        ctxt->myDoc = NULL;
1.59      daniel   6457:     }
1.86      daniel   6458:     if (sax != NULL)
                   6459:         ctxt->sax = NULL;
1.69      daniel   6460:     xmlFreeParserCtxt(ctxt);
1.20      daniel   6461:     
                   6462:     return(ret);
                   6463: }
                   6464: 
1.55      daniel   6465: /**
                   6466:  * xmlParseFile :
                   6467:  * @filename:  the filename
                   6468:  *
                   6469:  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
                   6470:  * compressed document is provided by default if found at compile-time.
                   6471:  *
1.68      daniel   6472:  * Returns the resulting document tree
1.55      daniel   6473:  */
                   6474: 
1.79      daniel   6475: xmlDocPtr
                   6476: xmlParseFile(const char *filename) {
1.59      daniel   6477:     return(xmlSAXParseFile(NULL, filename, 0));
                   6478: }
                   6479: 
                   6480: /**
                   6481:  * xmlRecoverFile :
                   6482:  * @filename:  the filename
                   6483:  *
                   6484:  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
                   6485:  * compressed document is provided by default if found at compile-time.
                   6486:  * In the case the document is not Well Formed, a tree is built anyway
                   6487:  *
1.68      daniel   6488:  * Returns the resulting document tree
1.59      daniel   6489:  */
                   6490: 
1.79      daniel   6491: xmlDocPtr
                   6492: xmlRecoverFile(const char *filename) {
1.59      daniel   6493:     return(xmlSAXParseFile(NULL, filename, 1));
1.55      daniel   6494: }
1.32      daniel   6495: 
1.50      daniel   6496: /**
1.69      daniel   6497:  * xmlCreateMemoryParserCtxt :
1.68      daniel   6498:  * @buffer:  an pointer to a char array
1.127     daniel   6499:  * @size:  the size of the array
1.50      daniel   6500:  *
1.69      daniel   6501:  * Create a parser context for an XML in-memory document.
1.50      daniel   6502:  *
1.69      daniel   6503:  * Returns the new parser context or NULL
1.20      daniel   6504:  */
1.69      daniel   6505: xmlParserCtxtPtr
                   6506: xmlCreateMemoryParserCtxt(char *buffer, int size) {
1.20      daniel   6507:     xmlParserCtxtPtr ctxt;
1.40      daniel   6508:     xmlParserInputPtr input;
1.75      daniel   6509:     xmlCharEncoding enc;
1.40      daniel   6510: 
                   6511:     buffer[size - 1] = '\0';
                   6512: 
1.97      daniel   6513:     ctxt = xmlNewParserCtxt();
1.20      daniel   6514:     if (ctxt == NULL) {
                   6515:        return(NULL);
                   6516:     }
1.97      daniel   6517: 
1.96      daniel   6518:     input = xmlNewInputStream(ctxt);
1.40      daniel   6519:     if (input == NULL) {
1.97      daniel   6520:        xmlFreeParserCtxt(ctxt);
1.40      daniel   6521:        return(NULL);
                   6522:     }
1.20      daniel   6523: 
1.40      daniel   6524:     input->filename = NULL;
                   6525:     input->line = 1;
                   6526:     input->col = 1;
1.96      daniel   6527:     input->buf = NULL;
1.91      daniel   6528:     input->consumed = 0;
1.45      daniel   6529: 
                   6530:     /*
1.75      daniel   6531:      * plug some encoding conversion routines here. !!!
1.45      daniel   6532:      */
1.116     daniel   6533:     enc = xmlDetectCharEncoding(BAD_CAST buffer);
1.75      daniel   6534:     xmlSwitchEncoding(ctxt, enc);
                   6535: 
1.116     daniel   6536:     input->base = BAD_CAST buffer;
                   6537:     input->cur = BAD_CAST buffer;
1.69      daniel   6538:     input->free = NULL;
1.20      daniel   6539: 
1.40      daniel   6540:     inputPush(ctxt, input);
1.69      daniel   6541:     return(ctxt);
                   6542: }
                   6543: 
                   6544: /**
                   6545:  * xmlSAXParseMemory :
                   6546:  * @sax:  the SAX handler block
                   6547:  * @buffer:  an pointer to a char array
1.127     daniel   6548:  * @size:  the size of the array
                   6549:  * @recovery:  work in recovery mode, i.e. tries to read not Well Formed
1.69      daniel   6550:  *             documents
                   6551:  *
                   6552:  * parse an XML in-memory block and use the given SAX function block
                   6553:  * to handle the parsing callback. If sax is NULL, fallback to the default
                   6554:  * DOM tree building routines.
                   6555:  * 
                   6556:  * Returns the resulting document tree
                   6557:  */
                   6558: xmlDocPtr
                   6559: xmlSAXParseMemory(xmlSAXHandlerPtr sax, char *buffer, int size, int recovery) {
                   6560:     xmlDocPtr ret;
                   6561:     xmlParserCtxtPtr ctxt;
                   6562: 
                   6563:     ctxt = xmlCreateMemoryParserCtxt(buffer, size);
                   6564:     if (ctxt == NULL) return(NULL);
1.74      daniel   6565:     if (sax != NULL) {
                   6566:         ctxt->sax = sax;
                   6567:         ctxt->userData = NULL;
                   6568:     }
1.20      daniel   6569: 
                   6570:     xmlParseDocument(ctxt);
1.40      daniel   6571: 
1.72      daniel   6572:     if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
1.59      daniel   6573:     else {
                   6574:        ret = NULL;
1.72      daniel   6575:        xmlFreeDoc(ctxt->myDoc);
                   6576:        ctxt->myDoc = NULL;
1.59      daniel   6577:     }
1.86      daniel   6578:     if (sax != NULL) 
                   6579:        ctxt->sax = NULL;
1.69      daniel   6580:     xmlFreeParserCtxt(ctxt);
1.16      daniel   6581:     
1.9       httpng   6582:     return(ret);
1.17      daniel   6583: }
                   6584: 
1.55      daniel   6585: /**
                   6586:  * xmlParseMemory :
1.68      daniel   6587:  * @buffer:  an pointer to a char array
1.55      daniel   6588:  * @size:  the size of the array
                   6589:  *
                   6590:  * parse an XML in-memory block and build a tree.
                   6591:  * 
1.68      daniel   6592:  * Returns the resulting document tree
1.55      daniel   6593:  */
                   6594: 
                   6595: xmlDocPtr xmlParseMemory(char *buffer, int size) {
1.59      daniel   6596:    return(xmlSAXParseMemory(NULL, buffer, size, 0));
                   6597: }
                   6598: 
                   6599: /**
                   6600:  * xmlRecoverMemory :
1.68      daniel   6601:  * @buffer:  an pointer to a char array
1.59      daniel   6602:  * @size:  the size of the array
                   6603:  *
                   6604:  * parse an XML in-memory block and build a tree.
                   6605:  * In the case the document is not Well Formed, a tree is built anyway
                   6606:  * 
1.68      daniel   6607:  * Returns the resulting document tree
1.59      daniel   6608:  */
                   6609: 
                   6610: xmlDocPtr xmlRecoverMemory(char *buffer, int size) {
                   6611:    return(xmlSAXParseMemory(NULL, buffer, size, 1));
1.17      daniel   6612: }
                   6613: 
                   6614: 
1.50      daniel   6615: /**
                   6616:  * xmlSetupParserForBuffer:
                   6617:  * @ctxt:  an XML parser context
1.123     daniel   6618:  * @buffer:  a xmlChar * buffer
1.50      daniel   6619:  * @filename:  a file name
                   6620:  *
1.19      daniel   6621:  * Setup the parser context to parse a new buffer; Clears any prior
                   6622:  * contents from the parser context. The buffer parameter must not be
                   6623:  * NULL, but the filename parameter can be
                   6624:  */
1.55      daniel   6625: void
1.123     daniel   6626: xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
1.17      daniel   6627:                              const char* filename)
                   6628: {
1.96      daniel   6629:     xmlParserInputPtr input;
1.40      daniel   6630: 
1.96      daniel   6631:     input = xmlNewInputStream(ctxt);
                   6632:     if (input == NULL) {
                   6633:         perror("malloc");
1.119     daniel   6634:         xmlFree(ctxt);
1.96      daniel   6635:         exit(1);
                   6636:     }
                   6637:   
                   6638:     xmlClearParserCtxt(ctxt);
                   6639:     if (filename != NULL)
1.119     daniel   6640:         input->filename = xmlMemStrdup(filename);
1.96      daniel   6641:     input->base = buffer;
                   6642:     input->cur = buffer;
                   6643:     inputPush(ctxt, input);
1.17      daniel   6644: }
                   6645: 
1.123     daniel   6646: /**
                   6647:  * xmlSAXUserParseFile:
                   6648:  * @sax:  a SAX handler
                   6649:  * @user_data:  The user data returned on SAX callbacks
                   6650:  * @filename:  a file name
                   6651:  *
                   6652:  * parse an XML file and call the given SAX handler routines.
                   6653:  * Automatic support for ZLIB/Compress compressed document is provided
                   6654:  * 
                   6655:  * Returns 0 in case of success or a error number otherwise
                   6656:  */
1.131     daniel   6657: int
                   6658: xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
                   6659:                     const char *filename) {
1.123     daniel   6660:     int ret = 0;
                   6661:     xmlParserCtxtPtr ctxt;
                   6662:     
                   6663:     ctxt = xmlCreateFileParserCtxt(filename);
                   6664:     if (ctxt == NULL) return -1;
                   6665:     ctxt->sax = sax;
                   6666:     ctxt->userData = user_data;
                   6667:     
                   6668:     xmlParseDocument(ctxt);
                   6669:     
                   6670:     if (ctxt->wellFormed)
                   6671:        ret = 0;
                   6672:     else {
                   6673:         if (ctxt->errNo != 0)
                   6674:            ret = ctxt->errNo;
                   6675:        else
                   6676:            ret = -1;
                   6677:     }
                   6678:     if (sax != NULL)
                   6679:        ctxt->sax = NULL;
                   6680:     xmlFreeParserCtxt(ctxt);
                   6681:     
                   6682:     return ret;
                   6683: }
                   6684: 
                   6685: /**
                   6686:  * xmlSAXUserParseMemory:
                   6687:  * @sax:  a SAX handler
                   6688:  * @user_data:  The user data returned on SAX callbacks
                   6689:  * @buffer:  an in-memory XML document input
1.127     daniel   6690:  * @size:  the length of the XML document in bytes
1.123     daniel   6691:  *
                   6692:  * A better SAX parsing routine.
                   6693:  * parse an XML in-memory buffer and call the given SAX handler routines.
                   6694:  * 
                   6695:  * Returns 0 in case of success or a error number otherwise
                   6696:  */
                   6697: int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
                   6698:                          char *buffer, int size) {
                   6699:     int ret = 0;
                   6700:     xmlParserCtxtPtr ctxt;
                   6701:     
                   6702:     ctxt = xmlCreateMemoryParserCtxt(buffer, size);
                   6703:     if (ctxt == NULL) return -1;
                   6704:     ctxt->sax = sax;
                   6705:     ctxt->userData = user_data;
                   6706:     
                   6707:     xmlParseDocument(ctxt);
                   6708:     
                   6709:     if (ctxt->wellFormed)
                   6710:        ret = 0;
                   6711:     else {
                   6712:         if (ctxt->errNo != 0)
                   6713:            ret = ctxt->errNo;
                   6714:        else
                   6715:            ret = -1;
                   6716:     }
                   6717:     if (sax != NULL)
                   6718:        ctxt->sax = NULL;
                   6719:     xmlFreeParserCtxt(ctxt);
                   6720:     
                   6721:     return ret;
                   6722: }
                   6723: 
1.32      daniel   6724: 
1.98      daniel   6725: /************************************************************************
                   6726:  *                                                                     *
1.127     daniel   6727:  *                             Miscellaneous                           *
1.98      daniel   6728:  *                                                                     *
                   6729:  ************************************************************************/
                   6730: 
1.132     daniel   6731: /**
                   6732:  * xmlCleanupParser:
                   6733:  *
                   6734:  * Cleanup function for the XML parser. It tries to reclaim all
                   6735:  * parsing related global memory allocated for the parser processing.
                   6736:  * It doesn't deallocate any document related memory. Calling this
                   6737:  * function should not prevent reusing the parser.
                   6738:  */
                   6739: 
                   6740: void
                   6741: xmlCleanupParser(void) {
                   6742:     xmlCleanupCharEncodingHandlers();
1.133   ! daniel   6743:     xmlCleanupPredefinedEntities();
1.132     daniel   6744: }
1.98      daniel   6745: 
1.50      daniel   6746: /**
                   6747:  * xmlParserFindNodeInfo:
                   6748:  * @ctxt:  an XML parser context
                   6749:  * @node:  an XML node within the tree
                   6750:  *
                   6751:  * Find the parser node info struct for a given node
                   6752:  * 
1.68      daniel   6753:  * Returns an xmlParserNodeInfo block pointer or NULL
1.32      daniel   6754:  */
                   6755: const xmlParserNodeInfo* xmlParserFindNodeInfo(const xmlParserCtxt* ctx,
                   6756:                                                const xmlNode* node)
                   6757: {
                   6758:   unsigned long pos;
                   6759: 
                   6760:   /* Find position where node should be at */
                   6761:   pos = xmlParserFindNodeInfoIndex(&ctx->node_seq, node);
                   6762:   if ( ctx->node_seq.buffer[pos].node == node )
                   6763:     return &ctx->node_seq.buffer[pos];
                   6764:   else
                   6765:     return NULL;
                   6766: }
                   6767: 
                   6768: 
1.50      daniel   6769: /**
                   6770:  * xmlInitNodeInfoSeq :
                   6771:  * @seq:  a node info sequence pointer
                   6772:  *
                   6773:  * -- Initialize (set to initial state) node info sequence
1.32      daniel   6774:  */
1.55      daniel   6775: void
                   6776: xmlInitNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
1.32      daniel   6777: {
                   6778:   seq->length = 0;
                   6779:   seq->maximum = 0;
                   6780:   seq->buffer = NULL;
                   6781: }
                   6782: 
1.50      daniel   6783: /**
                   6784:  * xmlClearNodeInfoSeq :
                   6785:  * @seq:  a node info sequence pointer
                   6786:  *
                   6787:  * -- Clear (release memory and reinitialize) node
1.32      daniel   6788:  *   info sequence
                   6789:  */
1.55      daniel   6790: void
                   6791: xmlClearNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
1.32      daniel   6792: {
                   6793:   if ( seq->buffer != NULL )
1.119     daniel   6794:     xmlFree(seq->buffer);
1.32      daniel   6795:   xmlInitNodeInfoSeq(seq);
                   6796: }
                   6797: 
                   6798: 
1.50      daniel   6799: /**
                   6800:  * xmlParserFindNodeInfoIndex:
                   6801:  * @seq:  a node info sequence pointer
                   6802:  * @node:  an XML node pointer
                   6803:  *
                   6804:  * 
1.32      daniel   6805:  * xmlParserFindNodeInfoIndex : Find the index that the info record for
                   6806:  *   the given node is or should be at in a sorted sequence
1.68      daniel   6807:  *
                   6808:  * Returns a long indicating the position of the record
1.32      daniel   6809:  */
                   6810: unsigned long xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeq* seq,
                   6811:                                          const xmlNode* node)
                   6812: {
                   6813:   unsigned long upper, lower, middle;
                   6814:   int found = 0;
                   6815: 
                   6816:   /* Do a binary search for the key */
                   6817:   lower = 1;
                   6818:   upper = seq->length;
                   6819:   middle = 0;
                   6820:   while ( lower <= upper && !found) {
                   6821:     middle = lower + (upper - lower) / 2;
                   6822:     if ( node == seq->buffer[middle - 1].node )
                   6823:       found = 1;
                   6824:     else if ( node < seq->buffer[middle - 1].node )
                   6825:       upper = middle - 1;
                   6826:     else
                   6827:       lower = middle + 1;
                   6828:   }
                   6829: 
                   6830:   /* Return position */
                   6831:   if ( middle == 0 || seq->buffer[middle - 1].node < node )
                   6832:     return middle;
                   6833:   else 
                   6834:     return middle - 1;
                   6835: }
                   6836: 
                   6837: 
1.50      daniel   6838: /**
                   6839:  * xmlParserAddNodeInfo:
                   6840:  * @ctxt:  an XML parser context
1.68      daniel   6841:  * @info:  a node info sequence pointer
1.50      daniel   6842:  *
                   6843:  * Insert node info record into the sorted sequence
1.32      daniel   6844:  */
1.55      daniel   6845: void
                   6846: xmlParserAddNodeInfo(xmlParserCtxtPtr ctxt, 
1.68      daniel   6847:                      const xmlParserNodeInfo* info)
1.32      daniel   6848: {
                   6849:   unsigned long pos;
                   6850:   static unsigned int block_size = 5;
                   6851: 
                   6852:   /* Find pos and check to see if node is already in the sequence */
1.55      daniel   6853:   pos = xmlParserFindNodeInfoIndex(&ctxt->node_seq, info->node);
                   6854:   if ( pos < ctxt->node_seq.length
                   6855:        && ctxt->node_seq.buffer[pos].node == info->node ) {
                   6856:     ctxt->node_seq.buffer[pos] = *info;
1.32      daniel   6857:   }
                   6858: 
                   6859:   /* Otherwise, we need to add new node to buffer */
                   6860:   else {
                   6861:     /* Expand buffer by 5 if needed */
1.55      daniel   6862:     if ( ctxt->node_seq.length + 1 > ctxt->node_seq.maximum ) {
1.32      daniel   6863:       xmlParserNodeInfo* tmp_buffer;
1.55      daniel   6864:       unsigned int byte_size = (sizeof(*ctxt->node_seq.buffer)
                   6865:                                 *(ctxt->node_seq.maximum + block_size));
1.32      daniel   6866: 
1.55      daniel   6867:       if ( ctxt->node_seq.buffer == NULL )
1.119     daniel   6868:         tmp_buffer = (xmlParserNodeInfo*) xmlMalloc(byte_size);
1.32      daniel   6869:       else 
1.119     daniel   6870:         tmp_buffer = (xmlParserNodeInfo*) xmlRealloc(ctxt->node_seq.buffer, byte_size);
1.32      daniel   6871: 
                   6872:       if ( tmp_buffer == NULL ) {
1.55      daniel   6873:         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   6874:            ctxt->sax->error(ctxt->userData, "Out of memory\n");
1.123     daniel   6875:        ctxt->errNo = XML_ERR_NO_MEMORY;
1.32      daniel   6876:         return;
                   6877:       }
1.55      daniel   6878:       ctxt->node_seq.buffer = tmp_buffer;
                   6879:       ctxt->node_seq.maximum += block_size;
1.32      daniel   6880:     }
                   6881: 
                   6882:     /* If position is not at end, move elements out of the way */
1.55      daniel   6883:     if ( pos != ctxt->node_seq.length ) {
1.32      daniel   6884:       unsigned long i;
                   6885: 
1.55      daniel   6886:       for ( i = ctxt->node_seq.length; i > pos; i-- )
                   6887:         ctxt->node_seq.buffer[i] = ctxt->node_seq.buffer[i - 1];
1.32      daniel   6888:     }
                   6889:   
                   6890:     /* Copy element and increase length */
1.55      daniel   6891:     ctxt->node_seq.buffer[pos] = *info;
                   6892:     ctxt->node_seq.length++;
1.32      daniel   6893:   }   
                   6894: }
1.77      daniel   6895: 
1.98      daniel   6896: 
                   6897: /**
                   6898:  * xmlSubstituteEntitiesDefault :
                   6899:  * @val:  int 0 or 1 
                   6900:  *
                   6901:  * Set and return the previous value for default entity support.
                   6902:  * Initially the parser always keep entity references instead of substituting
                   6903:  * entity values in the output. This function has to be used to change the
                   6904:  * default parser behaviour
                   6905:  * SAX::subtituteEntities() has to be used for changing that on a file by
                   6906:  * file basis.
                   6907:  *
                   6908:  * Returns the last value for 0 for no substitution, 1 for substitution.
                   6909:  */
                   6910: 
                   6911: int
                   6912: xmlSubstituteEntitiesDefault(int val) {
                   6913:     int old = xmlSubstituteEntitiesDefaultValue;
                   6914: 
                   6915:     xmlSubstituteEntitiesDefaultValue = val;
                   6916:     return(old);
                   6917: }
1.77      daniel   6918: 

Webmaster