Annotation of XML/parser.c, revision 1.139

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

Webmaster