Annotation of XML/parser.c, revision 1.136

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

Webmaster