Annotation of XML/parser.c, revision 1.84

1.1       veillard    1: /*
1.3       veillard    2:  * parser.c : an XML 1.0 non-verifying parser
1.15      veillard    3:  *
                      4:  * See Copyright for the status of this software.
                      5:  *
1.60      daniel      6:  * Daniel.Veillard@w3.org
1.1       veillard    7:  */
                      8: 
1.26      daniel      9: #ifdef WIN32
                     10: #define HAVE_FCNTL_H
                     11: #include <io.h>
                     12: #else
1.9       httpng     13: #include <config.h>
1.26      daniel     14: #endif
1.1       veillard   15: #include <stdio.h>
                     16: #include <ctype.h>
1.14      veillard   17: #include <string.h> /* for memset() only */
1.50      daniel     18: #include <stdlib.h>
1.9       httpng     19: #include <sys/stat.h>
                     20: #ifdef HAVE_FCNTL_H
                     21: #include <fcntl.h>
                     22: #endif
1.10      httpng     23: #ifdef HAVE_UNISTD_H
                     24: #include <unistd.h>
                     25: #endif
1.20      daniel     26: #ifdef HAVE_ZLIB_H
                     27: #include <zlib.h>
                     28: #endif
1.1       veillard   29: 
1.14      veillard   30: #include "tree.h"
1.1       veillard   31: #include "parser.h"
1.14      veillard   32: #include "entities.h"
1.75      daniel     33: #include "encoding.h"
1.61      daniel     34: #include "valid.h"
1.69      daniel     35: #include "parserInternals.h"
1.1       veillard   36: 
1.45      daniel     37: /************************************************************************
                     38:  *                                                                     *
                     39:  *             Parser stacks related functions and macros              *
                     40:  *                                                                     *
                     41:  ************************************************************************/
1.79      daniel     42: 
                     43: int xmlSubstituteEntitiesDefaultValue = 0;
                     44: 
1.1       veillard   45: /*
1.40      daniel     46:  * Generic function for accessing stacks in the Parser Context
1.1       veillard   47:  */
                     48: 
1.31      daniel     49: #define PUSH_AND_POP(type, name)                                       \
1.72      daniel     50: extern int name##Push(xmlParserCtxtPtr ctxt, type value) {             \
1.31      daniel     51:     if (ctxt->name##Nr >= ctxt->name##Max) {                           \
                     52:        ctxt->name##Max *= 2;                                           \
1.40      daniel     53:         ctxt->name##Tab = (void *) realloc(ctxt->name##Tab,            \
                     54:                     ctxt->name##Max * sizeof(ctxt->name##Tab[0]));     \
                     55:         if (ctxt->name##Tab == NULL) {                                 \
1.31      daniel     56:            fprintf(stderr, "realloc failed !\n");                      \
                     57:            exit(1);                                                    \
                     58:        }                                                               \
                     59:     }                                                                  \
1.40      daniel     60:     ctxt->name##Tab[ctxt->name##Nr] = value;                           \
                     61:     ctxt->name = value;                                                        \
                     62:     return(ctxt->name##Nr++);                                          \
1.31      daniel     63: }                                                                      \
1.72      daniel     64: extern type name##Pop(xmlParserCtxtPtr ctxt) {                         \
1.69      daniel     65:     type ret;                                                          \
1.40      daniel     66:     if (ctxt->name##Nr <= 0) return(0);                                        \
                     67:     ctxt->name##Nr--;                                                  \
1.50      daniel     68:     if (ctxt->name##Nr > 0)                                            \
                     69:        ctxt->name = ctxt->name##Tab[ctxt->name##Nr - 1];               \
                     70:     else                                                               \
                     71:         ctxt->name = NULL;                                             \
1.69      daniel     72:     ret = ctxt->name##Tab[ctxt->name##Nr];                             \
                     73:     ctxt->name##Tab[ctxt->name##Nr] = 0;                               \
                     74:     return(ret);                                                       \
1.31      daniel     75: }                                                                      \
                     76: 
1.40      daniel     77: PUSH_AND_POP(xmlParserInputPtr, input)
1.41      daniel     78: PUSH_AND_POP(xmlNodePtr, node)
1.40      daniel     79: 
1.55      daniel     80: /*
                     81:  * Macros for accessing the content. Those should be used only by the parser,
                     82:  * and not exported.
                     83:  *
                     84:  * Dirty macros, i.e. one need to make assumption on the context to use them
                     85:  *
                     86:  *   CUR_PTR return the current pointer to the CHAR to be parsed.
                     87:  *   CUR     returns the current CHAR value, i.e. a 8 bit value if compiled
                     88:  *           in ISO-Latin or UTF-8, and the current 16 bit value if compiled
                     89:  *           in UNICODE mode. This should be used internally by the parser
                     90:  *           only to compare to ASCII values otherwise it would break when
                     91:  *           running with UTF-8 encoding.
                     92:  *   NXT(n)  returns the n'th next CHAR. Same as CUR is should be used only
                     93:  *           to compare on ASCII based substring.
                     94:  *   SKIP(n) Skip n CHAR, and must also be used only to skip ASCII defined
                     95:  *           strings within the parser.
                     96:  *
1.77      daniel     97:  * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
1.55      daniel     98:  *
                     99:  *   CURRENT Returns the current char value, with the full decoding of
                    100:  *           UTF-8 if we are using this mode. It returns an int.
                    101:  *   NEXT    Skip to the next character, this does the proper decoding
                    102:  *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
                    103:  *           It returns the pointer to the current CHAR.
1.77      daniel    104:  *   COPY(to) copy one char to *to, increment CUR_PTR and to accordingly
1.55      daniel    105:  */
1.45      daniel    106: 
                    107: #define CUR (*ctxt->input->cur)
1.55      daniel    108: #define SKIP(val) ctxt->input->cur += (val)
                    109: #define NXT(val) ctxt->input->cur[(val)]
                    110: #define CUR_PTR ctxt->input->cur
                    111: 
                    112: #define SKIP_BLANKS                                                    \
                    113:     while (IS_BLANK(*(ctxt->input->cur))) NEXT
                    114: 
                    115: #ifndef USE_UTF_8
                    116: #define CURRENT (*ctxt->input->cur)
1.45      daniel    117: #define NEXT ((*ctxt->input->cur) ?                                    \
                    118:                 (((*(ctxt->input->cur) == '\n') ?                      \
                    119:                    (ctxt->input->line++, ctxt->input->col = 1) :       \
                    120:                    (ctxt->input->col++)), ctxt->input->cur++) :        \
                    121:                (xmlPopInput(ctxt), ctxt->input->cur))
1.55      daniel    122: #else
                    123: #endif
1.42      daniel    124: 
1.40      daniel    125: 
1.50      daniel    126: /**
                    127:  * xmlPopInput:
                    128:  * @ctxt:  an XML parser context
                    129:  *
1.40      daniel    130:  * xmlPopInput: the current input pointed by ctxt->input came to an end
                    131:  *          pop it and return the next char.
1.45      daniel    132:  *
                    133:  * TODO A deallocation of the popped Input structure is needed
1.68      daniel    134:  *
                    135:  * Returns the current CHAR in the parser context
1.40      daniel    136:  */
1.55      daniel    137: CHAR
                    138: xmlPopInput(xmlParserCtxtPtr ctxt) {
1.40      daniel    139:     if (ctxt->inputNr == 1) return(0); /* End of main Input */
1.69      daniel    140:     xmlFreeInputStream(inputPop(ctxt));
1.40      daniel    141:     return(CUR);
                    142: }
                    143: 
1.50      daniel    144: /**
                    145:  * xmlPushInput:
                    146:  * @ctxt:  an XML parser context
                    147:  * @input:  an XML parser input fragment (entity, XML fragment ...).
                    148:  *
1.40      daniel    149:  * xmlPushInput: switch to a new input stream which is stacked on top
                    150:  *               of the previous one(s).
                    151:  */
1.55      daniel    152: void
                    153: xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
1.40      daniel    154:     if (input == NULL) return;
                    155:     inputPush(ctxt, input);
                    156: }
                    157: 
1.50      daniel    158: /**
1.69      daniel    159:  * xmlFreeInputStream:
                    160:  * @input:  an xmlParserInputPtr
                    161:  *
                    162:  * Free up an input stream.
                    163:  */
                    164: void
                    165: xmlFreeInputStream(xmlParserInputPtr input) {
                    166:     if (input == NULL) return;
                    167: 
                    168:     if (input->filename != NULL) free((char *) input->filename);
                    169:     if ((input->free != NULL) && (input->base != NULL))
                    170:         input->free((char *) input->base);
                    171:     memset(input, -1, sizeof(xmlParserInput));
                    172:     free(input);
                    173: }
                    174: 
                    175: /**
1.50      daniel    176:  * xmlNewEntityInputStream:
                    177:  * @ctxt:  an XML parser context
                    178:  * @entity:  an Entity pointer
                    179:  *
1.82      daniel    180:  * Create a new input stream based on an xmlEntityPtr
1.68      daniel    181:  * Returns the new input stream
1.45      daniel    182:  */
1.50      daniel    183: xmlParserInputPtr
                    184: xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
1.45      daniel    185:     xmlParserInputPtr input;
                    186: 
                    187:     if (entity == NULL) {
1.55      daniel    188:         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel    189:            ctxt->sax->error(ctxt->userData,
1.45      daniel    190:              "internal: xmlNewEntityInputStream entity = NULL\n");
1.50      daniel    191:        return(NULL);
1.45      daniel    192:     }
                    193:     if (entity->content == NULL) {
1.55      daniel    194:         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel    195:            ctxt->sax->error(ctxt->userData,
1.45      daniel    196:              "internal: xmlNewEntityInputStream entity->input = NULL\n");
1.50      daniel    197:        return(NULL);
1.45      daniel    198:     }
                    199:     input = (xmlParserInputPtr) malloc(sizeof(xmlParserInput));
                    200:     if (input == NULL) {
1.55      daniel    201:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel    202:            ctxt->sax->error(ctxt->userData, "malloc: couldn't allocate a new input stream\n");
1.50      daniel    203:        return(NULL);
1.45      daniel    204:     }
                    205:     input->filename = entity->SystemID; /* TODO !!! char <- CHAR */
                    206:     input->base = entity->content;
                    207:     input->cur = entity->content;
                    208:     input->line = 1;
                    209:     input->col = 1;
1.69      daniel    210:     input->free = NULL;
1.50      daniel    211:     return(input);
1.45      daniel    212: }
                    213: 
1.59      daniel    214: /**
                    215:  * xmlNewStringInputStream:
                    216:  * @ctxt:  an XML parser context
1.82      daniel    217:  * @entity:  an Entity memory buffer
1.59      daniel    218:  *
                    219:  * Create a new input stream based on a memory buffer.
1.68      daniel    220:  * Returns the new input stream
1.59      daniel    221:  */
                    222: xmlParserInputPtr
1.82      daniel    223: xmlNewStringInputStream(xmlParserCtxtPtr ctxt, CHAR *entity) {
1.59      daniel    224:     xmlParserInputPtr input;
                    225: 
1.82      daniel    226:     if (entity == NULL) {
1.59      daniel    227:         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel    228:            ctxt->sax->error(ctxt->userData,
1.59      daniel    229:              "internal: xmlNewStringInputStream string = NULL\n");
                    230:        return(NULL);
                    231:     }
                    232:     input = (xmlParserInputPtr) malloc(sizeof(xmlParserInput));
                    233:     if (input == NULL) {
                    234:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel    235:            ctxt->sax->error(ctxt->userData, "malloc: couldn't allocate a new input stream\n");
1.59      daniel    236:        return(NULL);
                    237:     }
                    238:     input->filename = NULL;
1.82      daniel    239:     input->base = entity;
                    240:     input->cur = entity;
1.59      daniel    241:     input->line = 1;
                    242:     input->col = 1;
1.69      daniel    243:     input->free = NULL;
1.59      daniel    244:     return(input);
                    245: }
                    246: 
1.76      daniel    247: /**
                    248:  * xmlNewInputFromFile:
                    249:  * @ctxt:  an XML parser context
                    250:  * @filename:  the filename to use as entity
                    251:  *
                    252:  * Create a new input stream based on a file.
                    253:  *
                    254:  * Returns the new input stream or NULL in case of error
                    255:  */
                    256: xmlParserInputPtr
1.79      daniel    257: xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) {
1.76      daniel    258: #ifdef HAVE_ZLIB_H
                    259:     gzFile input;
                    260: #else
                    261:     int input;
                    262: #endif
                    263:     int res;
                    264:     int len;
                    265:     struct stat buf;
                    266:     char *buffer;
                    267:     xmlParserInputPtr inputStream;
1.77      daniel    268:     /* xmlCharEncoding enc; */
1.76      daniel    269: 
                    270:     res = stat(filename, &buf);
                    271:     if (res < 0) return(NULL);
                    272: 
                    273: #ifdef HAVE_ZLIB_H
                    274:     len = (buf.st_size * 8) + 1000;
                    275: retry_bigger:
                    276:     buffer = malloc(len);
                    277: #else
                    278:     len = buf.st_size + 100;
                    279:     buffer = malloc(len);
                    280: #endif
                    281:     if (buffer == NULL) {
                    282:        perror("malloc");
                    283:         return(NULL);
                    284:     }
                    285: 
                    286:     memset(buffer, 0, len);
                    287: #ifdef HAVE_ZLIB_H
                    288:     input = gzopen (filename, "r");
                    289:     if (input == NULL) {
                    290:         fprintf (stderr, "Cannot read file %s :\n", filename);
                    291:        perror ("gzopen failed");
                    292:        return(NULL);
                    293:     }
                    294: #else
                    295: #ifdef WIN32
                    296:     input = _open (filename, O_RDONLY | _O_BINARY);
                    297: #else
                    298:     input = open (filename, O_RDONLY);
                    299: #endif
                    300:     if (input < 0) {
                    301:         fprintf (stderr, "Cannot read file %s :\n", filename);
                    302:        perror ("open failed");
                    303:        return(NULL);
                    304:     }
                    305: #endif
                    306: #ifdef HAVE_ZLIB_H
                    307:     res = gzread(input, buffer, len);
                    308: #else
                    309:     res = read(input, buffer, buf.st_size);
                    310: #endif
                    311:     if (res < 0) {
                    312:         fprintf (stderr, "Cannot read file %s :\n", filename);
                    313: #ifdef HAVE_ZLIB_H
                    314:        perror ("gzread failed");
                    315: #else
                    316:        perror ("read failed");
                    317: #endif
                    318:        return(NULL);
                    319:     }
                    320: #ifdef HAVE_ZLIB_H
                    321:     gzclose(input);
                    322:     if (res >= len) {
                    323:         free(buffer);
                    324:        len *= 2;
                    325:        goto retry_bigger;
                    326:     }
                    327:     buf.st_size = res;
                    328: #else
                    329:     close(input);
                    330: #endif
                    331: 
                    332:     buffer[buf.st_size] = '\0';
                    333: 
                    334:     inputStream = (xmlParserInputPtr) malloc(sizeof(xmlParserInput));
                    335:     if (inputStream == NULL) {
                    336:         perror("malloc");
                    337:        free(ctxt);
                    338:        return(NULL);
                    339:     }
                    340: 
                    341:     inputStream->filename = strdup(filename);
                    342:     inputStream->line = 1;
                    343:     inputStream->col = 1;
                    344: 
                    345:     /*
                    346:      * plug some encoding conversion routines here. !!!
                    347:     enc = xmlDetectCharEncoding(buffer);
                    348:     xmlSwitchEncoding(ctxt, enc);
                    349:      */
                    350: 
                    351:     inputStream->base = buffer;
                    352:     inputStream->cur = buffer;
                    353:     inputStream->free = (xmlParserInputDeallocate) free;
                    354: 
                    355:     return(inputStream);
                    356: }
                    357: 
1.77      daniel    358: /************************************************************************
                    359:  *                                                                     *
                    360:  *             Commodity functions to handle entities                  *
                    361:  *                                                                     *
                    362:  ************************************************************************/
                    363: 
                    364: /*
                    365:  * Macro used to grow the current buffer.
                    366:  */
1.78      daniel    367: #define growBuffer(buffer) {                                           \
                    368:     buffer##_size *= 2;                                                        \
                    369:     buffer = (CHAR *) realloc(buffer, buffer##_size * sizeof(CHAR));   \
1.77      daniel    370:     if (buffer == NULL) {                                              \
                    371:        perror("realloc failed");                                       \
                    372:        exit(1);                                                        \
                    373:     }                                                                  \
                    374: }
                    375: 
                    376: 
                    377: /**
                    378:  * xmlDecodeEntities:
                    379:  * @ctxt:  the parser context
                    380:  * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
                    381:  * @len:  the len to decode (in bytes !), -1 for no size limit
                    382:  * @end:  an end marker CHAR, 0 if none
                    383:  * @end2:  an end marker CHAR, 0 if none
                    384:  * @end3:  an end marker CHAR, 0 if none
                    385:  * 
                    386:  * [67] Reference ::= EntityRef | CharRef
                    387:  *
                    388:  * [69] PEReference ::= '%' Name ';'
                    389:  *
                    390:  * Returns A newly allocated string with the substitution done. The caller
                    391:  *      must deallocate it !
                    392:  */
                    393: CHAR *
                    394: xmlDecodeEntities(xmlParserCtxtPtr ctxt, int len, int what,
                    395:                   CHAR end, CHAR  end2, CHAR end3) {
                    396:     CHAR *buffer = NULL;
1.78      daniel    397:     int buffer_size = 0;
1.77      daniel    398:     CHAR *out = NULL;
1.78      daniel    399: 
1.77      daniel    400:     CHAR *cur = NULL;
                    401:     xmlEntityPtr ent;
                    402:     const CHAR *start = CUR_PTR;
                    403:     unsigned int max = (unsigned int) len;
                    404: 
                    405:     /*
                    406:      * allocate a translation buffer.
                    407:      */
                    408:     buffer_size = 1000;
                    409:     buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
                    410:     if (buffer == NULL) {
                    411:        perror("xmlDecodeEntities: malloc failed");
                    412:        return(NULL);
                    413:     }
                    414:     out = buffer;
                    415: 
1.78      daniel    416:     /*
                    417:      * Ok loop until we reach one of the ending char or a size limit.
                    418:      */
1.77      daniel    419:     while ((CUR_PTR - start < max) && (CUR != end) &&
                    420:            (CUR != end2) && (CUR != end3)) {
                    421: 
                    422:         if (CUR == '&' && (what & XML_SUBSTITUTE_REF)) {
                    423:            if (NXT(1) == '#') {
                    424:                int val = xmlParseCharRef(ctxt);
                    425:                /* TODO: invalid for UTF-8 variable encoding !!! */
                    426:                *out++ = val;
                    427:            } else {
                    428:                ent = xmlParseEntityRef(ctxt);
                    429:                if (ent != NULL) {
                    430:                    cur = ent->content;
                    431:                    while (*cur != 0) {
                    432:                        *out++ = *cur++;
                    433:                        if (out - buffer > buffer_size - 100) {
                    434:                            int index = out - buffer;
                    435: 
1.78      daniel    436:                            growBuffer(buffer);
1.77      daniel    437:                            out = &buffer[index];
                    438:                        }
                    439:                    }
                    440:                }
                    441:            }
                    442:        } else if (CUR == '%' && (what & XML_SUBSTITUTE_PEREF)) {
                    443:            /*
                    444:             * a PEReference induce to switch the entity flow,
                    445:             * we break here to flush the current set of chars
                    446:             * parsed if any. We will be called back later.
                    447:             */
                    448:            if (CUR_PTR != start) break;
                    449: 
                    450:            xmlParsePEReference(ctxt);
1.79      daniel    451: 
                    452:            /*
                    453:             * Pop-up of finished entities.
                    454:             */
                    455:            while ((CUR == 0) && (ctxt->inputNr > 1))
                    456:                xmlPopInput(ctxt);
                    457: 
1.78      daniel    458:             break;
1.77      daniel    459:        } else {
                    460:            /*  TODO: invalid for UTF-8 , use COPY(out); */
                    461:            *out++ = CUR;
                    462:            NEXT;
                    463:        }
                    464:     }
                    465:     *out++ = 0;
                    466:     return(buffer);
                    467: }
                    468: 
1.1       veillard  469: 
1.28      daniel    470: /************************************************************************
                    471:  *                                                                     *
1.75      daniel    472:  *             Commodity functions to handle encodings                 *
                    473:  *                                                                     *
                    474:  ************************************************************************/
                    475: 
                    476: /**
                    477:  * xmlSwitchEncoding:
                    478:  * @ctxt:  the parser context
                    479:  * @len:  the len of @cur
                    480:  *
                    481:  * change the input functions when discovering the character encoding
                    482:  * of a given entity.
                    483:  *
                    484:  */
                    485: void
                    486: xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
                    487: {
                    488:     switch (enc) {
                    489:         case XML_CHAR_ENCODING_ERROR:
                    490:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    491:                ctxt->sax->error(ctxt->userData, "encoding unknown\n");
                    492:            ctxt->wellFormed = 0;
                    493:             break;
                    494:         case XML_CHAR_ENCODING_NONE:
                    495:            /* let's assume it's UTF-8 without the XML decl */
                    496:             return;
                    497:         case XML_CHAR_ENCODING_UTF8:
                    498:            /* default encoding, no conversion should be needed */
                    499:             return;
                    500:         case XML_CHAR_ENCODING_UTF16LE:
                    501:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    502:                 ctxt->sax->error(ctxt->userData,
                    503:                  "char encoding UTF16 little endian not supported\n");
                    504:             break;
                    505:         case XML_CHAR_ENCODING_UTF16BE:
                    506:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    507:                 ctxt->sax->error(ctxt->userData,
                    508:                  "char encoding UTF16 big endian not supported\n");
                    509:             break;
                    510:         case XML_CHAR_ENCODING_UCS4LE:
                    511:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    512:                 ctxt->sax->error(ctxt->userData,
                    513:                  "char encoding USC4 little endian not supported\n");
                    514:             break;
                    515:         case XML_CHAR_ENCODING_UCS4BE:
                    516:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    517:                 ctxt->sax->error(ctxt->userData,
                    518:                  "char encoding USC4 big endian not supported\n");
                    519:             break;
                    520:         case XML_CHAR_ENCODING_EBCDIC:
                    521:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    522:                 ctxt->sax->error(ctxt->userData,
                    523:                  "char encoding EBCDIC not supported\n");
                    524:             break;
                    525:         case XML_CHAR_ENCODING_UCS4_2143:
                    526:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    527:                 ctxt->sax->error(ctxt->userData,
                    528:                  "char encoding UCS4 2143 not supported\n");
                    529:             break;
                    530:         case XML_CHAR_ENCODING_UCS4_3412:
                    531:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    532:                 ctxt->sax->error(ctxt->userData,
                    533:                  "char encoding UCS4 3412 not supported\n");
                    534:             break;
                    535:         case XML_CHAR_ENCODING_UCS2:
                    536:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    537:                 ctxt->sax->error(ctxt->userData,
                    538:                  "char encoding UCS2 not supported\n");
                    539:             break;
                    540:         case XML_CHAR_ENCODING_8859_1:
                    541:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    542:                 ctxt->sax->error(ctxt->userData,
                    543:                  "char encoding ISO_8859_1 ISO Latin 1 not supported\n");
                    544:             break;
                    545:         case XML_CHAR_ENCODING_8859_2:
                    546:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    547:                 ctxt->sax->error(ctxt->userData,
                    548:                  "char encoding ISO_8859_2 ISO Latin 2 not supported\n");
                    549:             break;
                    550:         case XML_CHAR_ENCODING_8859_3:
                    551:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    552:                 ctxt->sax->error(ctxt->userData,
                    553:                  "char encoding ISO_8859_3 not supported\n");
                    554:             break;
                    555:         case XML_CHAR_ENCODING_8859_4:
                    556:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    557:                 ctxt->sax->error(ctxt->userData,
                    558:                  "char encoding ISO_8859_4 not supported\n");
                    559:             break;
                    560:         case XML_CHAR_ENCODING_8859_5:
                    561:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    562:                 ctxt->sax->error(ctxt->userData,
                    563:                  "char encoding ISO_8859_5 not supported\n");
                    564:             break;
                    565:         case XML_CHAR_ENCODING_8859_6:
                    566:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    567:                 ctxt->sax->error(ctxt->userData,
                    568:                  "char encoding ISO_8859_6 not supported\n");
                    569:             break;
                    570:         case XML_CHAR_ENCODING_8859_7:
                    571:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    572:                 ctxt->sax->error(ctxt->userData,
                    573:                  "char encoding ISO_8859_7 not supported\n");
                    574:             break;
                    575:         case XML_CHAR_ENCODING_8859_8:
                    576:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    577:                 ctxt->sax->error(ctxt->userData,
                    578:                  "char encoding ISO_8859_8 not supported\n");
                    579:             break;
                    580:         case XML_CHAR_ENCODING_8859_9:
                    581:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    582:                 ctxt->sax->error(ctxt->userData,
                    583:                  "char encoding ISO_8859_9 not supported\n");
                    584:             break;
                    585:         case XML_CHAR_ENCODING_2022_JP:
                    586:             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    587:                 ctxt->sax->error(ctxt->userData,
                    588:                   "char encoding ISO-2022-JPnot supported\n");
                    589:             break;
                    590:         case XML_CHAR_ENCODING_SHIFT_JIS:
                    591:             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    592:                 ctxt->sax->error(ctxt->userData,
                    593:                   "char encoding Shift_JISnot supported\n");
                    594:             break;
                    595:         case XML_CHAR_ENCODING_EUC_JP:
                    596:             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                    597:                 ctxt->sax->error(ctxt->userData,
                    598:                   "char encoding EUC-JPnot supported\n");
                    599:             break;
                    600:     }
                    601: }
                    602: 
                    603: /************************************************************************
                    604:  *                                                                     *
1.28      daniel    605:  *             Commodity functions to handle CHARs                     *
                    606:  *                                                                     *
                    607:  ************************************************************************/
                    608: 
1.50      daniel    609: /**
                    610:  * xmlStrndup:
                    611:  * @cur:  the input CHAR *
                    612:  * @len:  the len of @cur
                    613:  *
                    614:  * a strndup for array of CHAR's
1.68      daniel    615:  *
                    616:  * Returns a new CHAR * or NULL
1.1       veillard  617:  */
1.55      daniel    618: CHAR *
                    619: xmlStrndup(const CHAR *cur, int len) {
1.1       veillard  620:     CHAR *ret = malloc((len + 1) * sizeof(CHAR));
                    621: 
                    622:     if (ret == NULL) {
                    623:         fprintf(stderr, "malloc of %d byte failed\n",
                    624:                (len + 1) * sizeof(CHAR));
                    625:         return(NULL);
                    626:     }
                    627:     memcpy(ret, cur, len * sizeof(CHAR));
                    628:     ret[len] = 0;
                    629:     return(ret);
                    630: }
                    631: 
1.50      daniel    632: /**
                    633:  * xmlStrdup:
                    634:  * @cur:  the input CHAR *
                    635:  *
                    636:  * a strdup for array of CHAR's
1.68      daniel    637:  *
                    638:  * Returns a new CHAR * or NULL
1.1       veillard  639:  */
1.55      daniel    640: CHAR *
                    641: xmlStrdup(const CHAR *cur) {
1.6       httpng    642:     const CHAR *p = cur;
1.1       veillard  643: 
                    644:     while (IS_CHAR(*p)) p++;
                    645:     return(xmlStrndup(cur, p - cur));
                    646: }
                    647: 
1.50      daniel    648: /**
                    649:  * xmlCharStrndup:
                    650:  * @cur:  the input char *
                    651:  * @len:  the len of @cur
                    652:  *
                    653:  * a strndup for char's to CHAR's
1.68      daniel    654:  *
                    655:  * Returns a new CHAR * or NULL
1.45      daniel    656:  */
                    657: 
1.55      daniel    658: CHAR *
                    659: xmlCharStrndup(const char *cur, int len) {
1.45      daniel    660:     int i;
                    661:     CHAR *ret = malloc((len + 1) * sizeof(CHAR));
                    662: 
                    663:     if (ret == NULL) {
                    664:         fprintf(stderr, "malloc of %d byte failed\n",
                    665:                (len + 1) * sizeof(CHAR));
                    666:         return(NULL);
                    667:     }
                    668:     for (i = 0;i < len;i++)
                    669:         ret[i] = (CHAR) cur[i];
                    670:     ret[len] = 0;
                    671:     return(ret);
                    672: }
                    673: 
1.50      daniel    674: /**
                    675:  * xmlCharStrdup:
                    676:  * @cur:  the input char *
                    677:  * @len:  the len of @cur
                    678:  *
                    679:  * a strdup for char's to CHAR's
1.68      daniel    680:  *
                    681:  * Returns a new CHAR * or NULL
1.45      daniel    682:  */
                    683: 
1.55      daniel    684: CHAR *
                    685: xmlCharStrdup(const char *cur) {
1.45      daniel    686:     const char *p = cur;
                    687: 
                    688:     while (*p != '\0') p++;
                    689:     return(xmlCharStrndup(cur, p - cur));
                    690: }
                    691: 
1.50      daniel    692: /**
                    693:  * xmlStrcmp:
                    694:  * @str1:  the first CHAR *
                    695:  * @str2:  the second CHAR *
                    696:  *
                    697:  * a strcmp for CHAR's
1.68      daniel    698:  *
                    699:  * Returns the integer result of the comparison
1.14      veillard  700:  */
                    701: 
1.55      daniel    702: int
                    703: xmlStrcmp(const CHAR *str1, const CHAR *str2) {
1.14      veillard  704:     register int tmp;
                    705: 
                    706:     do {
                    707:         tmp = *str1++ - *str2++;
                    708:        if (tmp != 0) return(tmp);
                    709:     } while ((*str1 != 0) && (*str2 != 0));
                    710:     return (*str1 - *str2);
                    711: }
                    712: 
1.50      daniel    713: /**
                    714:  * xmlStrncmp:
                    715:  * @str1:  the first CHAR *
                    716:  * @str2:  the second CHAR *
                    717:  * @len:  the max comparison length
                    718:  *
                    719:  * a strncmp for CHAR's
1.68      daniel    720:  *
                    721:  * Returns the integer result of the comparison
1.14      veillard  722:  */
                    723: 
1.55      daniel    724: int
                    725: xmlStrncmp(const CHAR *str1, const CHAR *str2, int len) {
1.14      veillard  726:     register int tmp;
                    727: 
                    728:     if (len <= 0) return(0);
                    729:     do {
                    730:         tmp = *str1++ - *str2++;
                    731:        if (tmp != 0) return(tmp);
                    732:        len--;
                    733:         if (len <= 0) return(0);
                    734:     } while ((*str1 != 0) && (*str2 != 0));
                    735:     return (*str1 - *str2);
                    736: }
                    737: 
1.50      daniel    738: /**
                    739:  * xmlStrchr:
                    740:  * @str:  the CHAR * array
                    741:  * @val:  the CHAR to search
                    742:  *
                    743:  * a strchr for CHAR's
1.68      daniel    744:  *
                    745:  * Returns the CHAR * for the first occurence or NULL.
1.14      veillard  746:  */
                    747: 
1.55      daniel    748: CHAR *
                    749: xmlStrchr(const CHAR *str, CHAR val) {
1.14      veillard  750:     while (*str != 0) {
                    751:         if (*str == val) return((CHAR *) str);
                    752:        str++;
                    753:     }
                    754:     return(NULL);
                    755: }
1.28      daniel    756: 
1.50      daniel    757: /**
                    758:  * xmlStrlen:
                    759:  * @str:  the CHAR * array
                    760:  *
                    761:  * lenght of a CHAR's string
1.68      daniel    762:  *
                    763:  * Returns the number of CHAR contained in the ARRAY.
1.45      daniel    764:  */
                    765: 
1.55      daniel    766: int
                    767: xmlStrlen(const CHAR *str) {
1.45      daniel    768:     int len = 0;
                    769: 
                    770:     if (str == NULL) return(0);
                    771:     while (*str != 0) {
                    772:        str++;
                    773:        len++;
                    774:     }
                    775:     return(len);
                    776: }
                    777: 
1.50      daniel    778: /**
                    779:  * xmlStrncat:
1.68      daniel    780:  * @cur:  the original CHAR * array
1.50      daniel    781:  * @add:  the CHAR * array added
                    782:  * @len:  the length of @add
                    783:  *
                    784:  * a strncat for array of CHAR's
1.68      daniel    785:  *
                    786:  * Returns a new CHAR * containing the concatenated string.
1.45      daniel    787:  */
                    788: 
1.55      daniel    789: CHAR *
                    790: xmlStrncat(CHAR *cur, const CHAR *add, int len) {
1.45      daniel    791:     int size;
                    792:     CHAR *ret;
                    793: 
                    794:     if ((add == NULL) || (len == 0))
                    795:         return(cur);
                    796:     if (cur == NULL)
                    797:         return(xmlStrndup(add, len));
                    798: 
                    799:     size = xmlStrlen(cur);
                    800:     ret = realloc(cur, (size + len + 1) * sizeof(CHAR));
                    801:     if (ret == NULL) {
                    802:         fprintf(stderr, "xmlStrncat: realloc of %d byte failed\n",
                    803:                (size + len + 1) * sizeof(CHAR));
                    804:         return(cur);
                    805:     }
                    806:     memcpy(&ret[size], add, len * sizeof(CHAR));
                    807:     ret[size + len] = 0;
                    808:     return(ret);
                    809: }
                    810: 
1.50      daniel    811: /**
                    812:  * xmlStrcat:
1.68      daniel    813:  * @cur:  the original CHAR * array
1.50      daniel    814:  * @add:  the CHAR * array added
                    815:  *
                    816:  * a strcat for array of CHAR's
1.68      daniel    817:  *
                    818:  * Returns a new CHAR * containing the concatenated string.
1.45      daniel    819:  */
1.55      daniel    820: CHAR *
                    821: xmlStrcat(CHAR *cur, const CHAR *add) {
1.45      daniel    822:     const CHAR *p = add;
                    823: 
                    824:     if (add == NULL) return(cur);
                    825:     if (cur == NULL) 
                    826:         return(xmlStrdup(add));
                    827: 
                    828:     while (IS_CHAR(*p)) p++;
                    829:     return(xmlStrncat(cur, add, p - add));
                    830: }
                    831: 
                    832: /************************************************************************
                    833:  *                                                                     *
                    834:  *             Commodity functions, cleanup needed ?                   *
                    835:  *                                                                     *
                    836:  ************************************************************************/
                    837: 
1.50      daniel    838: /**
                    839:  * areBlanks:
                    840:  * @ctxt:  an XML parser context
                    841:  * @str:  a CHAR *
                    842:  * @len:  the size of @str
                    843:  *
1.45      daniel    844:  * Is this a sequence of blank chars that one can ignore ?
1.50      daniel    845:  *
                    846:  * TODO: to be corrected accodingly to DTD information if available
1.68      daniel    847:  *
                    848:  * Returns 1 if ignorable 0 otherwise.
1.45      daniel    849:  */
                    850: 
                    851: static int areBlanks(xmlParserCtxtPtr ctxt, const CHAR *str, int len) {
                    852:     int i;
                    853:     xmlNodePtr lastChild;
                    854: 
                    855:     for (i = 0;i < len;i++)
                    856:         if (!(IS_BLANK(str[i]))) return(0);
                    857: 
                    858:     if (CUR != '<') return(0);
1.72      daniel    859:     if (ctxt->node == NULL) return(0);
1.45      daniel    860:     lastChild = xmlGetLastChild(ctxt->node);
                    861:     if (lastChild == NULL) {
                    862:         if (ctxt->node->content != NULL) return(0);
                    863:     } else if (xmlNodeIsText(lastChild))
                    864:         return(0);
                    865:     return(1);
                    866: }
                    867: 
1.50      daniel    868: /**
                    869:  * xmlHandleEntity:
                    870:  * @ctxt:  an XML parser context
                    871:  * @entity:  an XML entity pointer.
                    872:  *
                    873:  * Default handling of defined entities, when should we define a new input
1.45      daniel    874:  * stream ? When do we just handle that as a set of chars ?
1.50      daniel    875:  * TODO: we should call the SAX handler here and have it resolve the issue
1.45      daniel    876:  */
                    877: 
1.55      daniel    878: void
                    879: xmlHandleEntity(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
1.45      daniel    880:     int len;
1.50      daniel    881:     xmlParserInputPtr input;
1.45      daniel    882: 
                    883:     if (entity->content == NULL) {
1.55      daniel    884:         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel    885:            ctxt->sax->error(ctxt->userData, "xmlHandleEntity %s: content == NULL\n",
1.45      daniel    886:                       entity->name);
1.59      daniel    887:        ctxt->wellFormed = 0;
1.45      daniel    888:         return;
                    889:     }
                    890:     len = xmlStrlen(entity->content);
                    891:     if (len <= 2) goto handle_as_char;
                    892: 
                    893:     /*
                    894:      * Redefine its content as an input stream.
                    895:      */
1.50      daniel    896:     input = xmlNewEntityInputStream(ctxt, entity);
                    897:     xmlPushInput(ctxt, input);
1.45      daniel    898:     return;
                    899: 
                    900: handle_as_char:
                    901:     /*
                    902:      * Just handle the content as a set of chars.
                    903:      */
1.72      daniel    904:     if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
1.74      daniel    905:        ctxt->sax->characters(ctxt->userData, entity->content, len);
1.45      daniel    906: 
                    907: }
                    908: 
                    909: /*
                    910:  * Forward definition for recusive behaviour.
                    911:  */
1.77      daniel    912: void xmlParsePEReference(xmlParserCtxtPtr ctxt);
                    913: void xmlParseReference(xmlParserCtxtPtr ctxt);
1.45      daniel    914: 
1.28      daniel    915: /************************************************************************
                    916:  *                                                                     *
                    917:  *             Extra stuff for namespace support                       *
                    918:  *     Relates to http://www.w3.org/TR/WD-xml-names                    *
                    919:  *                                                                     *
                    920:  ************************************************************************/
                    921: 
1.50      daniel    922: /**
                    923:  * xmlNamespaceParseNCName:
                    924:  * @ctxt:  an XML parser context
                    925:  *
                    926:  * parse an XML namespace name.
1.28      daniel    927:  *
                    928:  * [NS 3] NCName ::= (Letter | '_') (NCNameChar)*
                    929:  *
                    930:  * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
                    931:  *                       CombiningChar | Extender
1.68      daniel    932:  *
                    933:  * Returns the namespace name or NULL
1.28      daniel    934:  */
                    935: 
1.55      daniel    936: CHAR *
                    937: xmlNamespaceParseNCName(xmlParserCtxtPtr ctxt) {
1.28      daniel    938:     const CHAR *q;
                    939:     CHAR *ret = NULL;
                    940: 
1.40      daniel    941:     if (!IS_LETTER(CUR) && (CUR != '_')) return(NULL);
                    942:     q = NEXT;
1.28      daniel    943: 
1.40      daniel    944:     while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
                    945:            (CUR == '.') || (CUR == '-') ||
                    946:           (CUR == '_') ||
                    947:           (IS_COMBINING(CUR)) ||
                    948:           (IS_EXTENDER(CUR)))
                    949:        NEXT;
1.28      daniel    950:     
1.40      daniel    951:     ret = xmlStrndup(q, CUR_PTR - q);
1.28      daniel    952: 
                    953:     return(ret);
                    954: }
                    955: 
1.50      daniel    956: /**
                    957:  * xmlNamespaceParseQName:
                    958:  * @ctxt:  an XML parser context
                    959:  * @prefix:  a CHAR ** 
                    960:  *
                    961:  * parse an XML qualified name
1.28      daniel    962:  *
                    963:  * [NS 5] QName ::= (Prefix ':')? LocalPart
                    964:  *
                    965:  * [NS 6] Prefix ::= NCName
                    966:  *
                    967:  * [NS 7] LocalPart ::= NCName
1.68      daniel    968:  *
                    969:  * Returns the function returns the local part, and prefix is updated
1.50      daniel    970:  *   to get the Prefix if any.
1.28      daniel    971:  */
                    972: 
1.55      daniel    973: CHAR *
                    974: xmlNamespaceParseQName(xmlParserCtxtPtr ctxt, CHAR **prefix) {
1.28      daniel    975:     CHAR *ret = NULL;
                    976: 
                    977:     *prefix = NULL;
                    978:     ret = xmlNamespaceParseNCName(ctxt);
1.40      daniel    979:     if (CUR == ':') {
1.28      daniel    980:         *prefix = ret;
1.40      daniel    981:        NEXT;
1.28      daniel    982:        ret = xmlNamespaceParseNCName(ctxt);
                    983:     }
                    984: 
                    985:     return(ret);
                    986: }
                    987: 
1.50      daniel    988: /**
1.72      daniel    989:  * xmlSplitQName:
                    990:  * @name:  an XML parser context
                    991:  * @prefix:  a CHAR ** 
                    992:  *
                    993:  * parse an XML qualified name string
                    994:  *
                    995:  * [NS 5] QName ::= (Prefix ':')? LocalPart
                    996:  *
                    997:  * [NS 6] Prefix ::= NCName
                    998:  *
                    999:  * [NS 7] LocalPart ::= NCName
                   1000:  *
                   1001:  * Returns the function returns the local part, and prefix is updated
                   1002:  *   to get the Prefix if any.
                   1003:  */
                   1004: 
                   1005: CHAR *
                   1006: xmlSplitQName(const CHAR *name, CHAR **prefix) {
                   1007:     CHAR *ret = NULL;
                   1008:     const CHAR *q;
                   1009:     const CHAR *cur = name;
                   1010: 
                   1011:     *prefix = NULL;
                   1012:     if (!IS_LETTER(*cur) && (*cur != '_')) return(NULL);
                   1013:     q = cur++;
                   1014: 
                   1015:     while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
                   1016:            (*cur == '.') || (*cur == '-') ||
                   1017:           (*cur == '_') ||
                   1018:           (IS_COMBINING(*cur)) ||
                   1019:           (IS_EXTENDER(*cur)))
                   1020:        cur++;
                   1021:     
                   1022:     ret = xmlStrndup(q, cur - q);
                   1023: 
                   1024:     if (*cur == ':') {
                   1025:        cur++;
                   1026:        if (!IS_LETTER(*cur) && (*cur != '_')) return(ret);
                   1027:         *prefix = ret;
                   1028: 
                   1029:        q = cur++;
                   1030: 
                   1031:        while ((IS_LETTER(*cur)) || (IS_DIGIT(*cur)) ||
                   1032:               (*cur == '.') || (*cur == '-') ||
                   1033:               (*cur == '_') ||
                   1034:               (IS_COMBINING(*cur)) ||
                   1035:               (IS_EXTENDER(*cur)))
                   1036:            cur++;
                   1037:        
                   1038:        ret = xmlStrndup(q, cur - q);
                   1039:     }
                   1040: 
                   1041:     return(ret);
                   1042: }
                   1043: /**
1.50      daniel   1044:  * xmlNamespaceParseNSDef:
                   1045:  * @ctxt:  an XML parser context
                   1046:  *
                   1047:  * parse a namespace prefix declaration
1.28      daniel   1048:  *
                   1049:  * [NS 1] NSDef ::= PrefixDef Eq SystemLiteral
                   1050:  *
                   1051:  * [NS 2] PrefixDef ::= 'xmlns' (':' NCName)?
1.68      daniel   1052:  *
                   1053:  * Returns the namespace name
1.28      daniel   1054:  */
                   1055: 
1.55      daniel   1056: CHAR *
                   1057: xmlNamespaceParseNSDef(xmlParserCtxtPtr ctxt) {
1.28      daniel   1058:     CHAR *name = NULL;
                   1059: 
1.40      daniel   1060:     if ((CUR == 'x') && (NXT(1) == 'm') &&
                   1061:         (NXT(2) == 'l') && (NXT(3) == 'n') &&
                   1062:        (NXT(4) == 's')) {
                   1063:        SKIP(5);
                   1064:        if (CUR == ':') {
                   1065:            NEXT;
1.28      daniel   1066:            name = xmlNamespaceParseNCName(ctxt);
                   1067:        }
                   1068:     }
1.39      daniel   1069:     return(name);
1.28      daniel   1070: }
                   1071: 
1.50      daniel   1072: /**
                   1073:  * xmlParseQuotedString:
                   1074:  * @ctxt:  an XML parser context
                   1075:  *
1.45      daniel   1076:  * [OLD] Parse and return a string between quotes or doublequotes
1.68      daniel   1077:  *
                   1078:  * Returns the string parser or NULL.
1.45      daniel   1079:  */
1.55      daniel   1080: CHAR *
                   1081: xmlParseQuotedString(xmlParserCtxtPtr ctxt) {
1.45      daniel   1082:     CHAR *ret = NULL;
                   1083:     const CHAR *q;
                   1084: 
                   1085:     if (CUR == '"') {
                   1086:         NEXT;
                   1087:        q = CUR_PTR;
                   1088:        while (IS_CHAR(CUR) && (CUR != '"')) NEXT;
1.55      daniel   1089:        if (CUR != '"') {
                   1090:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1091:                ctxt->sax->error(ctxt->userData, "String not closed \"%.50s\"\n", q);
1.59      daniel   1092:            ctxt->wellFormed = 0;
1.55      daniel   1093:         } else {
1.45      daniel   1094:             ret = xmlStrndup(q, CUR_PTR - q);
                   1095:            NEXT;
                   1096:        }
                   1097:     } else if (CUR == '\''){
                   1098:         NEXT;
                   1099:        q = CUR_PTR;
                   1100:        while (IS_CHAR(CUR) && (CUR != '\'')) NEXT;
1.55      daniel   1101:        if (CUR != '\'') {
                   1102:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1103:                ctxt->sax->error(ctxt->userData, "String not closed \"%.50s\"\n", q);
1.59      daniel   1104:            ctxt->wellFormed = 0;
1.55      daniel   1105:         } else {
1.45      daniel   1106:             ret = xmlStrndup(q, CUR_PTR - q);
                   1107:            NEXT;
                   1108:        }
                   1109:     }
                   1110:     return(ret);
                   1111: }
                   1112: 
1.50      daniel   1113: /**
                   1114:  * xmlParseNamespace:
                   1115:  * @ctxt:  an XML parser context
                   1116:  *
1.45      daniel   1117:  * [OLD] xmlParseNamespace: parse specific PI '<?namespace ...' constructs.
                   1118:  *
                   1119:  * This is what the older xml-name Working Draft specified, a bunch of
                   1120:  * other stuff may still rely on it, so support is still here as
                   1121:  * if ot was declared on the root of the Tree:-(
                   1122:  */
                   1123: 
1.55      daniel   1124: void
                   1125: xmlParseNamespace(xmlParserCtxtPtr ctxt) {
1.45      daniel   1126:     CHAR *href = NULL;
                   1127:     CHAR *prefix = NULL;
                   1128:     int garbage = 0;
                   1129: 
                   1130:     /*
                   1131:      * We just skipped "namespace" or "xml:namespace"
                   1132:      */
                   1133:     SKIP_BLANKS;
                   1134: 
                   1135:     while (IS_CHAR(CUR) && (CUR != '>')) {
                   1136:        /*
                   1137:         * We can have "ns" or "prefix" attributes
                   1138:         * Old encoding as 'href' or 'AS' attributes is still supported
                   1139:         */
                   1140:        if ((CUR == 'n') && (NXT(1) == 's')) {
                   1141:            garbage = 0;
                   1142:            SKIP(2);
                   1143:            SKIP_BLANKS;
                   1144: 
                   1145:            if (CUR != '=') continue;
                   1146:            NEXT;
                   1147:            SKIP_BLANKS;
                   1148: 
                   1149:            href = xmlParseQuotedString(ctxt);
                   1150:            SKIP_BLANKS;
                   1151:        } else if ((CUR == 'h') && (NXT(1) == 'r') &&
                   1152:            (NXT(2) == 'e') && (NXT(3) == 'f')) {
                   1153:            garbage = 0;
                   1154:            SKIP(4);
                   1155:            SKIP_BLANKS;
                   1156: 
                   1157:            if (CUR != '=') continue;
                   1158:            NEXT;
                   1159:            SKIP_BLANKS;
                   1160: 
                   1161:            href = xmlParseQuotedString(ctxt);
                   1162:            SKIP_BLANKS;
                   1163:        } else if ((CUR == 'p') && (NXT(1) == 'r') &&
                   1164:                   (NXT(2) == 'e') && (NXT(3) == 'f') &&
                   1165:                   (NXT(4) == 'i') && (NXT(5) == 'x')) {
                   1166:            garbage = 0;
                   1167:            SKIP(6);
                   1168:            SKIP_BLANKS;
                   1169: 
                   1170:            if (CUR != '=') continue;
                   1171:            NEXT;
                   1172:            SKIP_BLANKS;
                   1173: 
                   1174:            prefix = xmlParseQuotedString(ctxt);
                   1175:            SKIP_BLANKS;
                   1176:        } else if ((CUR == 'A') && (NXT(1) == 'S')) {
                   1177:            garbage = 0;
                   1178:            SKIP(2);
                   1179:            SKIP_BLANKS;
                   1180: 
                   1181:            if (CUR != '=') continue;
                   1182:            NEXT;
                   1183:            SKIP_BLANKS;
                   1184: 
                   1185:            prefix = xmlParseQuotedString(ctxt);
                   1186:            SKIP_BLANKS;
                   1187:        } else if ((CUR == '?') && (NXT(1) == '>')) {
                   1188:            garbage = 0;
                   1189:            CUR_PTR ++;
                   1190:        } else {
                   1191:             /*
                   1192:             * Found garbage when parsing the namespace
                   1193:             */
                   1194:            if (!garbage)
1.55      daniel   1195:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1196:                    ctxt->sax->error(ctxt->userData, "xmlParseNamespace found garbage\n");
1.59      daniel   1197:            ctxt->wellFormed = 0;
1.45      daniel   1198:             NEXT;
                   1199:         }
                   1200:     }
                   1201: 
                   1202:     MOVETO_ENDTAG(CUR_PTR);
                   1203:     NEXT;
                   1204: 
                   1205:     /*
                   1206:      * Register the DTD.
1.72      daniel   1207:     if (href != NULL)
                   1208:        if ((ctxt->sax != NULL) && (ctxt->sax->globalNamespace != NULL))
1.74      daniel   1209:            ctxt->sax->globalNamespace(ctxt->userData, href, prefix);
1.45      daniel   1210:      */
                   1211: 
                   1212:     if (prefix != NULL) free(prefix);
                   1213:     if (href != NULL) free(href);
                   1214: }
                   1215: 
1.28      daniel   1216: /************************************************************************
                   1217:  *                                                                     *
                   1218:  *                     The parser itself                               *
                   1219:  *     Relates to http://www.w3.org/TR/REC-xml                         *
                   1220:  *                                                                     *
                   1221:  ************************************************************************/
1.14      veillard 1222: 
1.50      daniel   1223: /**
                   1224:  * xmlParseName:
                   1225:  * @ctxt:  an XML parser context
                   1226:  *
                   1227:  * parse an XML name.
1.22      daniel   1228:  *
                   1229:  * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
                   1230:  *                  CombiningChar | Extender
                   1231:  *
                   1232:  * [5] Name ::= (Letter | '_' | ':') (NameChar)*
                   1233:  *
                   1234:  * [6] Names ::= Name (S Name)*
1.68      daniel   1235:  *
                   1236:  * Returns the Name parsed or NULL
1.1       veillard 1237:  */
                   1238: 
1.55      daniel   1239: CHAR *
                   1240: xmlParseName(xmlParserCtxtPtr ctxt) {
1.17      daniel   1241:     const CHAR *q;
                   1242:     CHAR *ret = NULL;
1.1       veillard 1243: 
1.40      daniel   1244:     if (!IS_LETTER(CUR) && (CUR != '_') &&
                   1245:         (CUR != ':')) return(NULL);
                   1246:     q = NEXT;
                   1247: 
                   1248:     while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
                   1249:            (CUR == '.') || (CUR == '-') ||
                   1250:           (CUR == '_') || (CUR == ':') || 
                   1251:           (IS_COMBINING(CUR)) ||
                   1252:           (IS_EXTENDER(CUR)))
                   1253:        NEXT;
1.22      daniel   1254:     
1.40      daniel   1255:     ret = xmlStrndup(q, CUR_PTR - q);
1.22      daniel   1256: 
                   1257:     return(ret);
                   1258: }
                   1259: 
1.50      daniel   1260: /**
                   1261:  * xmlParseNmtoken:
                   1262:  * @ctxt:  an XML parser context
                   1263:  * 
                   1264:  * parse an XML Nmtoken.
1.22      daniel   1265:  *
                   1266:  * [7] Nmtoken ::= (NameChar)+
                   1267:  *
                   1268:  * [8] Nmtokens ::= Nmtoken (S Nmtoken)*
1.68      daniel   1269:  *
                   1270:  * Returns the Nmtoken parsed or NULL
1.22      daniel   1271:  */
                   1272: 
1.55      daniel   1273: CHAR *
                   1274: xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
1.22      daniel   1275:     const CHAR *q;
                   1276:     CHAR *ret = NULL;
                   1277: 
1.40      daniel   1278:     q = NEXT;
1.22      daniel   1279: 
1.40      daniel   1280:     while ((IS_LETTER(CUR)) || (IS_DIGIT(CUR)) ||
                   1281:            (CUR == '.') || (CUR == '-') ||
                   1282:           (CUR == '_') || (CUR == ':') || 
                   1283:           (IS_COMBINING(CUR)) ||
                   1284:           (IS_EXTENDER(CUR)))
                   1285:        NEXT;
1.3       veillard 1286:     
1.40      daniel   1287:     ret = xmlStrndup(q, CUR_PTR - q);
1.1       veillard 1288: 
1.3       veillard 1289:     return(ret);
1.1       veillard 1290: }
                   1291: 
1.50      daniel   1292: /**
                   1293:  * xmlParseEntityValue:
                   1294:  * @ctxt:  an XML parser context
1.78      daniel   1295:  * @orig:  if non-NULL store a copy of the original entity value
1.50      daniel   1296:  *
                   1297:  * parse a value for ENTITY decl.
1.24      daniel   1298:  *
                   1299:  * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
                   1300:  *                    "'" ([^%&'] | PEReference | Reference)* "'"
1.68      daniel   1301:  *
1.78      daniel   1302:  * Returns the EntityValue parsed with reference substitued or NULL
1.24      daniel   1303:  */
                   1304: 
1.55      daniel   1305: CHAR *
1.78      daniel   1306: xmlParseEntityValue(xmlParserCtxtPtr ctxt, CHAR **orig) {
1.77      daniel   1307:     CHAR *ret = NULL;
1.78      daniel   1308:     const CHAR *org = NULL;
1.79      daniel   1309:     const CHAR *tst = NULL;
                   1310:     const CHAR *temp = NULL;
1.24      daniel   1311: 
1.40      daniel   1312:     if (CUR == '"') {
                   1313:         NEXT;
1.78      daniel   1314:        org = CUR_PTR;
1.79      daniel   1315:        while (CUR != '"') {
                   1316:            tst = CUR_PTR;
                   1317:            temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_BOTH, '"', 0, 0);
                   1318:            if ((temp == NULL) && (tst == CUR_PTR)) break;
                   1319:            ret = xmlStrcat(ret, temp);
1.80      daniel   1320:            if (temp != NULL) free((char *)temp);
1.79      daniel   1321:        }
1.77      daniel   1322:         if (CUR != '"') {
1.55      daniel   1323:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.79      daniel   1324:                ctxt->sax->error(ctxt->userData, "EntityValue: \" expected\n");
1.59      daniel   1325:            ctxt->wellFormed = 0;
1.78      daniel   1326:        } else {
                   1327:            if (orig != NULL)
                   1328:                *orig = xmlStrndup(org, CUR_PTR - org);
1.40      daniel   1329:            NEXT;
1.78      daniel   1330:        }
1.40      daniel   1331:     } else if (CUR == '\'') {
                   1332:         NEXT;
1.78      daniel   1333:        org = CUR_PTR;
1.80      daniel   1334:        while (CUR != '\'') {
1.79      daniel   1335:            tst = CUR_PTR;
                   1336:            temp = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_BOTH, '\'', 0, 0);
                   1337:            if ((temp == NULL) && (tst == CUR_PTR)) break;
                   1338:            ret = xmlStrcat(ret, temp);
1.80      daniel   1339:            if (temp != NULL) free((char *)temp);
1.79      daniel   1340:        }
1.77      daniel   1341:         if (CUR != '\'') {
1.55      daniel   1342:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.77      daniel   1343:                ctxt->sax->error(ctxt->userData, "EntityValue: ' expected\n");
1.59      daniel   1344:            ctxt->wellFormed = 0;
1.78      daniel   1345:        } else {
                   1346:            if (orig != NULL)
                   1347:                *orig = xmlStrndup(org, CUR_PTR - org);
1.40      daniel   1348:            NEXT;
1.78      daniel   1349:        }
1.24      daniel   1350:     } else {
1.55      daniel   1351:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.77      daniel   1352:            ctxt->sax->error(ctxt->userData, "EntityValue: \" or ' expected\n");
1.59      daniel   1353:        ctxt->wellFormed = 0;
1.24      daniel   1354:     }
                   1355:     
                   1356:     return(ret);
                   1357: }
                   1358: 
1.50      daniel   1359: /**
                   1360:  * xmlParseAttValue:
                   1361:  * @ctxt:  an XML parser context
                   1362:  *
                   1363:  * parse a value for an attribute
1.78      daniel   1364:  * Note: the parser won't do substitution of entities here, this
1.79      daniel   1365:  * will be handled later in xmlStringGetNodeList, unless it was
                   1366:  * asked for ctxt->replaceEntities != 0 
1.29      daniel   1367:  *
                   1368:  * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
                   1369:  *                   "'" ([^<&'] | Reference)* "'"
1.68      daniel   1370:  *
                   1371:  * Returns the AttValue parsed or NULL.
1.29      daniel   1372:  */
                   1373: 
1.55      daniel   1374: CHAR *
                   1375: xmlParseAttValue(xmlParserCtxtPtr ctxt) {
1.77      daniel   1376:     CHAR *ret = NULL;
1.29      daniel   1377: 
1.40      daniel   1378:     if (CUR == '"') {
                   1379:         NEXT;
1.79      daniel   1380:        if (ctxt->replaceEntities != 0)
                   1381:            ret = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_REF, '"', '<', 0);
                   1382:        else
                   1383:            ret = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_NONE, '"', '<', 0);
1.77      daniel   1384:        if (CUR == '<') {
                   1385:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1386:                ctxt->sax->error(ctxt->userData,
                   1387:                   "Unescaped '<' not allowed in attributes values\n");
                   1388:            ctxt->wellFormed = 0;
1.29      daniel   1389:        }
1.77      daniel   1390:         if (CUR != '"') {
1.55      daniel   1391:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.77      daniel   1392:                ctxt->sax->error(ctxt->userData, "AttValue: ' expected\n");
1.59      daniel   1393:            ctxt->wellFormed = 0;
1.77      daniel   1394:        } else
1.40      daniel   1395:            NEXT;
                   1396:     } else if (CUR == '\'') {
                   1397:         NEXT;
1.79      daniel   1398:        if (ctxt->replaceEntities != 0)
                   1399:            ret = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_REF, '\'', '<', 0);
                   1400:        else
                   1401:            ret = xmlDecodeEntities(ctxt, -1, XML_SUBSTITUTE_NONE, '\'', '<', 0);
1.77      daniel   1402:        if (CUR == '<') {
                   1403:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   1404:                ctxt->sax->error(ctxt->userData,
                   1405:                   "Unescaped '<' not allowed in attributes values\n");
                   1406:            ctxt->wellFormed = 0;
1.29      daniel   1407:        }
1.77      daniel   1408:         if (CUR != '\'') {
1.55      daniel   1409:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.77      daniel   1410:                ctxt->sax->error(ctxt->userData, "AttValue: ' expected\n");
1.59      daniel   1411:            ctxt->wellFormed = 0;
1.77      daniel   1412:        } else
1.40      daniel   1413:            NEXT;
1.29      daniel   1414:     } else {
1.55      daniel   1415:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1416:            ctxt->sax->error(ctxt->userData, "AttValue: \" or ' expected\n");
1.59      daniel   1417:        ctxt->wellFormed = 0;
1.29      daniel   1418:     }
                   1419:     
                   1420:     return(ret);
                   1421: }
                   1422: 
1.50      daniel   1423: /**
                   1424:  * xmlParseSystemLiteral:
                   1425:  * @ctxt:  an XML parser context
                   1426:  * 
                   1427:  * parse an XML Literal
1.21      daniel   1428:  *
1.22      daniel   1429:  * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
1.68      daniel   1430:  *
                   1431:  * Returns the SystemLiteral parsed or NULL
1.21      daniel   1432:  */
                   1433: 
1.55      daniel   1434: CHAR *
                   1435: xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
1.21      daniel   1436:     const CHAR *q;
                   1437:     CHAR *ret = NULL;
                   1438: 
1.40      daniel   1439:     if (CUR == '"') {
                   1440:         NEXT;
                   1441:        q = CUR_PTR;
                   1442:        while ((IS_CHAR(CUR)) && (CUR != '"'))
                   1443:            NEXT;
                   1444:        if (!IS_CHAR(CUR)) {
1.55      daniel   1445:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1446:                ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n");
1.59      daniel   1447:            ctxt->wellFormed = 0;
1.21      daniel   1448:        } else {
1.40      daniel   1449:            ret = xmlStrndup(q, CUR_PTR - q);
                   1450:            NEXT;
1.21      daniel   1451:         }
1.40      daniel   1452:     } else if (CUR == '\'') {
                   1453:         NEXT;
                   1454:        q = CUR_PTR;
                   1455:        while ((IS_CHAR(CUR)) && (CUR != '\''))
                   1456:            NEXT;
                   1457:        if (!IS_CHAR(CUR)) {
1.55      daniel   1458:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1459:                ctxt->sax->error(ctxt->userData, "Unfinished SystemLiteral\n");
1.59      daniel   1460:            ctxt->wellFormed = 0;
1.21      daniel   1461:        } else {
1.40      daniel   1462:            ret = xmlStrndup(q, CUR_PTR - q);
                   1463:            NEXT;
1.21      daniel   1464:         }
                   1465:     } else {
1.55      daniel   1466:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1467:            ctxt->sax->error(ctxt->userData, "SystemLiteral \" or ' expected\n");
1.59      daniel   1468:        ctxt->wellFormed = 0;
1.21      daniel   1469:     }
                   1470:     
                   1471:     return(ret);
                   1472: }
                   1473: 
1.50      daniel   1474: /**
                   1475:  * xmlParsePubidLiteral:
                   1476:  * @ctxt:  an XML parser context
1.21      daniel   1477:  *
1.50      daniel   1478:  * parse an XML public literal
1.68      daniel   1479:  *
                   1480:  * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
                   1481:  *
                   1482:  * Returns the PubidLiteral parsed or NULL.
1.21      daniel   1483:  */
                   1484: 
1.55      daniel   1485: CHAR *
                   1486: xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
1.21      daniel   1487:     const CHAR *q;
                   1488:     CHAR *ret = NULL;
                   1489:     /*
                   1490:      * Name ::= (Letter | '_') (NameChar)*
                   1491:      */
1.40      daniel   1492:     if (CUR == '"') {
                   1493:         NEXT;
                   1494:        q = CUR_PTR;
                   1495:        while (IS_PUBIDCHAR(CUR)) NEXT;
                   1496:        if (CUR != '"') {
1.55      daniel   1497:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1498:                ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n");
1.59      daniel   1499:            ctxt->wellFormed = 0;
1.21      daniel   1500:        } else {
1.40      daniel   1501:            ret = xmlStrndup(q, CUR_PTR - q);
                   1502:            NEXT;
1.21      daniel   1503:        }
1.40      daniel   1504:     } else if (CUR == '\'') {
                   1505:         NEXT;
                   1506:        q = CUR_PTR;
                   1507:        while ((IS_LETTER(CUR)) && (CUR != '\''))
                   1508:            NEXT;
                   1509:        if (!IS_LETTER(CUR)) {
1.55      daniel   1510:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1511:                ctxt->sax->error(ctxt->userData, "Unfinished PubidLiteral\n");
1.59      daniel   1512:            ctxt->wellFormed = 0;
1.21      daniel   1513:        } else {
1.40      daniel   1514:            ret = xmlStrndup(q, CUR_PTR - q);
                   1515:            NEXT;
1.21      daniel   1516:        }
                   1517:     } else {
1.55      daniel   1518:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1519:            ctxt->sax->error(ctxt->userData, "SystemLiteral \" or ' expected\n");
1.59      daniel   1520:        ctxt->wellFormed = 0;
1.21      daniel   1521:     }
                   1522:     
                   1523:     return(ret);
                   1524: }
                   1525: 
1.50      daniel   1526: /**
                   1527:  * xmlParseCharData:
                   1528:  * @ctxt:  an XML parser context
                   1529:  * @cdata:  int indicating whether we are within a CDATA section
                   1530:  *
                   1531:  * parse a CharData section.
                   1532:  * if we are within a CDATA section ']]>' marks an end of section.
1.27      daniel   1533:  *
                   1534:  * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
                   1535:  */
                   1536: 
1.55      daniel   1537: void
                   1538: xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
1.27      daniel   1539:     const CHAR *q;
                   1540: 
1.40      daniel   1541:     q = CUR_PTR;
                   1542:     while ((IS_CHAR(CUR)) && (CUR != '<') &&
                   1543:            (CUR != '&')) {
1.59      daniel   1544:        if ((CUR == ']') && (NXT(1) == ']') &&
                   1545:            (NXT(2) == '>')) {
                   1546:            if (cdata) break;
                   1547:            else {
                   1548:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1549:                    ctxt->sax->error(ctxt->userData,
1.59      daniel   1550:                       "Sequence ']]>' not allowed in content\n");
                   1551:                ctxt->wellFormed = 0;
                   1552:            }
                   1553:        }
1.40      daniel   1554:         NEXT;
1.27      daniel   1555:     }
1.45      daniel   1556:     if (q == CUR_PTR) return;
                   1557: 
                   1558:     /*
                   1559:      * Ok the segment [q CUR_PTR] is to be consumed as chars.
                   1560:      */
                   1561:     if (ctxt->sax != NULL) {
1.72      daniel   1562:        if (areBlanks(ctxt, q, CUR_PTR - q)) {
                   1563:            if (ctxt->sax->ignorableWhitespace != NULL)
1.74      daniel   1564:                ctxt->sax->ignorableWhitespace(ctxt->userData, q, CUR_PTR - q);
1.72      daniel   1565:        } else {
                   1566:            if (ctxt->sax->characters != NULL)
1.74      daniel   1567:                ctxt->sax->characters(ctxt->userData, q, CUR_PTR - q);
1.72      daniel   1568:         }
1.45      daniel   1569:     }
1.27      daniel   1570: }
                   1571: 
1.50      daniel   1572: /**
                   1573:  * xmlParseExternalID:
                   1574:  * @ctxt:  an XML parser context
                   1575:  * @publicID:  a CHAR** receiving PubidLiteral
1.67      daniel   1576:  * @strict: indicate whether we should restrict parsing to only
                   1577:  *          production [75], see NOTE below
1.50      daniel   1578:  *
1.67      daniel   1579:  * Parse an External ID or a Public ID
                   1580:  *
                   1581:  * NOTE: Productions [75] and [83] interract badly since [75] can generate
                   1582:  *       'PUBLIC' S PubidLiteral S SystemLiteral
1.22      daniel   1583:  *
                   1584:  * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
                   1585:  *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
1.67      daniel   1586:  *
                   1587:  * [83] PublicID ::= 'PUBLIC' S PubidLiteral
                   1588:  *
1.68      daniel   1589:  * Returns the function returns SystemLiteral and in the second
1.67      daniel   1590:  *                case publicID receives PubidLiteral, is strict is off
                   1591:  *                it is possible to return NULL and have publicID set.
1.22      daniel   1592:  */
                   1593: 
1.55      daniel   1594: CHAR *
1.67      daniel   1595: xmlParseExternalID(xmlParserCtxtPtr ctxt, CHAR **publicID, int strict) {
1.39      daniel   1596:     CHAR *URI = NULL;
1.22      daniel   1597: 
1.40      daniel   1598:     if ((CUR == 'S') && (NXT(1) == 'Y') &&
                   1599:          (NXT(2) == 'S') && (NXT(3) == 'T') &&
                   1600:         (NXT(4) == 'E') && (NXT(5) == 'M')) {
                   1601:         SKIP(6);
1.59      daniel   1602:        if (!IS_BLANK(CUR)) {
                   1603:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1604:                ctxt->sax->error(ctxt->userData,
1.59      daniel   1605:                    "Space required after 'SYSTEM'\n");
                   1606:            ctxt->wellFormed = 0;
                   1607:        }
1.42      daniel   1608:         SKIP_BLANKS;
1.39      daniel   1609:        URI = xmlParseSystemLiteral(ctxt);
1.59      daniel   1610:        if (URI == NULL) {
1.55      daniel   1611:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1612:                ctxt->sax->error(ctxt->userData,
1.39      daniel   1613:                  "xmlParseExternalID: SYSTEM, no URI\n");
1.59      daniel   1614:            ctxt->wellFormed = 0;
                   1615:         }
1.40      daniel   1616:     } else if ((CUR == 'P') && (NXT(1) == 'U') &&
                   1617:               (NXT(2) == 'B') && (NXT(3) == 'L') &&
                   1618:               (NXT(4) == 'I') && (NXT(5) == 'C')) {
                   1619:         SKIP(6);
1.59      daniel   1620:        if (!IS_BLANK(CUR)) {
                   1621:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1622:                ctxt->sax->error(ctxt->userData,
1.59      daniel   1623:                    "Space required after 'PUBLIC'\n");
                   1624:            ctxt->wellFormed = 0;
                   1625:        }
1.42      daniel   1626:         SKIP_BLANKS;
1.39      daniel   1627:        *publicID = xmlParsePubidLiteral(ctxt);
1.59      daniel   1628:        if (*publicID == NULL) {
1.55      daniel   1629:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1630:                ctxt->sax->error(ctxt->userData, 
1.39      daniel   1631:                  "xmlParseExternalID: PUBLIC, no Public Identifier\n");
1.59      daniel   1632:            ctxt->wellFormed = 0;
                   1633:        }
1.67      daniel   1634:        if (strict) {
                   1635:            /*
                   1636:             * We don't handle [83] so "S SystemLiteral" is required.
                   1637:             */
                   1638:            if (!IS_BLANK(CUR)) {
                   1639:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1640:                    ctxt->sax->error(ctxt->userData,
1.67      daniel   1641:                        "Space required after the Public Identifier\n");
                   1642:                ctxt->wellFormed = 0;
                   1643:            }
                   1644:        } else {
                   1645:            /*
                   1646:             * We handle [83] so we return immediately, if 
                   1647:             * "S SystemLiteral" is not detected. From a purely parsing
                   1648:             * point of view that's a nice mess.
                   1649:             */
                   1650:            const CHAR *ptr = CUR_PTR;
                   1651:            if (!IS_BLANK(*ptr)) return(NULL);
                   1652:            
                   1653:            while (IS_BLANK(*ptr)) ptr++;
                   1654:            if ((*ptr != '\'') || (*ptr != '"')) return(NULL);
1.59      daniel   1655:        }
1.42      daniel   1656:         SKIP_BLANKS;
1.39      daniel   1657:        URI = xmlParseSystemLiteral(ctxt);
1.59      daniel   1658:        if (URI == NULL) {
1.55      daniel   1659:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1660:                ctxt->sax->error(ctxt->userData, 
1.39      daniel   1661:                   "xmlParseExternalID: PUBLIC, no URI\n");
1.59      daniel   1662:            ctxt->wellFormed = 0;
                   1663:         }
1.22      daniel   1664:     }
1.39      daniel   1665:     return(URI);
1.22      daniel   1666: }
                   1667: 
1.50      daniel   1668: /**
                   1669:  * xmlParseComment:
1.69      daniel   1670:  * @ctxt:  an XML parser context
                   1671:  * @create: should we create a node, or just skip the content
1.50      daniel   1672:  *
1.3       veillard 1673:  * Skip an XML (SGML) comment <!-- .... -->
1.31      daniel   1674:  *  This may or may not create a node (depending on the context)
1.38      daniel   1675:  *  The spec says that "For compatibility, the string "--" (double-hyphen)
                   1676:  *  must not occur within comments. "
1.22      daniel   1677:  *
                   1678:  * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
1.3       veillard 1679:  */
1.72      daniel   1680: void
1.69      daniel   1681: xmlParseComment(xmlParserCtxtPtr ctxt, int create) {
1.17      daniel   1682:     const CHAR *q, *start;
                   1683:     const CHAR *r;
1.39      daniel   1684:     CHAR *val;
1.3       veillard 1685: 
                   1686:     /*
1.22      daniel   1687:      * Check that there is a comment right here.
1.3       veillard 1688:      */
1.40      daniel   1689:     if ((CUR != '<') || (NXT(1) != '!') ||
1.72      daniel   1690:         (NXT(2) != '-') || (NXT(3) != '-')) return;
1.3       veillard 1691: 
1.40      daniel   1692:     SKIP(4);
                   1693:     start = q = CUR_PTR;
                   1694:     NEXT;
                   1695:     r = CUR_PTR;
                   1696:     NEXT;
                   1697:     while (IS_CHAR(CUR) &&
                   1698:            ((CUR == ':') || (CUR != '>') ||
1.16      daniel   1699:            (*r != '-') || (*q != '-'))) {
1.59      daniel   1700:        if ((*r == '-') && (*q == '-')) {
1.55      daniel   1701:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1702:                ctxt->sax->error(ctxt->userData,
1.38      daniel   1703:               "Comment must not contain '--' (double-hyphen)`\n");
1.59      daniel   1704:            ctxt->wellFormed = 0;
                   1705:        }
1.40      daniel   1706:         NEXT;r++;q++;
1.3       veillard 1707:     }
1.40      daniel   1708:     if (!IS_CHAR(CUR)) {
1.55      daniel   1709:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1710:            ctxt->sax->error(ctxt->userData, "Comment not terminated \n<!--%.50s\n", start);
1.59      daniel   1711:        ctxt->wellFormed = 0;
1.3       veillard 1712:     } else {
1.40      daniel   1713:         NEXT;
1.31      daniel   1714:        if (create) {
1.39      daniel   1715:            val = xmlStrndup(start, q - start);
1.72      daniel   1716:            if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL))
1.74      daniel   1717:                ctxt->sax->comment(ctxt->userData, val);
1.39      daniel   1718:            free(val);
1.31      daniel   1719:        }
1.3       veillard 1720:     }
                   1721: }
                   1722: 
1.50      daniel   1723: /**
                   1724:  * xmlParsePITarget:
                   1725:  * @ctxt:  an XML parser context
                   1726:  * 
                   1727:  * parse the name of a PI
1.22      daniel   1728:  *
                   1729:  * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
1.68      daniel   1730:  *
                   1731:  * Returns the PITarget name or NULL
1.22      daniel   1732:  */
                   1733: 
1.55      daniel   1734: CHAR *
                   1735: xmlParsePITarget(xmlParserCtxtPtr ctxt) {
1.22      daniel   1736:     CHAR *name;
                   1737: 
                   1738:     name = xmlParseName(ctxt);
                   1739:     if ((name != NULL) && (name[3] == 0) &&
                   1740:         ((name[0] == 'x') || (name[0] == 'X')) &&
1.31      daniel   1741:         ((name[1] == 'm') || (name[1] == 'M')) &&
                   1742:         ((name[2] == 'l') || (name[2] == 'L'))) {
1.55      daniel   1743:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1744:            ctxt->sax->error(ctxt->userData, "xmlParsePItarget: invalid name prefix 'xml'\n");
1.22      daniel   1745:        return(NULL);
                   1746:     }
                   1747:     return(name);
                   1748: }
                   1749: 
1.50      daniel   1750: /**
                   1751:  * xmlParsePI:
                   1752:  * @ctxt:  an XML parser context
                   1753:  * 
                   1754:  * parse an XML Processing Instruction.
1.22      daniel   1755:  *
                   1756:  * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
1.68      daniel   1757:  *
1.69      daniel   1758:  * The processing is transfered to SAX once parsed.
1.3       veillard 1759:  */
                   1760: 
1.55      daniel   1761: void
                   1762: xmlParsePI(xmlParserCtxtPtr ctxt) {
1.22      daniel   1763:     CHAR *target;
                   1764: 
1.40      daniel   1765:     if ((CUR == '<') && (NXT(1) == '?')) {
1.3       veillard 1766:        /*
                   1767:         * this is a Processing Instruction.
                   1768:         */
1.40      daniel   1769:        SKIP(2);
1.3       veillard 1770: 
                   1771:        /*
1.22      daniel   1772:         * Parse the target name and check for special support like
                   1773:         * namespace.
                   1774:         *
                   1775:         * TODO : PI handling should be dynamically redefinable using an
                   1776:         *        API. Only namespace should be in the code IMHO ...
1.3       veillard 1777:         */
1.22      daniel   1778:         target = xmlParsePITarget(ctxt);
                   1779:        if (target != NULL) {
1.72      daniel   1780:            const CHAR *q = CUR_PTR;
                   1781: 
                   1782:            while (IS_CHAR(CUR) &&
                   1783:                   ((CUR != '?') || (NXT(1) != '>')))
                   1784:                NEXT;
                   1785:            if (!IS_CHAR(CUR)) {
                   1786:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1787:                    ctxt->sax->error(ctxt->userData,
1.72      daniel   1788:                      "xmlParsePI: PI %s never end ...\n", target);
                   1789:                ctxt->wellFormed = 0;
1.22      daniel   1790:            } else {
1.72      daniel   1791:                CHAR *data;
1.44      daniel   1792: 
1.72      daniel   1793:                data = xmlStrndup(q, CUR_PTR - q);
                   1794:                SKIP(2);
1.44      daniel   1795: 
1.72      daniel   1796:                /*
                   1797:                 * SAX: PI detected.
                   1798:                 */
                   1799:                if ((ctxt->sax) &&
                   1800:                    (ctxt->sax->processingInstruction != NULL))
1.74      daniel   1801:                    ctxt->sax->processingInstruction(ctxt->userData, target, data);
1.72      daniel   1802:                free(data);
1.22      daniel   1803:            }
1.39      daniel   1804:            free(target);
1.3       veillard 1805:        } else {
1.55      daniel   1806:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1807:                ctxt->sax->error(ctxt->userData, "xmlParsePI : no target name\n");
1.59      daniel   1808:            ctxt->wellFormed = 0;
                   1809: 
1.22      daniel   1810:            /********* Should we try to complete parsing the PI ???
1.40      daniel   1811:            while (IS_CHAR(CUR) &&
                   1812:                   (CUR != '?') && (CUR != '>'))
                   1813:                NEXT;
                   1814:            if (!IS_CHAR(CUR)) {
1.22      daniel   1815:                fprintf(stderr, "xmlParsePI: PI %s never end ...\n",
                   1816:                        target);
                   1817:            }
                   1818:             ********************************************************/
                   1819:        }
                   1820:     }
                   1821: }
                   1822: 
1.50      daniel   1823: /**
                   1824:  * xmlParseNotationDecl:
                   1825:  * @ctxt:  an XML parser context
                   1826:  *
                   1827:  * parse a notation declaration
1.22      daniel   1828:  *
                   1829:  * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
                   1830:  *
                   1831:  * Hence there is actually 3 choices:
                   1832:  *     'PUBLIC' S PubidLiteral
                   1833:  *     'PUBLIC' S PubidLiteral S SystemLiteral
                   1834:  * and 'SYSTEM' S SystemLiteral
1.50      daniel   1835:  *
1.67      daniel   1836:  * See the NOTE on xmlParseExternalID().
1.22      daniel   1837:  */
                   1838: 
1.55      daniel   1839: void
                   1840: xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
1.22      daniel   1841:     CHAR *name;
1.67      daniel   1842:     CHAR *Pubid;
                   1843:     CHAR *Systemid;
1.22      daniel   1844:     
1.40      daniel   1845:     if ((CUR == '<') && (NXT(1) == '!') &&
                   1846:         (NXT(2) == 'N') && (NXT(3) == 'O') &&
                   1847:         (NXT(4) == 'T') && (NXT(5) == 'A') &&
                   1848:         (NXT(6) == 'T') && (NXT(7) == 'I') &&
1.67      daniel   1849:         (NXT(8) == 'O') && (NXT(9) == 'N')) {
1.40      daniel   1850:        SKIP(10);
1.67      daniel   1851:        if (!IS_BLANK(CUR)) {
                   1852:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1853:                ctxt->sax->error(ctxt->userData, "Space required after '<!NOTATION'\n");
1.67      daniel   1854:            ctxt->wellFormed = 0;
                   1855:            return;
                   1856:        }
                   1857:        SKIP_BLANKS;
1.22      daniel   1858: 
                   1859:         name = xmlParseName(ctxt);
                   1860:        if (name == NULL) {
1.55      daniel   1861:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1862:                ctxt->sax->error(ctxt->userData, "NOTATION: Name expected here\n");
1.67      daniel   1863:            ctxt->wellFormed = 0;
                   1864:            return;
                   1865:        }
                   1866:        if (!IS_BLANK(CUR)) {
                   1867:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1868:                ctxt->sax->error(ctxt->userData, 
1.67      daniel   1869:                     "Space required after the NOTATION name'\n");
1.59      daniel   1870:            ctxt->wellFormed = 0;
1.22      daniel   1871:            return;
                   1872:        }
1.42      daniel   1873:        SKIP_BLANKS;
1.67      daniel   1874: 
1.22      daniel   1875:        /*
1.67      daniel   1876:         * Parse the IDs.
1.22      daniel   1877:         */
1.67      daniel   1878:        Systemid = xmlParseExternalID(ctxt, &Pubid, 1);
                   1879:        SKIP_BLANKS;
                   1880: 
                   1881:        if (CUR == '>') {
1.40      daniel   1882:            NEXT;
1.72      daniel   1883:            if ((ctxt->sax != NULL) && (ctxt->sax->notationDecl != NULL))
1.74      daniel   1884:                ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
1.67      daniel   1885:        } else {
                   1886:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1887:                ctxt->sax->error(ctxt->userData,
1.67      daniel   1888:                       "'>' required to close NOTATION declaration\n");
                   1889:            ctxt->wellFormed = 0;
                   1890:        }
1.22      daniel   1891:        free(name);
1.67      daniel   1892:        if (Systemid != NULL) free(Systemid);
                   1893:        if (Pubid != NULL) free(Pubid);
1.22      daniel   1894:     }
                   1895: }
                   1896: 
1.50      daniel   1897: /**
                   1898:  * xmlParseEntityDecl:
                   1899:  * @ctxt:  an XML parser context
                   1900:  *
                   1901:  * parse <!ENTITY declarations
1.22      daniel   1902:  *
                   1903:  * [70] EntityDecl ::= GEDecl | PEDecl
                   1904:  *
                   1905:  * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
                   1906:  *
                   1907:  * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
                   1908:  *
                   1909:  * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
                   1910:  *
                   1911:  * [74] PEDef ::= EntityValue | ExternalID
1.24      daniel   1912:  *
                   1913:  * [76] NDataDecl ::= S 'NDATA' S Name
1.22      daniel   1914:  */
                   1915: 
1.55      daniel   1916: void
                   1917: xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
1.39      daniel   1918:     CHAR *name = NULL;
1.24      daniel   1919:     CHAR *value = NULL;
1.39      daniel   1920:     CHAR *URI = NULL, *literal = NULL;
1.24      daniel   1921:     CHAR *ndata = NULL;
1.39      daniel   1922:     int isParameter = 0;
1.78      daniel   1923:     CHAR *orig = NULL;
1.22      daniel   1924:     
1.40      daniel   1925:     if ((CUR == '<') && (NXT(1) == '!') &&
                   1926:         (NXT(2) == 'E') && (NXT(3) == 'N') &&
                   1927:         (NXT(4) == 'T') && (NXT(5) == 'I') &&
1.59      daniel   1928:         (NXT(6) == 'T') && (NXT(7) == 'Y')) {
1.40      daniel   1929:        SKIP(8);
1.59      daniel   1930:        if (!IS_BLANK(CUR)) {
                   1931:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1932:                ctxt->sax->error(ctxt->userData, "Space required after '<!ENTITY'\n");
1.59      daniel   1933:            ctxt->wellFormed = 0;
                   1934:        }
                   1935:        SKIP_BLANKS;
1.40      daniel   1936: 
                   1937:        if (CUR == '%') {
                   1938:            NEXT;
1.59      daniel   1939:            if (!IS_BLANK(CUR)) {
                   1940:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1941:                    ctxt->sax->error(ctxt->userData, "Space required after '%'\n");
1.59      daniel   1942:                ctxt->wellFormed = 0;
                   1943:            }
1.42      daniel   1944:            SKIP_BLANKS;
1.39      daniel   1945:            isParameter = 1;
1.22      daniel   1946:        }
                   1947: 
                   1948:         name = xmlParseName(ctxt);
1.24      daniel   1949:        if (name == NULL) {
1.55      daniel   1950:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1951:                ctxt->sax->error(ctxt->userData, "xmlParseEntityDecl: no name\n");
1.59      daniel   1952:            ctxt->wellFormed = 0;
1.24      daniel   1953:             return;
                   1954:        }
1.59      daniel   1955:        if (!IS_BLANK(CUR)) {
                   1956:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1957:                ctxt->sax->error(ctxt->userData,
1.59      daniel   1958:                     "Space required after the entity name\n");
                   1959:            ctxt->wellFormed = 0;
                   1960:        }
1.42      daniel   1961:         SKIP_BLANKS;
1.24      daniel   1962: 
1.22      daniel   1963:        /*
1.68      daniel   1964:         * handle the various case of definitions...
1.22      daniel   1965:         */
1.39      daniel   1966:        if (isParameter) {
1.40      daniel   1967:            if ((CUR == '"') || (CUR == '\''))
1.78      daniel   1968:                value = xmlParseEntityValue(ctxt, &orig);
1.39      daniel   1969:                if (value) {
1.72      daniel   1970:                    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74      daniel   1971:                        ctxt->sax->entityDecl(ctxt->userData, name,
1.39      daniel   1972:                                    XML_INTERNAL_PARAMETER_ENTITY,
                   1973:                                    NULL, NULL, value);
                   1974:                }
1.24      daniel   1975:            else {
1.67      daniel   1976:                URI = xmlParseExternalID(ctxt, &literal, 1);
1.39      daniel   1977:                if (URI) {
1.72      daniel   1978:                    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74      daniel   1979:                        ctxt->sax->entityDecl(ctxt->userData, name,
1.39      daniel   1980:                                    XML_EXTERNAL_PARAMETER_ENTITY,
                   1981:                                    literal, URI, NULL);
                   1982:                }
1.24      daniel   1983:            }
                   1984:        } else {
1.40      daniel   1985:            if ((CUR == '"') || (CUR == '\'')) {
1.78      daniel   1986:                value = xmlParseEntityValue(ctxt, &orig);
1.72      daniel   1987:                if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74      daniel   1988:                    ctxt->sax->entityDecl(ctxt->userData, name,
1.39      daniel   1989:                                XML_INTERNAL_GENERAL_ENTITY,
                   1990:                                NULL, NULL, value);
                   1991:            } else {
1.67      daniel   1992:                URI = xmlParseExternalID(ctxt, &literal, 1);
1.59      daniel   1993:                if ((CUR != '>') && (!IS_BLANK(CUR))) {
                   1994:                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   1995:                        ctxt->sax->error(ctxt->userData,
1.59      daniel   1996:                            "Space required before 'NDATA'\n");
                   1997:                    ctxt->wellFormed = 0;
                   1998:                }
1.42      daniel   1999:                SKIP_BLANKS;
1.40      daniel   2000:                if ((CUR == 'N') && (NXT(1) == 'D') &&
                   2001:                    (NXT(2) == 'A') && (NXT(3) == 'T') &&
                   2002:                    (NXT(4) == 'A')) {
                   2003:                    SKIP(5);
1.59      daniel   2004:                    if (!IS_BLANK(CUR)) {
                   2005:                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2006:                            ctxt->sax->error(ctxt->userData,
1.59      daniel   2007:                                "Space required after 'NDATA'\n");
                   2008:                        ctxt->wellFormed = 0;
                   2009:                    }
1.42      daniel   2010:                    SKIP_BLANKS;
1.24      daniel   2011:                    ndata = xmlParseName(ctxt);
1.72      daniel   2012:                    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74      daniel   2013:                        ctxt->sax->entityDecl(ctxt->userData, name,
1.39      daniel   2014:                                    XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
                   2015:                                    literal, URI, ndata);
                   2016:                } else {
1.72      daniel   2017:                    if ((ctxt->sax != NULL) && (ctxt->sax->entityDecl != NULL))
1.74      daniel   2018:                        ctxt->sax->entityDecl(ctxt->userData, name,
1.39      daniel   2019:                                    XML_EXTERNAL_GENERAL_PARSED_ENTITY,
                   2020:                                    literal, URI, NULL);
1.24      daniel   2021:                }
                   2022:            }
                   2023:        }
1.42      daniel   2024:        SKIP_BLANKS;
1.40      daniel   2025:        if (CUR != '>') {
1.55      daniel   2026:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2027:                ctxt->sax->error(ctxt->userData, 
1.31      daniel   2028:                    "xmlParseEntityDecl: entity %s not terminated\n", name);
1.59      daniel   2029:            ctxt->wellFormed = 0;
1.24      daniel   2030:        } else
1.40      daniel   2031:            NEXT;
1.78      daniel   2032:        if (orig != NULL) {
                   2033:            /*
                   2034:             * TODO: somwhat unclean, extending the SAx API would be better !
                   2035:             */
                   2036:            xmlEntityPtr cur = NULL;
                   2037: 
                   2038:            if ((ctxt->sax != NULL) && (ctxt->sax->getEntity != NULL))
                   2039:                cur = ctxt->sax->getEntity(ctxt, name);
                   2040:             if (cur != NULL)
                   2041:                cur->orig = orig;
                   2042:            else
                   2043:                free(orig);
                   2044:        }
1.39      daniel   2045:        if (name != NULL) free(name);
                   2046:        if (value != NULL) free(value);
                   2047:        if (URI != NULL) free(URI);
                   2048:        if (literal != NULL) free(literal);
                   2049:        if (ndata != NULL) free(ndata);
1.22      daniel   2050:     }
                   2051: }
                   2052: 
1.50      daniel   2053: /**
1.59      daniel   2054:  * xmlParseDefaultDecl:
                   2055:  * @ctxt:  an XML parser context
                   2056:  * @value:  Receive a possible fixed default value for the attribute
                   2057:  *
                   2058:  * Parse an attribute default declaration
                   2059:  *
                   2060:  * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
                   2061:  *
                   2062:  * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
                   2063:  *          or XML_ATTRIBUTE_FIXED. 
                   2064:  */
                   2065: 
                   2066: int
                   2067: xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, CHAR **value) {
                   2068:     int val;
                   2069:     CHAR *ret;
                   2070: 
                   2071:     *value = NULL;
                   2072:     if ((CUR == '#') && (NXT(1) == 'R') &&
                   2073:         (NXT(2) == 'E') && (NXT(3) == 'Q') &&
                   2074:         (NXT(4) == 'U') && (NXT(5) == 'I') &&
                   2075:         (NXT(6) == 'R') && (NXT(7) == 'E') &&
                   2076:         (NXT(8) == 'D')) {
                   2077:        SKIP(9);
                   2078:        return(XML_ATTRIBUTE_REQUIRED);
                   2079:     }
                   2080:     if ((CUR == '#') && (NXT(1) == 'I') &&
                   2081:         (NXT(2) == 'M') && (NXT(3) == 'P') &&
                   2082:         (NXT(4) == 'L') && (NXT(5) == 'I') &&
                   2083:         (NXT(6) == 'E') && (NXT(7) == 'D')) {
                   2084:        SKIP(8);
                   2085:        return(XML_ATTRIBUTE_IMPLIED);
                   2086:     }
                   2087:     val = XML_ATTRIBUTE_NONE;
                   2088:     if ((CUR == '#') && (NXT(1) == 'F') &&
                   2089:         (NXT(2) == 'I') && (NXT(3) == 'X') &&
                   2090:         (NXT(4) == 'E') && (NXT(5) == 'D')) {
                   2091:        SKIP(6);
                   2092:        val = XML_ATTRIBUTE_FIXED;
                   2093:        if (!IS_BLANK(CUR)) {
                   2094:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2095:                ctxt->sax->error(ctxt->userData, "Space required after '#FIXED'\n");
1.59      daniel   2096:            ctxt->wellFormed = 0;
                   2097:        }
                   2098:        SKIP_BLANKS;
                   2099:     }
                   2100:     ret = xmlParseAttValue(ctxt);
                   2101:     if (ret == NULL) {
                   2102:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2103:            ctxt->sax->error(ctxt->userData,
1.59      daniel   2104:               "Attribute default value declaration error\n");
                   2105:        ctxt->wellFormed = 0;
                   2106:     } else
                   2107:         *value = ret;
                   2108:     return(val);
                   2109: }
                   2110: 
                   2111: /**
1.66      daniel   2112:  * xmlParseNotationType:
                   2113:  * @ctxt:  an XML parser context
                   2114:  *
                   2115:  * parse an Notation attribute type.
                   2116:  *
                   2117:  * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
                   2118:  *
                   2119:  * Note: the leading 'NOTATION' S part has already being parsed...
                   2120:  *
                   2121:  * Returns: the notation attribute tree built while parsing
                   2122:  */
                   2123: 
                   2124: xmlEnumerationPtr
                   2125: xmlParseNotationType(xmlParserCtxtPtr ctxt) {
                   2126:     CHAR *name;
                   2127:     xmlEnumerationPtr ret = NULL, last = NULL, cur;
                   2128: 
                   2129:     if (CUR != '(') {
                   2130:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2131:            ctxt->sax->error(ctxt->userData, "'(' required to start 'NOTATION'\n");
1.66      daniel   2132:        ctxt->wellFormed = 0;
                   2133:        return(NULL);
                   2134:     }
                   2135:     do {
                   2136:         NEXT;
                   2137:        SKIP_BLANKS;
                   2138:         name = xmlParseName(ctxt);
                   2139:        if (name == NULL) {
                   2140:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2141:                ctxt->sax->error(ctxt->userData, 
1.66      daniel   2142:                                 "Name expected in NOTATION declaration\n");
                   2143:            ctxt->wellFormed = 0;
                   2144:            return(ret);
                   2145:        }
                   2146:        cur = xmlCreateEnumeration(name);
1.67      daniel   2147:        free(name);
1.66      daniel   2148:        if (cur == NULL) return(ret);
                   2149:        if (last == NULL) ret = last = cur;
                   2150:        else {
                   2151:            last->next = cur;
                   2152:            last = cur;
                   2153:        }
                   2154:        SKIP_BLANKS;
                   2155:     } while (CUR == '|');
                   2156:     if (CUR != ')') {
                   2157:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2158:            ctxt->sax->error(ctxt->userData,
1.66      daniel   2159:                             "')' required to finish NOTATION declaration\n");
                   2160:        ctxt->wellFormed = 0;
                   2161:        return(ret);
                   2162:     }
                   2163:     NEXT;
                   2164:     return(ret);
                   2165: }
                   2166: 
                   2167: /**
                   2168:  * xmlParseEnumerationType:
                   2169:  * @ctxt:  an XML parser context
                   2170:  *
                   2171:  * parse an Enumeration attribute type.
                   2172:  *
                   2173:  * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
                   2174:  *
                   2175:  * Returns: the enumeration attribute tree built while parsing
                   2176:  */
                   2177: 
                   2178: xmlEnumerationPtr
                   2179: xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
                   2180:     CHAR *name;
                   2181:     xmlEnumerationPtr ret = NULL, last = NULL, cur;
                   2182: 
                   2183:     if (CUR != '(') {
                   2184:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2185:            ctxt->sax->error(ctxt->userData,
1.66      daniel   2186:                             "'(' required to start ATTLIST enumeration\n");
                   2187:        ctxt->wellFormed = 0;
                   2188:        return(NULL);
                   2189:     }
                   2190:     do {
                   2191:         NEXT;
                   2192:        SKIP_BLANKS;
                   2193:         name = xmlParseNmtoken(ctxt);
                   2194:        if (name == NULL) {
                   2195:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2196:                ctxt->sax->error(ctxt->userData, 
1.66      daniel   2197:                                 "NmToken expected in ATTLIST enumeration\n");
                   2198:            ctxt->wellFormed = 0;
                   2199:            return(ret);
                   2200:        }
                   2201:        cur = xmlCreateEnumeration(name);
1.67      daniel   2202:        free(name);
1.66      daniel   2203:        if (cur == NULL) return(ret);
                   2204:        if (last == NULL) ret = last = cur;
                   2205:        else {
                   2206:            last->next = cur;
                   2207:            last = cur;
                   2208:        }
                   2209:        SKIP_BLANKS;
                   2210:     } while (CUR == '|');
                   2211:     if (CUR != ')') {
                   2212:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2213:            ctxt->sax->error(ctxt->userData,
1.66      daniel   2214:                             "')' required to finish ATTLIST enumeration\n");
                   2215:        ctxt->wellFormed = 0;
                   2216:        return(ret);
                   2217:     }
                   2218:     NEXT;
                   2219:     return(ret);
                   2220: }
                   2221: 
                   2222: /**
1.50      daniel   2223:  * xmlParseEnumeratedType:
                   2224:  * @ctxt:  an XML parser context
1.66      daniel   2225:  * @tree:  the enumeration tree built while parsing
1.50      daniel   2226:  *
1.66      daniel   2227:  * parse an Enumerated attribute type.
1.22      daniel   2228:  *
                   2229:  * [57] EnumeratedType ::= NotationType | Enumeration
                   2230:  *
                   2231:  * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
                   2232:  *
1.50      daniel   2233:  *
1.66      daniel   2234:  * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
1.22      daniel   2235:  */
                   2236: 
1.66      daniel   2237: int
                   2238: xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
                   2239:     if ((CUR == 'N') && (NXT(1) == 'O') &&
                   2240:         (NXT(2) == 'T') && (NXT(3) == 'A') &&
                   2241:         (NXT(4) == 'T') && (NXT(5) == 'I') &&
                   2242:        (NXT(6) == 'O') && (NXT(7) == 'N')) {
                   2243:        SKIP(8);
                   2244:        if (!IS_BLANK(CUR)) {
                   2245:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2246:                ctxt->sax->error(ctxt->userData, "Space required after 'NOTATION'\n");
1.66      daniel   2247:            ctxt->wellFormed = 0;
                   2248:            return(0);
                   2249:        }
                   2250:         SKIP_BLANKS;
                   2251:        *tree = xmlParseNotationType(ctxt);
                   2252:        if (*tree == NULL) return(0);
                   2253:        return(XML_ATTRIBUTE_NOTATION);
                   2254:     }
                   2255:     *tree = xmlParseEnumerationType(ctxt);
                   2256:     if (*tree == NULL) return(0);
                   2257:     return(XML_ATTRIBUTE_ENUMERATION);
1.22      daniel   2258: }
                   2259: 
1.50      daniel   2260: /**
                   2261:  * xmlParseAttributeType:
                   2262:  * @ctxt:  an XML parser context
1.66      daniel   2263:  * @tree:  the enumeration tree built while parsing
1.50      daniel   2264:  *
1.59      daniel   2265:  * parse the Attribute list def for an element
1.22      daniel   2266:  *
                   2267:  * [54] AttType ::= StringType | TokenizedType | EnumeratedType
                   2268:  *
                   2269:  * [55] StringType ::= 'CDATA'
                   2270:  *
                   2271:  * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
                   2272:  *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
1.50      daniel   2273:  *
1.69      daniel   2274:  * Returns the attribute type
1.22      daniel   2275:  */
1.59      daniel   2276: int 
1.66      daniel   2277: xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
1.40      daniel   2278:     if ((CUR == 'C') && (NXT(1) == 'D') &&
                   2279:         (NXT(2) == 'A') && (NXT(3) == 'T') &&
                   2280:         (NXT(4) == 'A')) {
                   2281:        SKIP(5);
1.66      daniel   2282:        return(XML_ATTRIBUTE_CDATA);
1.40      daniel   2283:      } else if ((CUR == 'I') && (NXT(1) == 'D') &&
                   2284:         (NXT(2) == 'R') && (NXT(3) == 'E') &&
                   2285:         (NXT(4) == 'F')) {
                   2286:        SKIP(5);
1.59      daniel   2287:        return(XML_ATTRIBUTE_IDREF);
1.66      daniel   2288:      } else if ((CUR == 'I') && (NXT(1) == 'D')) {
                   2289:         SKIP(2);
                   2290:        return(XML_ATTRIBUTE_ID);
1.40      daniel   2291:      } else if ((CUR == 'I') && (NXT(1) == 'D') &&
                   2292:         (NXT(2) == 'R') && (NXT(3) == 'E') &&
                   2293:         (NXT(4) == 'F') && (NXT(5) == 'S')) {
                   2294:        SKIP(6);
1.59      daniel   2295:        return(XML_ATTRIBUTE_IDREFS);
1.40      daniel   2296:      } else if ((CUR == 'E') && (NXT(1) == 'N') &&
                   2297:         (NXT(2) == 'T') && (NXT(3) == 'I') &&
                   2298:         (NXT(4) == 'T') && (NXT(5) == 'Y')) {
                   2299:        SKIP(6);
1.59      daniel   2300:        return(XML_ATTRIBUTE_ENTITY);
1.40      daniel   2301:      } else if ((CUR == 'E') && (NXT(1) == 'N') &&
                   2302:         (NXT(2) == 'T') && (NXT(3) == 'I') &&
                   2303:         (NXT(4) == 'T') && (NXT(5) == 'I') &&
                   2304:         (NXT(6) == 'E') && (NXT(7) == 'S')) {
                   2305:        SKIP(8);
1.59      daniel   2306:        return(XML_ATTRIBUTE_ENTITIES);
1.40      daniel   2307:      } else if ((CUR == 'N') && (NXT(1) == 'M') &&
                   2308:         (NXT(2) == 'T') && (NXT(3) == 'O') &&
                   2309:         (NXT(4) == 'K') && (NXT(5) == 'E') &&
1.66      daniel   2310:         (NXT(6) == 'N') && (NXT(7) == 'S')) {
                   2311:        SKIP(8);
                   2312:        return(XML_ATTRIBUTE_NMTOKENS);
                   2313:      } else if ((CUR == 'N') && (NXT(1) == 'M') &&
                   2314:         (NXT(2) == 'T') && (NXT(3) == 'O') &&
                   2315:         (NXT(4) == 'K') && (NXT(5) == 'E') &&
1.40      daniel   2316:         (NXT(6) == 'N')) {
                   2317:        SKIP(7);
1.59      daniel   2318:        return(XML_ATTRIBUTE_NMTOKEN);
1.22      daniel   2319:      }
1.66      daniel   2320:      return(xmlParseEnumeratedType(ctxt, tree));
1.22      daniel   2321: }
                   2322: 
1.50      daniel   2323: /**
                   2324:  * xmlParseAttributeListDecl:
                   2325:  * @ctxt:  an XML parser context
                   2326:  *
                   2327:  * : parse the Attribute list def for an element
1.22      daniel   2328:  *
                   2329:  * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
                   2330:  *
                   2331:  * [53] AttDef ::= S Name S AttType S DefaultDecl
1.50      daniel   2332:  *
1.22      daniel   2333:  */
1.55      daniel   2334: void
                   2335: xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
1.59      daniel   2336:     CHAR *elemName;
                   2337:     CHAR *attrName;
1.66      daniel   2338:     xmlEnumerationPtr tree = NULL;
1.22      daniel   2339: 
1.40      daniel   2340:     if ((CUR == '<') && (NXT(1) == '!') &&
                   2341:         (NXT(2) == 'A') && (NXT(3) == 'T') &&
                   2342:         (NXT(4) == 'T') && (NXT(5) == 'L') &&
                   2343:         (NXT(6) == 'I') && (NXT(7) == 'S') &&
1.59      daniel   2344:         (NXT(8) == 'T')) {
1.40      daniel   2345:        SKIP(9);
1.59      daniel   2346:        if (!IS_BLANK(CUR)) {
                   2347:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2348:                ctxt->sax->error(ctxt->userData, "Space required after '<!ATTLIST'\n");
1.59      daniel   2349:            ctxt->wellFormed = 0;
                   2350:        }
1.42      daniel   2351:         SKIP_BLANKS;
1.59      daniel   2352:         elemName = xmlParseName(ctxt);
                   2353:        if (elemName == NULL) {
1.55      daniel   2354:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2355:                ctxt->sax->error(ctxt->userData, "ATTLIST: no name for Element\n");
1.59      daniel   2356:            ctxt->wellFormed = 0;
1.22      daniel   2357:            return;
                   2358:        }
1.42      daniel   2359:        SKIP_BLANKS;
1.40      daniel   2360:        while (CUR != '>') {
                   2361:            const CHAR *check = CUR_PTR;
1.59      daniel   2362:            int type;
                   2363:            int def;
                   2364:            CHAR *defaultValue = NULL;
                   2365: 
                   2366:            attrName = xmlParseName(ctxt);
                   2367:            if (attrName == NULL) {
                   2368:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2369:                    ctxt->sax->error(ctxt->userData, "ATTLIST: no name for Attribute\n");
1.59      daniel   2370:                ctxt->wellFormed = 0;
                   2371:                break;
                   2372:            }
                   2373:            if (!IS_BLANK(CUR)) {
                   2374:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2375:                    ctxt->sax->error(ctxt->userData, 
1.59      daniel   2376:                        "Space required after the attribute name\n");
                   2377:                ctxt->wellFormed = 0;
                   2378:                break;
                   2379:            }
                   2380:            SKIP_BLANKS;
                   2381: 
1.66      daniel   2382:            type = xmlParseAttributeType(ctxt, &tree);
1.59      daniel   2383:            if (type <= 0) break;
1.22      daniel   2384: 
1.59      daniel   2385:            if (!IS_BLANK(CUR)) {
                   2386:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2387:                    ctxt->sax->error(ctxt->userData, 
1.59      daniel   2388:                        "Space required after the attribute type\n");
                   2389:                ctxt->wellFormed = 0;
                   2390:                break;
                   2391:            }
1.42      daniel   2392:            SKIP_BLANKS;
1.59      daniel   2393: 
                   2394:            def = xmlParseDefaultDecl(ctxt, &defaultValue);
                   2395:            if (def <= 0) break;
                   2396: 
                   2397:             if (CUR != '>') {
                   2398:                if (!IS_BLANK(CUR)) {
                   2399:                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2400:                        ctxt->sax->error(ctxt->userData, 
1.59      daniel   2401:                        "Space required after the attribute default value\n");
                   2402:                    ctxt->wellFormed = 0;
                   2403:                    break;
                   2404:                }
                   2405:                SKIP_BLANKS;
                   2406:            }
1.40      daniel   2407:            if (check == CUR_PTR) {
1.55      daniel   2408:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2409:                    ctxt->sax->error(ctxt->userData, 
1.59      daniel   2410:                    "xmlParseAttributeListDecl: detected internal error\n");
1.22      daniel   2411:                break;
                   2412:            }
1.72      daniel   2413:            if ((ctxt->sax != NULL) && (ctxt->sax->attributeDecl != NULL))
1.74      daniel   2414:                ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
1.66      daniel   2415:                                type, def, defaultValue, tree);
1.59      daniel   2416:            if (attrName != NULL)
                   2417:                free(attrName);
                   2418:            if (defaultValue != NULL)
                   2419:                free(defaultValue);
1.22      daniel   2420:        }
1.40      daniel   2421:        if (CUR == '>')
                   2422:            NEXT;
1.22      daniel   2423: 
1.59      daniel   2424:        free(elemName);
1.22      daniel   2425:     }
                   2426: }
                   2427: 
1.50      daniel   2428: /**
1.61      daniel   2429:  * xmlParseElementMixedContentDecl:
                   2430:  * @ctxt:  an XML parser context
                   2431:  *
                   2432:  * parse the declaration for a Mixed Element content
                   2433:  * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
                   2434:  * 
                   2435:  * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
                   2436:  *                '(' S? '#PCDATA' S? ')'
                   2437:  *
                   2438:  * returns: the list of the xmlElementContentPtr describing the element choices
                   2439:  */
                   2440: xmlElementContentPtr
1.62      daniel   2441: xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt) {
1.64      daniel   2442:     xmlElementContentPtr ret = NULL, cur = NULL, n;
1.61      daniel   2443:     CHAR *elem = NULL;
                   2444: 
                   2445:     if ((CUR == '#') && (NXT(1) == 'P') &&
                   2446:         (NXT(2) == 'C') && (NXT(3) == 'D') &&
                   2447:         (NXT(4) == 'A') && (NXT(5) == 'T') &&
                   2448:         (NXT(6) == 'A')) {
                   2449:        SKIP(7);
                   2450:        SKIP_BLANKS;
1.63      daniel   2451:        if (CUR == ')') {
                   2452:            NEXT;
                   2453:            ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
                   2454:            return(ret);
                   2455:        }
1.61      daniel   2456:        if ((CUR == '(') || (CUR == '|')) {
                   2457:            ret = cur = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_PCDATA);
                   2458:            if (ret == NULL) return(NULL);
1.63      daniel   2459:        } /********** else {
1.61      daniel   2460:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2461:                ctxt->sax->error(ctxt->userData, 
1.61      daniel   2462:                    "xmlParseElementMixedContentDecl : '|' or ')' expected\n");
                   2463:            ctxt->wellFormed = 0;
                   2464:            return(NULL);
1.63      daniel   2465:        } **********/
1.61      daniel   2466:        while (CUR == '|') {
1.64      daniel   2467:            NEXT;
1.61      daniel   2468:            if (elem == NULL) {
                   2469:                ret = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
                   2470:                if (ret == NULL) return(NULL);
                   2471:                ret->c1 = cur;
1.64      daniel   2472:                cur = ret;
1.61      daniel   2473:            } else {
1.64      daniel   2474:                n = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
                   2475:                if (n == NULL) return(NULL);
                   2476:                n->c1 = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
                   2477:                cur->c2 = n;
                   2478:                cur = n;
1.66      daniel   2479:                free(elem);
1.61      daniel   2480:            }
                   2481:            SKIP_BLANKS;
                   2482:            elem = xmlParseName(ctxt);
                   2483:            if (elem == NULL) {
                   2484:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2485:                    ctxt->sax->error(ctxt->userData, 
1.61      daniel   2486:                        "xmlParseElementMixedContentDecl : Name expected\n");
                   2487:                ctxt->wellFormed = 0;
                   2488:                xmlFreeElementContent(cur);
                   2489:                return(NULL);
                   2490:            }
                   2491:            SKIP_BLANKS;
                   2492:        }
1.63      daniel   2493:        if ((CUR == ')') && (NXT(1) == '*')) {
1.66      daniel   2494:            if (elem != NULL) {
1.61      daniel   2495:                cur->c2 = xmlNewElementContent(elem,
                   2496:                                               XML_ELEMENT_CONTENT_ELEMENT);
1.66      daniel   2497:                free(elem);
                   2498:             }
1.65      daniel   2499:            ret->ocur = XML_ELEMENT_CONTENT_MULT;
1.64      daniel   2500:            SKIP(2);
1.61      daniel   2501:        } else {
1.66      daniel   2502:            if (elem != NULL) free(elem);
1.61      daniel   2503:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2504:                ctxt->sax->error(ctxt->userData, 
1.63      daniel   2505:                    "xmlParseElementMixedContentDecl : '|' or ')*' expected\n");
1.61      daniel   2506:            ctxt->wellFormed = 0;
                   2507:            xmlFreeElementContent(ret);
                   2508:            return(NULL);
                   2509:        }
                   2510: 
                   2511:     } else {
                   2512:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2513:            ctxt->sax->error(ctxt->userData, 
1.61      daniel   2514:                "xmlParseElementMixedContentDecl : '#PCDATA' expected\n");
                   2515:        ctxt->wellFormed = 0;
                   2516:     }
                   2517:     return(ret);
                   2518: }
                   2519: 
                   2520: /**
                   2521:  * xmlParseElementChildrenContentDecl:
1.50      daniel   2522:  * @ctxt:  an XML parser context
                   2523:  *
1.61      daniel   2524:  * parse the declaration for a Mixed Element content
                   2525:  * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
1.22      daniel   2526:  * 
1.61      daniel   2527:  *
1.22      daniel   2528:  * [47] children ::= (choice | seq) ('?' | '*' | '+')?
                   2529:  *
                   2530:  * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
                   2531:  *
                   2532:  * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
                   2533:  *
                   2534:  * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
                   2535:  *
1.62      daniel   2536:  * returns: the tree of xmlElementContentPtr describing the element 
1.61      daniel   2537:  *          hierarchy.
                   2538:  */
                   2539: xmlElementContentPtr
1.62      daniel   2540: xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt) {
1.63      daniel   2541:     xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
1.62      daniel   2542:     CHAR *elem;
                   2543:     CHAR type = 0;
                   2544: 
                   2545:     SKIP_BLANKS;
                   2546:     if (CUR == '(') {
1.63      daniel   2547:         /* Recurse on first child */
1.62      daniel   2548:        NEXT;
                   2549:        SKIP_BLANKS;
                   2550:         cur = ret = xmlParseElementChildrenContentDecl(ctxt);
                   2551:        SKIP_BLANKS;
                   2552:     } else {
                   2553:        elem = xmlParseName(ctxt);
                   2554:        if (elem == NULL) {
                   2555:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2556:                ctxt->sax->error(ctxt->userData, 
1.62      daniel   2557:                "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
                   2558:            ctxt->wellFormed = 0;
                   2559:            return(NULL);
                   2560:        }
                   2561:         cur = ret = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
                   2562:        if (CUR == '?') {
                   2563:            ret->ocur = XML_ELEMENT_CONTENT_OPT;
                   2564:            NEXT;
                   2565:        } else if (CUR == '*') {
                   2566:            ret->ocur = XML_ELEMENT_CONTENT_MULT;
                   2567:            NEXT;
                   2568:        } else if (CUR == '+') {
                   2569:            ret->ocur = XML_ELEMENT_CONTENT_PLUS;
                   2570:            NEXT;
                   2571:        } else {
                   2572:            ret->ocur = XML_ELEMENT_CONTENT_ONCE;
                   2573:        }
1.66      daniel   2574:        free(elem);
1.62      daniel   2575:     }
                   2576:     SKIP_BLANKS;
                   2577:     while (CUR != ')') {
1.63      daniel   2578:         /*
                   2579:         * Each loop we parse one separator and one element.
                   2580:         */
1.62      daniel   2581:         if (CUR == ',') {
                   2582:            if (type == 0) type = CUR;
                   2583: 
                   2584:            /*
                   2585:             * Detect "Name | Name , Name" error
                   2586:             */
                   2587:            else if (type != CUR) {
                   2588:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2589:                    ctxt->sax->error(ctxt->userData, 
1.62      daniel   2590:                    "xmlParseElementChildrenContentDecl : '%c' expected\n",
                   2591:                    type);
                   2592:                ctxt->wellFormed = 0;
                   2593:                xmlFreeElementContent(ret);
                   2594:                return(NULL);
                   2595:            }
1.64      daniel   2596:            NEXT;
1.62      daniel   2597: 
1.63      daniel   2598:            op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_SEQ);
                   2599:            if (op == NULL) {
                   2600:                xmlFreeElementContent(ret);
                   2601:                return(NULL);
                   2602:            }
                   2603:            if (last == NULL) {
                   2604:                op->c1 = ret;
1.65      daniel   2605:                ret = cur = op;
1.63      daniel   2606:            } else {
                   2607:                cur->c2 = op;
                   2608:                op->c1 = last;
                   2609:                cur =op;
1.65      daniel   2610:                last = NULL;
1.63      daniel   2611:            }
1.62      daniel   2612:        } else if (CUR == '|') {
                   2613:            if (type == 0) type = CUR;
                   2614: 
                   2615:            /*
1.63      daniel   2616:             * Detect "Name , Name | Name" error
1.62      daniel   2617:             */
                   2618:            else if (type != CUR) {
                   2619:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2620:                    ctxt->sax->error(ctxt->userData, 
1.62      daniel   2621:                    "xmlParseElementChildrenContentDecl : '%c' expected\n",
                   2622:                    type);
                   2623:                ctxt->wellFormed = 0;
                   2624:                xmlFreeElementContent(ret);
                   2625:                return(NULL);
                   2626:            }
1.64      daniel   2627:            NEXT;
1.62      daniel   2628: 
1.63      daniel   2629:            op = xmlNewElementContent(NULL, XML_ELEMENT_CONTENT_OR);
                   2630:            if (op == NULL) {
                   2631:                xmlFreeElementContent(ret);
                   2632:                return(NULL);
                   2633:            }
                   2634:            if (last == NULL) {
                   2635:                op->c1 = ret;
1.65      daniel   2636:                ret = cur = op;
1.63      daniel   2637:            } else {
                   2638:                cur->c2 = op;
                   2639:                op->c1 = last;
                   2640:                cur =op;
1.65      daniel   2641:                last = NULL;
1.63      daniel   2642:            }
1.62      daniel   2643:        } else {
                   2644:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2645:                ctxt->sax->error(ctxt->userData, 
1.62      daniel   2646:            "xmlParseElementChildrenContentDecl : ',' '|' or ')' expected\n");
                   2647:            ctxt->wellFormed = 0;
                   2648:            xmlFreeElementContent(ret);
                   2649:            return(NULL);
                   2650:        }
                   2651:        SKIP_BLANKS;
                   2652:        if (CUR == '(') {
1.63      daniel   2653:            /* Recurse on second child */
1.62      daniel   2654:            NEXT;
                   2655:            SKIP_BLANKS;
1.65      daniel   2656:            last = xmlParseElementChildrenContentDecl(ctxt);
1.62      daniel   2657:            SKIP_BLANKS;
                   2658:        } else {
                   2659:            elem = xmlParseName(ctxt);
                   2660:            if (elem == NULL) {
                   2661:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2662:                    ctxt->sax->error(ctxt->userData, 
1.62      daniel   2663:                    "xmlParseElementChildrenContentDecl : Name or '(' expected\n");
                   2664:                ctxt->wellFormed = 0;
                   2665:                return(NULL);
                   2666:            }
1.65      daniel   2667:            last = xmlNewElementContent(elem, XML_ELEMENT_CONTENT_ELEMENT);
1.66      daniel   2668:            free(elem);
1.62      daniel   2669:        }
1.63      daniel   2670:        if (CUR == '?') {
                   2671:            ret->ocur = XML_ELEMENT_CONTENT_OPT;
                   2672:            NEXT;
                   2673:        } else if (CUR == '*') {
                   2674:            ret->ocur = XML_ELEMENT_CONTENT_MULT;
                   2675:            NEXT;
                   2676:        } else if (CUR == '+') {
                   2677:            ret->ocur = XML_ELEMENT_CONTENT_PLUS;
                   2678:            NEXT;
                   2679:        } else {
                   2680:            ret->ocur = XML_ELEMENT_CONTENT_ONCE;
                   2681:        }
                   2682:        SKIP_BLANKS;
1.64      daniel   2683:     }
1.65      daniel   2684:     if ((cur != NULL) && (last != NULL)) {
                   2685:         cur->c2 = last;
1.62      daniel   2686:     }
                   2687:     NEXT;
                   2688:     if (CUR == '?') {
                   2689:         ret->ocur = XML_ELEMENT_CONTENT_OPT;
                   2690:        NEXT;
                   2691:     } else if (CUR == '*') {
                   2692:         ret->ocur = XML_ELEMENT_CONTENT_MULT;
                   2693:        NEXT;
                   2694:     } else if (CUR == '+') {
                   2695:         ret->ocur = XML_ELEMENT_CONTENT_PLUS;
                   2696:        NEXT;
                   2697:     } else {
                   2698:         ret->ocur = XML_ELEMENT_CONTENT_ONCE;
                   2699:     }
                   2700:     return(ret);
1.61      daniel   2701: }
                   2702: 
                   2703: /**
                   2704:  * xmlParseElementContentDecl:
                   2705:  * @ctxt:  an XML parser context
                   2706:  * @name:  the name of the element being defined.
                   2707:  * @result:  the Element Content pointer will be stored here if any
1.22      daniel   2708:  *
1.61      daniel   2709:  * parse the declaration for an Element content either Mixed or Children,
                   2710:  * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
                   2711:  * 
                   2712:  * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
1.50      daniel   2713:  *
1.61      daniel   2714:  * returns: the type of element content XML_ELEMENT_TYPE_xxx
1.22      daniel   2715:  */
                   2716: 
1.61      daniel   2717: int
                   2718: xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, CHAR *name,
                   2719:                            xmlElementContentPtr *result) {
                   2720: 
                   2721:     xmlElementContentPtr tree = NULL;
                   2722:     int res;
                   2723: 
                   2724:     *result = NULL;
                   2725: 
                   2726:     if (CUR != '(') {
                   2727:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2728:            ctxt->sax->error(ctxt->userData, 
1.61      daniel   2729:                "xmlParseElementContentDecl : '(' expected\n");
                   2730:        ctxt->wellFormed = 0;
                   2731:        return(-1);
                   2732:     }
                   2733:     NEXT;
                   2734:     SKIP_BLANKS;
                   2735:     if ((CUR == '#') && (NXT(1) == 'P') &&
                   2736:         (NXT(2) == 'C') && (NXT(3) == 'D') &&
                   2737:         (NXT(4) == 'A') && (NXT(5) == 'T') &&
                   2738:         (NXT(6) == 'A')) {
1.62      daniel   2739:         tree = xmlParseElementMixedContentDecl(ctxt);
1.61      daniel   2740:        res = XML_ELEMENT_TYPE_MIXED;
                   2741:     } else {
1.62      daniel   2742:         tree = xmlParseElementChildrenContentDecl(ctxt);
1.61      daniel   2743:        res = XML_ELEMENT_TYPE_ELEMENT;
                   2744:     }
                   2745:     SKIP_BLANKS;
1.63      daniel   2746:     /****************************
1.61      daniel   2747:     if (CUR != ')') {
                   2748:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2749:            ctxt->sax->error(ctxt->userData, 
1.61      daniel   2750:                "xmlParseElementContentDecl : ')' expected\n");
                   2751:        ctxt->wellFormed = 0;
                   2752:        return(-1);
                   2753:     }
1.63      daniel   2754:      ****************************/
                   2755:     *result = tree;
1.61      daniel   2756:     return(res);
1.22      daniel   2757: }
                   2758: 
1.50      daniel   2759: /**
                   2760:  * xmlParseElementDecl:
                   2761:  * @ctxt:  an XML parser context
                   2762:  *
                   2763:  * parse an Element declaration.
1.22      daniel   2764:  *
                   2765:  * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
                   2766:  *
                   2767:  * TODO There is a check [ VC: Unique Element Type Declaration ]
1.69      daniel   2768:  *
                   2769:  * Returns the type of the element, or -1 in case of error
1.22      daniel   2770:  */
1.59      daniel   2771: int
1.55      daniel   2772: xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
1.22      daniel   2773:     CHAR *name;
1.59      daniel   2774:     int ret = -1;
1.61      daniel   2775:     xmlElementContentPtr content  = NULL;
1.22      daniel   2776: 
1.40      daniel   2777:     if ((CUR == '<') && (NXT(1) == '!') &&
                   2778:         (NXT(2) == 'E') && (NXT(3) == 'L') &&
                   2779:         (NXT(4) == 'E') && (NXT(5) == 'M') &&
                   2780:         (NXT(6) == 'E') && (NXT(7) == 'N') &&
1.59      daniel   2781:         (NXT(8) == 'T')) {
1.40      daniel   2782:        SKIP(9);
1.59      daniel   2783:        if (!IS_BLANK(CUR)) {
                   2784:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2785:                ctxt->sax->error(ctxt->userData, 
1.59      daniel   2786:                    "Space required after 'ELEMENT'\n");
                   2787:            ctxt->wellFormed = 0;
                   2788:        }
1.42      daniel   2789:         SKIP_BLANKS;
1.22      daniel   2790:         name = xmlParseName(ctxt);
                   2791:        if (name == NULL) {
1.55      daniel   2792:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2793:                ctxt->sax->error(ctxt->userData,
1.59      daniel   2794:                   "xmlParseElementDecl: no name for Element\n");
                   2795:            ctxt->wellFormed = 0;
                   2796:            return(-1);
                   2797:        }
                   2798:        if (!IS_BLANK(CUR)) {
                   2799:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2800:                ctxt->sax->error(ctxt->userData, 
1.59      daniel   2801:                    "Space required after the element name\n");
                   2802:            ctxt->wellFormed = 0;
1.22      daniel   2803:        }
1.42      daniel   2804:         SKIP_BLANKS;
1.40      daniel   2805:        if ((CUR == 'E') && (NXT(1) == 'M') &&
                   2806:            (NXT(2) == 'P') && (NXT(3) == 'T') &&
                   2807:            (NXT(4) == 'Y')) {
                   2808:            SKIP(5);
1.22      daniel   2809:            /*
                   2810:             * Element must always be empty.
                   2811:             */
1.59      daniel   2812:            ret = XML_ELEMENT_TYPE_EMPTY;
1.40      daniel   2813:        } else if ((CUR == 'A') && (NXT(1) == 'N') &&
                   2814:                   (NXT(2) == 'Y')) {
                   2815:            SKIP(3);
1.22      daniel   2816:            /*
                   2817:             * Element is a generic container.
                   2818:             */
1.59      daniel   2819:            ret = XML_ELEMENT_TYPE_ANY;
1.61      daniel   2820:        } else if (CUR == '(') {
                   2821:            ret = xmlParseElementContentDecl(ctxt, name, &content);
1.22      daniel   2822:        } else {
1.61      daniel   2823:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2824:                ctxt->sax->error(ctxt->userData, 
1.61      daniel   2825:                  "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
                   2826:            ctxt->wellFormed = 0;
                   2827:            if (name != NULL) free(name);
                   2828:            return(-1);
1.22      daniel   2829:        }
1.42      daniel   2830:        SKIP_BLANKS;
1.40      daniel   2831:        if (CUR != '>') {
1.55      daniel   2832:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   2833:                ctxt->sax->error(ctxt->userData, 
1.31      daniel   2834:                  "xmlParseElementDecl: expected '>' at the end\n");
1.59      daniel   2835:            ctxt->wellFormed = 0;
1.61      daniel   2836:        } else {
1.40      daniel   2837:            NEXT;
1.72      daniel   2838:            if ((ctxt->sax != NULL) && (ctxt->sax->elementDecl != NULL))
1.76      daniel   2839:                ctxt->sax->elementDecl(ctxt->userData, name, ret,
                   2840:                                       content);
1.61      daniel   2841:        }
1.84    ! daniel   2842:        if (content != NULL) {
        !          2843:            xmlFreeElementContent(content);
        !          2844:        }
1.61      daniel   2845:        if (name != NULL) {
                   2846:            free(name);
                   2847:        }
1.22      daniel   2848:     }
1.59      daniel   2849:     return(ret);
1.22      daniel   2850: }
                   2851: 
1.50      daniel   2852: /**
                   2853:  * xmlParseMarkupDecl:
                   2854:  * @ctxt:  an XML parser context
                   2855:  * 
                   2856:  * parse Markup declarations
1.22      daniel   2857:  *
                   2858:  * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
                   2859:  *                     NotationDecl | PI | Comment
                   2860:  *
                   2861:  * TODO There is a check [ VC: Proper Declaration/PE Nesting ]
                   2862:  */
1.55      daniel   2863: void
                   2864: xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
1.22      daniel   2865:     xmlParseElementDecl(ctxt);
                   2866:     xmlParseAttributeListDecl(ctxt);
                   2867:     xmlParseEntityDecl(ctxt);
                   2868:     xmlParseNotationDecl(ctxt);
                   2869:     xmlParsePI(ctxt);
1.31      daniel   2870:     xmlParseComment(ctxt, 0);
1.22      daniel   2871: }
                   2872: 
1.50      daniel   2873: /**
1.76      daniel   2874:  * xmlParseTextDecl:
                   2875:  * @ctxt:  an XML parser context
                   2876:  * 
                   2877:  * parse an XML declaration header for external entities
                   2878:  *
                   2879:  * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
                   2880:  *
                   2881:  * Returns the only valuable info for an external parsed entity, the encoding
                   2882:  */
                   2883: 
                   2884: CHAR *
                   2885: xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
                   2886:     CHAR *version;
                   2887:     CHAR *encoding = NULL;
                   2888: 
                   2889:     /*
                   2890:      * We know that '<?xml' is here.
                   2891:      */
                   2892:     SKIP(5);
                   2893: 
                   2894:     if (!IS_BLANK(CUR)) {
                   2895:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   2896:            ctxt->sax->error(ctxt->userData, "Blank needed after '<?xml'\n");
                   2897:        ctxt->wellFormed = 0;
                   2898:     }
                   2899:     SKIP_BLANKS;
                   2900: 
                   2901:     /*
                   2902:      * We may have the VersionInfo here.
                   2903:      */
                   2904:     version = xmlParseVersionInfo(ctxt);
                   2905:     /* TODO: we should actually inherit from the referencing doc if absent
                   2906:     if (version == NULL)
                   2907:        version = xmlCharStrdup(XML_DEFAULT_VERSION);
                   2908:     ctxt->version = xmlStrdup(version);
                   2909:      */
                   2910:     if (version != NULL)
                   2911:        free(version);
                   2912: 
                   2913:     /*
                   2914:      * We must have the encoding declaration
                   2915:      */
                   2916:     if (!IS_BLANK(CUR)) {
                   2917:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   2918:            ctxt->sax->error(ctxt->userData, "Blank needed here\n");
                   2919:        ctxt->wellFormed = 0;
                   2920:     }
                   2921:     encoding = xmlParseEncodingDecl(ctxt);
                   2922: 
                   2923:     SKIP_BLANKS;
                   2924:     if ((CUR == '?') && (NXT(1) == '>')) {
                   2925:         SKIP(2);
                   2926:     } else if (CUR == '>') {
                   2927:         /* Deprecated old WD ... */
                   2928:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   2929:            ctxt->sax->error(ctxt->userData, "XML declaration must end-up with '?>'\n");
                   2930:        ctxt->wellFormed = 0;
                   2931:        NEXT;
                   2932:     } else {
                   2933:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   2934:            ctxt->sax->error(ctxt->userData, "parsing XML declaration: '?>' expected\n");
                   2935:        ctxt->wellFormed = 0;
                   2936:        MOVETO_ENDTAG(CUR_PTR);
                   2937:        NEXT;
                   2938:     }
                   2939:     return(encoding);
                   2940: }
                   2941: 
                   2942: /*
                   2943:  * xmlParseConditionalSections
                   2944:  * @ctxt:  an XML parser context
                   2945:  *
                   2946:  * TODO : Conditionnal section are not yet supported !
                   2947:  *
                   2948:  * [61] conditionalSect ::= includeSect | ignoreSect 
                   2949:  * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>' 
                   2950:  * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
                   2951:  * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
                   2952:  * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
                   2953:  */
                   2954: 
                   2955: void
                   2956: xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
                   2957:     if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
                   2958:        ctxt->sax->warning(ctxt->userData,
                   2959:                            "XML conditional section not supported\n");
                   2960:     /*
                   2961:      * Skip up to the end of the conditionnal section.
                   2962:      */
                   2963:     while ((CUR != 0) && ((CUR != ']') || (NXT(1) != ']') || (NXT(2) != '>')))
                   2964:        NEXT;
                   2965:     if (CUR == 0) {
                   2966:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   2967:            ctxt->sax->error(ctxt->userData,
                   2968:                "XML conditional section not closed\n");
                   2969:        ctxt->wellFormed = 0;
                   2970:     }
                   2971: }
                   2972: 
                   2973: /**
                   2974:  * xmlParseExternalSubset
                   2975:  * @ctxt:  an XML parser context
                   2976:  * 
                   2977:  * parse Markup declarations from an external subset
                   2978:  *
                   2979:  * [30] extSubset ::= textDecl? extSubsetDecl
                   2980:  *
                   2981:  * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
                   2982:  *
                   2983:  * TODO There is a check [ VC: Proper Declaration/PE Nesting ]
                   2984:  */
                   2985: void
1.79      daniel   2986: xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const CHAR *ExternalID,
                   2987:                        const CHAR *SystemID) {
1.76      daniel   2988:     if ((CUR == '<') && (NXT(1) == '?') &&
                   2989:         (NXT(2) == 'x') && (NXT(3) == 'm') &&
                   2990:        (NXT(4) == 'l')) {
                   2991:        xmlParseTextDecl(ctxt);
                   2992:     }
1.79      daniel   2993:     if (ctxt->myDoc == NULL) {
                   2994:         ctxt->myDoc = xmlNewDoc("1.0");
                   2995:     }
                   2996:     if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
                   2997:         xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
                   2998: 
1.76      daniel   2999:     while (((CUR == '<') && (NXT(1) == '?')) ||
                   3000:            ((CUR == '<') && (NXT(1) == '!')) ||
                   3001:            IS_BLANK(CUR)) {
                   3002:         if ((CUR == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
                   3003:            xmlParseConditionalSections(ctxt);
                   3004:        } else if (IS_BLANK(CUR)) {
                   3005:            NEXT;
                   3006:        } else if (CUR == '%') {
                   3007:             xmlParsePEReference(ctxt);
                   3008:        } else
                   3009:            xmlParseMarkupDecl(ctxt);
1.77      daniel   3010: 
                   3011:        /*
                   3012:         * Pop-up of finished entities.
                   3013:         */
                   3014:        while ((CUR == 0) && (ctxt->inputNr > 1))
                   3015:            xmlPopInput(ctxt);
                   3016: 
1.76      daniel   3017:     }
                   3018:     
                   3019:     if (CUR != 0) {
                   3020:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   3021:            ctxt->sax->error(ctxt->userData,
                   3022:                "Extra content at the end of the document\n");
                   3023:        ctxt->wellFormed = 0;
                   3024:     }
                   3025: 
                   3026: }
                   3027: 
                   3028: /**
1.50      daniel   3029:  * xmlParseCharRef:
                   3030:  * @ctxt:  an XML parser context
                   3031:  *
                   3032:  * parse Reference declarations
1.24      daniel   3033:  *
                   3034:  * [66] CharRef ::= '&#' [0-9]+ ';' |
                   3035:  *                  '&#x' [0-9a-fA-F]+ ';'
1.68      daniel   3036:  *
1.77      daniel   3037:  * Returns the value parsed (as an int)
1.24      daniel   3038:  */
1.77      daniel   3039: int
1.55      daniel   3040: xmlParseCharRef(xmlParserCtxtPtr ctxt) {
1.29      daniel   3041:     int val = 0;
1.24      daniel   3042: 
1.40      daniel   3043:     if ((CUR == '&') && (NXT(1) == '#') &&
                   3044:         (NXT(2) == 'x')) {
                   3045:        SKIP(3);
                   3046:        while (CUR != ';') {
                   3047:            if ((CUR >= '0') && (CUR <= '9')) 
                   3048:                val = val * 16 + (CUR - '0');
                   3049:            else if ((CUR >= 'a') && (CUR <= 'f'))
                   3050:                val = val * 16 + (CUR - 'a') + 10;
                   3051:            else if ((CUR >= 'A') && (CUR <= 'F'))
                   3052:                val = val * 16 + (CUR - 'A') + 10;
1.24      daniel   3053:            else {
1.55      daniel   3054:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3055:                    ctxt->sax->error(ctxt->userData, 
1.59      daniel   3056:                         "xmlParseCharRef: invalid hexadecimal value\n");
                   3057:                ctxt->wellFormed = 0;
1.29      daniel   3058:                val = 0;
1.24      daniel   3059:                break;
                   3060:            }
1.47      daniel   3061:            NEXT;
1.24      daniel   3062:        }
1.55      daniel   3063:        if (CUR == ';')
1.40      daniel   3064:            NEXT;
                   3065:     } else if  ((CUR == '&') && (NXT(1) == '#')) {
                   3066:        SKIP(2);
                   3067:        while (CUR != ';') {
                   3068:            if ((CUR >= '0') && (CUR <= '9')) 
1.55      daniel   3069:                val = val * 10 + (CUR - '0');
1.24      daniel   3070:            else {
1.55      daniel   3071:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3072:                    ctxt->sax->error(ctxt->userData, 
1.58      daniel   3073:                         "xmlParseCharRef: invalid decimal value\n");
1.59      daniel   3074:                ctxt->wellFormed = 0;
1.29      daniel   3075:                val = 0;
1.24      daniel   3076:                break;
                   3077:            }
1.47      daniel   3078:            NEXT;
1.24      daniel   3079:        }
1.55      daniel   3080:        if (CUR == ';')
1.40      daniel   3081:            NEXT;
1.24      daniel   3082:     } else {
1.55      daniel   3083:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3084:            ctxt->sax->error(ctxt->userData, "xmlParseCharRef: invalid value\n");
1.59      daniel   3085:        ctxt->wellFormed = 0;
1.24      daniel   3086:     }
1.29      daniel   3087:     /*
                   3088:      * Check the value IS_CHAR ...
                   3089:      */
1.44      daniel   3090:     if (IS_CHAR(val)) {
1.77      daniel   3091:         return(val);
1.44      daniel   3092:     } else {
1.55      daniel   3093:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3094:            ctxt->sax->error(ctxt->userData, "xmlParseCharRef: invalid CHAR value %d\n",
1.58      daniel   3095:                             val);
1.59      daniel   3096:        ctxt->wellFormed = 0;
1.29      daniel   3097:     }
1.77      daniel   3098:     return(0);
                   3099: }
                   3100: 
                   3101: /**
                   3102:  * xmlParseReference:
                   3103:  * @ctxt:  an XML parser context
                   3104:  * 
                   3105:  * parse and handle entity references in content, depending on the SAX
                   3106:  * interface, this may end-up in a call to character() if this is a
1.79      daniel   3107:  * CharRef, a predefined entity, if there is no reference() callback.
                   3108:  * or if the parser was asked to switch to that mode.
1.77      daniel   3109:  *
                   3110:  * [67] Reference ::= EntityRef | CharRef
                   3111:  */
                   3112: void
                   3113: xmlParseReference(xmlParserCtxtPtr ctxt) {
                   3114:     xmlEntityPtr ent;
                   3115:     CHAR *val;
                   3116:     if (CUR != '&') return;
                   3117: 
                   3118:     if (NXT(1) == '#') {
                   3119:        CHAR out[2];
                   3120:        int val = xmlParseCharRef(ctxt);
                   3121:        /* TODO: invalid for UTF-8 variable encoding !!! */
                   3122:        out[0] = val;
                   3123:        out[1] = 0;
                   3124:        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
                   3125:            ctxt->sax->characters(ctxt->userData, out, 1);
                   3126:     } else {
                   3127:        ent = xmlParseEntityRef(ctxt);
                   3128:        if (ent == NULL) return;
                   3129:        if ((ent->name != NULL) && 
                   3130:            (ent->type != XML_INTERNAL_PREDEFINED_ENTITY) &&
1.79      daniel   3131:            (ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
                   3132:            (ctxt->replaceEntities == 0)) {
                   3133: 
1.77      daniel   3134:            /*
                   3135:             * Create a node.
                   3136:             */
                   3137:            ctxt->sax->reference(ctxt->userData, ent->name);
                   3138:            return;
                   3139:        }
                   3140:        val = ent->content;
                   3141:        if (val == NULL) return;
                   3142:        /*
                   3143:         * inline the entity.
                   3144:         */
                   3145:        if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL))
                   3146:            ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
                   3147:     }
1.24      daniel   3148: }
                   3149: 
1.50      daniel   3150: /**
                   3151:  * xmlParseEntityRef:
                   3152:  * @ctxt:  an XML parser context
                   3153:  *
                   3154:  * parse ENTITY references declarations
1.24      daniel   3155:  *
                   3156:  * [68] EntityRef ::= '&' Name ';'
1.68      daniel   3157:  *
1.77      daniel   3158:  * Returns the xmlEntityPtr if found, or NULL otherwise.
1.24      daniel   3159:  */
1.77      daniel   3160: xmlEntityPtr
1.55      daniel   3161: xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
1.84    ! daniel   3162:     const CHAR *q; /* !!!!!!!!!!! Unused !!!!!!!!!! */
1.24      daniel   3163:     CHAR *name;
1.72      daniel   3164:     xmlEntityPtr ent = NULL;
1.24      daniel   3165: 
1.50      daniel   3166:     q = CUR_PTR;
1.40      daniel   3167:     if (CUR == '&') {
                   3168:         NEXT;
1.24      daniel   3169:         name = xmlParseName(ctxt);
                   3170:        if (name == NULL) {
1.55      daniel   3171:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3172:                ctxt->sax->error(ctxt->userData, "xmlParseEntityRef: no name\n");
1.59      daniel   3173:            ctxt->wellFormed = 0;
1.24      daniel   3174:        } else {
1.40      daniel   3175:            if (CUR == ';') {
                   3176:                NEXT;
1.24      daniel   3177:                /*
1.77      daniel   3178:                 * Ask first SAX for entity resolution, otherwise try the
                   3179:                 * predefined set.
                   3180:                 */
                   3181:                if (ctxt->sax != NULL) {
                   3182:                    if (ctxt->sax->getEntity != NULL)
                   3183:                        ent = ctxt->sax->getEntity(ctxt->userData, name);
                   3184:                    if (ent == NULL)
                   3185:                        ent = xmlGetPredefinedEntity(name);
                   3186:                }
                   3187: 
                   3188:                /*
1.59      daniel   3189:                 * Well Formedness Constraint if:
                   3190:                 *   - standalone
                   3191:                 * or
                   3192:                 *   - no external subset and no external parameter entities
                   3193:                 *     referenced
                   3194:                 * then
                   3195:                 *   the entity referenced must have been declared
                   3196:                 *
1.72      daniel   3197:                 * TODO: to be double checked !!! This is wrong !
1.59      daniel   3198:                 */
1.77      daniel   3199:                if (ent == NULL) {
                   3200:                    if (ctxt->sax != NULL) {
1.72      daniel   3201:                    if (((ctxt->sax->isStandalone != NULL) &&
1.77      daniel   3202:                         ctxt->sax->isStandalone(ctxt->userData) == 1) ||
1.72      daniel   3203:                        (((ctxt->sax->hasInternalSubset == NULL) ||
1.74      daniel   3204:                          ctxt->sax->hasInternalSubset(ctxt->userData) == 0) &&
1.72      daniel   3205:                         ((ctxt->sax->hasExternalSubset == NULL) ||
1.74      daniel   3206:                          ctxt->sax->hasExternalSubset(ctxt->userData) == 0))) {
1.77      daniel   3207:                        if (ctxt->sax->error != NULL)
                   3208:                            ctxt->sax->error(ctxt->userData, 
                   3209:                                 "Entity '%s' not defined\n", name);
                   3210:                        ctxt->wellFormed = 0;
                   3211:                    }
                   3212:                    } else {
                   3213:                        fprintf(stderr, "Entity '%s' not defined\n", name);
                   3214:                        ctxt->wellFormed = 0;
1.59      daniel   3215:                    }
1.77      daniel   3216:                }
1.59      daniel   3217: 
                   3218:                /*
                   3219:                 * Well Formedness Constraint :
                   3220:                 *   The referenced entity must be a parsed entity.
                   3221:                 */
                   3222:                if (ent != NULL) {
                   3223:                    switch (ent->type) {
                   3224:                        case XML_INTERNAL_PARAMETER_ENTITY:
                   3225:                        case XML_EXTERNAL_PARAMETER_ENTITY:
                   3226:                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3227:                            ctxt->sax->error(ctxt->userData, 
1.59      daniel   3228:                     "Attempt to reference the parameter entity '%s'\n", name);
                   3229:                        ctxt->wellFormed = 0;
                   3230:                        break;
                   3231:                         
                   3232:                        case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                   3233:                        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3234:                            ctxt->sax->error(ctxt->userData, 
1.59      daniel   3235:                     "Attempt to reference unparsed entity '%s'\n", name);
                   3236:                        ctxt->wellFormed = 0;
                   3237:                        break;
                   3238:                    }
                   3239:                }
                   3240: 
                   3241:                /*
1.77      daniel   3242:                 * TODO: !!!
1.59      daniel   3243:                 * Well Formedness Constraint :
                   3244:                 *   The referenced entity must not lead to recursion !
                   3245:                 */
                   3246:                 
1.77      daniel   3247: 
1.24      daniel   3248:            } else {
1.55      daniel   3249:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3250:                    ctxt->sax->error(ctxt->userData,
1.59      daniel   3251:                                     "xmlParseEntityRef: expecting ';'\n");
                   3252:                ctxt->wellFormed = 0;
1.24      daniel   3253:            }
1.45      daniel   3254:            free(name);
1.24      daniel   3255:        }
                   3256:     }
1.77      daniel   3257:     return(ent);
1.24      daniel   3258: }
                   3259: 
1.50      daniel   3260: /**
                   3261:  * xmlParsePEReference:
                   3262:  * @ctxt:  an XML parser context
                   3263:  *
                   3264:  * parse PEReference declarations
1.77      daniel   3265:  * The entity content is handled directly by pushing it's content as
                   3266:  * a new input stream.
1.22      daniel   3267:  *
                   3268:  * [69] PEReference ::= '%' Name ';'
1.68      daniel   3269:  *
1.22      daniel   3270:  */
1.77      daniel   3271: void
1.55      daniel   3272: xmlParsePEReference(xmlParserCtxtPtr ctxt) {
1.22      daniel   3273:     CHAR *name;
1.72      daniel   3274:     xmlEntityPtr entity = NULL;
1.50      daniel   3275:     xmlParserInputPtr input;
1.22      daniel   3276: 
1.40      daniel   3277:     if (CUR == '%') {
                   3278:         NEXT;
1.22      daniel   3279:         name = xmlParseName(ctxt);
                   3280:        if (name == NULL) {
1.55      daniel   3281:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3282:                ctxt->sax->error(ctxt->userData, "xmlParsePEReference: no name\n");
1.59      daniel   3283:            ctxt->wellFormed = 0;
1.22      daniel   3284:        } else {
1.40      daniel   3285:            if (CUR == ';') {
                   3286:                NEXT;
1.72      daniel   3287:                if ((ctxt->sax != NULL) && (ctxt->sax->getEntity != NULL))
1.79      daniel   3288:                    entity = ctxt->sax->getEntity(ctxt->userData, name);
1.72      daniel   3289:                /* TODO !!!! Must check that it's of the proper type !!! */
1.45      daniel   3290:                if (entity == NULL) {
1.55      daniel   3291:                    if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1.74      daniel   3292:                        ctxt->sax->warning(ctxt->userData,
1.59      daniel   3293:                         "xmlParsePEReference: %%%s; not found\n", name);
1.50      daniel   3294:                } else {
                   3295:                    input = xmlNewEntityInputStream(ctxt, entity);
                   3296:                    xmlPushInput(ctxt, input);
1.45      daniel   3297:                }
1.22      daniel   3298:            } else {
1.55      daniel   3299:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3300:                    ctxt->sax->error(ctxt->userData,
1.59      daniel   3301:                                     "xmlParsePEReference: expecting ';'\n");
                   3302:                ctxt->wellFormed = 0;
1.22      daniel   3303:            }
1.45      daniel   3304:            free(name);
1.3       veillard 3305:        }
                   3306:     }
                   3307: }
                   3308: 
1.50      daniel   3309: /**
                   3310:  * xmlParseDocTypeDecl :
                   3311:  * @ctxt:  an XML parser context
                   3312:  *
                   3313:  * parse a DOCTYPE declaration
1.21      daniel   3314:  *
1.22      daniel   3315:  * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? 
                   3316:  *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
1.21      daniel   3317:  */
                   3318: 
1.55      daniel   3319: void
                   3320: xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
1.21      daniel   3321:     CHAR *name;
                   3322:     CHAR *ExternalID = NULL;
1.39      daniel   3323:     CHAR *URI = NULL;
1.21      daniel   3324: 
                   3325:     /*
                   3326:      * We know that '<!DOCTYPE' has been detected.
                   3327:      */
1.40      daniel   3328:     SKIP(9);
1.21      daniel   3329: 
1.42      daniel   3330:     SKIP_BLANKS;
1.21      daniel   3331: 
                   3332:     /*
                   3333:      * Parse the DOCTYPE name.
                   3334:      */
                   3335:     name = xmlParseName(ctxt);
                   3336:     if (name == NULL) {
1.55      daniel   3337:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3338:            ctxt->sax->error(ctxt->userData, "xmlParseDocTypeDecl : no DOCTYPE name !\n");
1.59      daniel   3339:        ctxt->wellFormed = 0;
1.21      daniel   3340:     }
                   3341: 
1.42      daniel   3342:     SKIP_BLANKS;
1.21      daniel   3343: 
                   3344:     /*
1.22      daniel   3345:      * Check for SystemID and ExternalID
                   3346:      */
1.67      daniel   3347:     URI = xmlParseExternalID(ctxt, &ExternalID, 1);
1.42      daniel   3348:     SKIP_BLANKS;
1.36      daniel   3349: 
1.76      daniel   3350:     /*
                   3351:      * NOTE: the SAX callback may try to fetch the external subset
                   3352:      *       entity and fill it up !
                   3353:      */
1.72      daniel   3354:     if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL))
1.74      daniel   3355:        ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
1.22      daniel   3356: 
                   3357:     /*
                   3358:      * Is there any DTD definition ?
                   3359:      */
1.40      daniel   3360:     if (CUR == '[') {
                   3361:         NEXT;
1.22      daniel   3362:        /*
                   3363:         * Parse the succession of Markup declarations and 
                   3364:         * PEReferences.
                   3365:         * Subsequence (markupdecl | PEReference | S)*
                   3366:         */
1.40      daniel   3367:        while (CUR != ']') {
                   3368:            const CHAR *check = CUR_PTR;
1.22      daniel   3369: 
1.42      daniel   3370:            SKIP_BLANKS;
1.22      daniel   3371:            xmlParseMarkupDecl(ctxt);
1.50      daniel   3372:            xmlParsePEReference(ctxt);
1.22      daniel   3373: 
1.40      daniel   3374:            if (CUR_PTR == check) {
1.55      daniel   3375:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3376:                    ctxt->sax->error(ctxt->userData, 
1.31      daniel   3377:                 "xmlParseDocTypeDecl: error detected in Markup declaration\n");
1.59      daniel   3378:                ctxt->wellFormed = 0;
1.22      daniel   3379:                break;
                   3380:            }
1.77      daniel   3381: 
                   3382:            /*
                   3383:             * Pop-up of finished entities.
                   3384:             */
                   3385:            while ((CUR == 0) && (ctxt->inputNr > 1))
                   3386:                xmlPopInput(ctxt);
                   3387: 
1.22      daniel   3388:        }
1.40      daniel   3389:        if (CUR == ']') NEXT;
1.22      daniel   3390:     }
                   3391: 
                   3392:     /*
                   3393:      * We should be at the end of the DOCTYPE declaration.
1.21      daniel   3394:      */
1.40      daniel   3395:     if (CUR != '>') {
1.55      daniel   3396:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3397:            ctxt->sax->error(ctxt->userData, "DOCTYPE unproperly terminated\n");
1.59      daniel   3398:        ctxt->wellFormed = 0;
1.22      daniel   3399:         /* We shouldn't try to resynchronize ... */
1.21      daniel   3400:     }
1.40      daniel   3401:     NEXT;
1.22      daniel   3402: 
                   3403:     /*
                   3404:      * Cleanup, since we don't use all those identifiers
                   3405:      * TODO : the DOCTYPE if available should be stored !
                   3406:      */
1.39      daniel   3407:     if (URI != NULL) free(URI);
1.22      daniel   3408:     if (ExternalID != NULL) free(ExternalID);
                   3409:     if (name != NULL) free(name);
1.21      daniel   3410: }
                   3411: 
1.50      daniel   3412: /**
                   3413:  * xmlParseAttribute:
                   3414:  * @ctxt:  an XML parser context
1.72      daniel   3415:  * @value:  a CHAR ** used to store the value of the attribute
1.50      daniel   3416:  *
                   3417:  * parse an attribute
1.3       veillard 3418:  *
1.22      daniel   3419:  * [41] Attribute ::= Name Eq AttValue
                   3420:  *
                   3421:  * [25] Eq ::= S? '=' S?
                   3422:  *
1.29      daniel   3423:  * With namespace:
                   3424:  *
                   3425:  * [NS 11] Attribute ::= QName Eq AttValue
1.43      daniel   3426:  *
                   3427:  * Also the case QName == xmlns:??? is handled independently as a namespace
                   3428:  * definition.
1.69      daniel   3429:  *
1.72      daniel   3430:  * Returns the attribute name, and the value in *value.
1.3       veillard 3431:  */
                   3432: 
1.72      daniel   3433: CHAR *
                   3434: xmlParseAttribute(xmlParserCtxtPtr ctxt, CHAR **value) {
1.59      daniel   3435:     CHAR *name, *val;
1.3       veillard 3436: 
1.72      daniel   3437:     *value = NULL;
                   3438:     name = xmlParseName(ctxt);
1.22      daniel   3439:     if (name == NULL) {
1.55      daniel   3440:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3441:            ctxt->sax->error(ctxt->userData, "error parsing attribute name\n");
1.59      daniel   3442:        ctxt->wellFormed = 0;
1.52      daniel   3443:         return(NULL);
1.3       veillard 3444:     }
                   3445: 
                   3446:     /*
1.29      daniel   3447:      * read the value
1.3       veillard 3448:      */
1.42      daniel   3449:     SKIP_BLANKS;
1.40      daniel   3450:     if (CUR == '=') {
                   3451:         NEXT;
1.42      daniel   3452:        SKIP_BLANKS;
1.72      daniel   3453:        val = xmlParseAttValue(ctxt);
1.29      daniel   3454:     } else {
1.55      daniel   3455:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3456:            ctxt->sax->error(ctxt->userData,
1.59      daniel   3457:               "Specification mandate value for attribute %s\n", name);
                   3458:        ctxt->wellFormed = 0;
1.52      daniel   3459:        return(NULL);
1.43      daniel   3460:     }
                   3461: 
1.72      daniel   3462:     *value = val;
                   3463:     return(name);
1.3       veillard 3464: }
                   3465: 
1.50      daniel   3466: /**
                   3467:  * xmlParseStartTag:
                   3468:  * @ctxt:  an XML parser context
                   3469:  * 
                   3470:  * parse a start of tag either for rule element or
                   3471:  * EmptyElement. In both case we don't parse the tag closing chars.
1.27      daniel   3472:  *
                   3473:  * [40] STag ::= '<' Name (S Attribute)* S? '>'
                   3474:  *
1.29      daniel   3475:  * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
                   3476:  *
                   3477:  * With namespace:
                   3478:  *
                   3479:  * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
                   3480:  *
                   3481:  * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
1.83      daniel   3482:  *
                   3483:  * Returns the element name parsed
1.2       veillard 3484:  */
                   3485: 
1.83      daniel   3486: CHAR *
1.69      daniel   3487: xmlParseStartTag(xmlParserCtxtPtr ctxt) {
1.72      daniel   3488:     CHAR *name;
                   3489:     CHAR *attname;
                   3490:     CHAR *attvalue;
                   3491:     const CHAR **atts = NULL;
                   3492:     int nbatts = 0;
                   3493:     int maxatts = 0;
                   3494:     int i;
1.2       veillard 3495: 
1.83      daniel   3496:     if (CUR != '<') return(NULL);
1.40      daniel   3497:     NEXT;
1.3       veillard 3498: 
1.72      daniel   3499:     name = xmlParseName(ctxt);
1.59      daniel   3500:     if (name == NULL) {
                   3501:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3502:            ctxt->sax->error(ctxt->userData, 
1.59      daniel   3503:             "xmlParseStartTag: invalid element name\n");
                   3504:        ctxt->wellFormed = 0;
1.83      daniel   3505:         return(NULL);
1.50      daniel   3506:     }
                   3507: 
                   3508:     /*
1.3       veillard 3509:      * Now parse the attributes, it ends up with the ending
                   3510:      *
                   3511:      * (S Attribute)* S?
                   3512:      */
1.42      daniel   3513:     SKIP_BLANKS;
1.40      daniel   3514:     while ((IS_CHAR(CUR)) &&
                   3515:            (CUR != '>') && 
                   3516:           ((CUR != '/') || (NXT(1) != '>'))) {
                   3517:        const CHAR *q = CUR_PTR;
1.29      daniel   3518: 
1.72      daniel   3519:        attname = xmlParseAttribute(ctxt, &attvalue);
                   3520:         if ((attname != NULL) && (attvalue != NULL)) {
                   3521:            /*
                   3522:             * Well formedness requires at most one declaration of an attribute
                   3523:             */
                   3524:            for (i = 0; i < nbatts;i += 2) {
                   3525:                if (!xmlStrcmp(atts[i], attname)) {
                   3526:                    if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3527:                        ctxt->sax->error(ctxt->userData, "Attribute %s redefined\n",
1.72      daniel   3528:                                         name);
                   3529:                    ctxt->wellFormed = 0;
                   3530:                    free(attname);
                   3531:                    free(attvalue);
                   3532:                    break;
                   3533:                }
                   3534:            }
                   3535: 
                   3536:            /*
                   3537:             * Add the pair to atts
                   3538:             */
                   3539:            if (atts == NULL) {
                   3540:                maxatts = 10;
                   3541:                atts = (const CHAR **) malloc(maxatts * sizeof(CHAR *));
                   3542:                if (atts == NULL) {
                   3543:                    fprintf(stderr, "malloc of %d byte failed\n",
                   3544:                            maxatts * sizeof(CHAR *));
1.83      daniel   3545:                    return(NULL);
1.72      daniel   3546:                }
                   3547:            } else if (nbatts + 2 < maxatts) {
                   3548:                maxatts *= 2;
                   3549:                atts = (const CHAR **) realloc(atts, maxatts * sizeof(CHAR *));
                   3550:                if (atts == NULL) {
                   3551:                    fprintf(stderr, "realloc of %d byte failed\n",
                   3552:                            maxatts * sizeof(CHAR *));
1.83      daniel   3553:                    return(NULL);
1.72      daniel   3554:                }
                   3555:            }
                   3556:            atts[nbatts++] = attname;
                   3557:            atts[nbatts++] = attvalue;
                   3558:            atts[nbatts] = NULL;
                   3559:            atts[nbatts + 1] = NULL;
                   3560:        }
                   3561: 
1.42      daniel   3562:        SKIP_BLANKS;
1.40      daniel   3563:         if (q == CUR_PTR) {
1.55      daniel   3564:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3565:                ctxt->sax->error(ctxt->userData, 
1.31      daniel   3566:                 "xmlParseStartTag: problem parsing attributes\n");
1.59      daniel   3567:            ctxt->wellFormed = 0;
1.29      daniel   3568:            break;
1.3       veillard 3569:        }
                   3570:     }
                   3571: 
1.43      daniel   3572:     /*
1.72      daniel   3573:      * SAX: Start of Element !
1.43      daniel   3574:      */
1.72      daniel   3575:     if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
1.74      daniel   3576:         ctxt->sax->startElement(ctxt->userData, name, atts);
1.43      daniel   3577: 
1.72      daniel   3578:     if (atts != NULL) {
                   3579:         for (i = 0;i < nbatts;i++) free((CHAR *) atts[i]);
                   3580:        free(atts);
                   3581:     }
1.83      daniel   3582:     return(name);
1.3       veillard 3583: }
                   3584: 
1.50      daniel   3585: /**
                   3586:  * xmlParseEndTag:
                   3587:  * @ctxt:  an XML parser context
1.83      daniel   3588:  * @tagname:  the tag name as parsed in the opening tag.
1.50      daniel   3589:  *
                   3590:  * parse an end of tag
1.27      daniel   3591:  *
                   3592:  * [42] ETag ::= '</' Name S? '>'
1.29      daniel   3593:  *
                   3594:  * With namespace
                   3595:  *
1.72      daniel   3596:  * [NS 9] ETag ::= '</' QName S? '>'
1.7       veillard 3597:  */
                   3598: 
1.55      daniel   3599: void
1.83      daniel   3600: xmlParseEndTag(xmlParserCtxtPtr ctxt, CHAR *tagname) {
1.72      daniel   3601:     CHAR *name;
1.7       veillard 3602: 
1.40      daniel   3603:     if ((CUR != '<') || (NXT(1) != '/')) {
1.55      daniel   3604:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3605:            ctxt->sax->error(ctxt->userData, "xmlParseEndTag: '</' not found\n");
1.59      daniel   3606:        ctxt->wellFormed = 0;
1.27      daniel   3607:        return;
                   3608:     }
1.40      daniel   3609:     SKIP(2);
1.7       veillard 3610: 
1.72      daniel   3611:     name = xmlParseName(ctxt);
1.7       veillard 3612: 
                   3613:     /*
                   3614:      * We should definitely be at the ending "S? '>'" part
                   3615:      */
1.42      daniel   3616:     SKIP_BLANKS;
1.40      daniel   3617:     if ((!IS_CHAR(CUR)) || (CUR != '>')) {
1.55      daniel   3618:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3619:            ctxt->sax->error(ctxt->userData, "End tag : expected '>'\n");
1.59      daniel   3620:        ctxt->wellFormed = 0;
1.7       veillard 3621:     } else
1.40      daniel   3622:        NEXT;
1.7       veillard 3623: 
1.72      daniel   3624:     /*
1.83      daniel   3625:      * Well formedness constraints, opening and closing must match.
                   3626:      */
                   3627:     if (xmlStrcmp(name, tagname)) {
                   3628:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
                   3629:            ctxt->sax->error(ctxt->userData,
                   3630:             "Opening and ending tag mismatch: %s and %s\n", tagname, name);
                   3631:        ctxt->wellFormed = 0;
                   3632:     }
                   3633: 
                   3634:     /*
1.72      daniel   3635:      * SAX: End of Tag
                   3636:      */
                   3637:     if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
1.74      daniel   3638:         ctxt->sax->endElement(ctxt->userData, name);
1.72      daniel   3639: 
                   3640:     if (name != NULL)
                   3641:        free(name);
                   3642: 
1.7       veillard 3643:     return;
                   3644: }
                   3645: 
1.50      daniel   3646: /**
                   3647:  * xmlParseCDSect:
                   3648:  * @ctxt:  an XML parser context
                   3649:  * 
                   3650:  * Parse escaped pure raw content.
1.29      daniel   3651:  *
                   3652:  * [18] CDSect ::= CDStart CData CDEnd
                   3653:  *
                   3654:  * [19] CDStart ::= '<![CDATA['
                   3655:  *
                   3656:  * [20] Data ::= (Char* - (Char* ']]>' Char*))
                   3657:  *
                   3658:  * [21] CDEnd ::= ']]>'
1.3       veillard 3659:  */
1.55      daniel   3660: void
                   3661: xmlParseCDSect(xmlParserCtxtPtr ctxt) {
1.17      daniel   3662:     const CHAR *r, *s, *base;
1.3       veillard 3663: 
1.40      daniel   3664:     if ((CUR == '<') && (NXT(1) == '!') &&
                   3665:        (NXT(2) == '[') && (NXT(3) == 'C') &&
                   3666:        (NXT(4) == 'D') && (NXT(5) == 'A') &&
                   3667:        (NXT(6) == 'T') && (NXT(7) == 'A') &&
                   3668:        (NXT(8) == '[')) {
                   3669:        SKIP(9);
1.29      daniel   3670:     } else
1.45      daniel   3671:         return;
1.40      daniel   3672:     base = CUR_PTR;
                   3673:     if (!IS_CHAR(CUR)) {
1.55      daniel   3674:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3675:            ctxt->sax->error(ctxt->userData, "CData section not finished\n%.50s\n", base);
1.59      daniel   3676:        ctxt->wellFormed = 0;
1.45      daniel   3677:         return;
1.3       veillard 3678:     }
1.40      daniel   3679:     r = NEXT;
                   3680:     if (!IS_CHAR(CUR)) {
1.55      daniel   3681:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3682:            ctxt->sax->error(ctxt->userData, "CData section not finished\n%.50s\n", base);
1.59      daniel   3683:        ctxt->wellFormed = 0;
1.45      daniel   3684:         return;
1.3       veillard 3685:     }
1.40      daniel   3686:     s = NEXT;
                   3687:     while (IS_CHAR(CUR) &&
                   3688:            ((*r != ']') || (*s != ']') || (CUR != '>'))) {
                   3689:         r++;s++;NEXT;
1.3       veillard 3690:     }
1.40      daniel   3691:     if (!IS_CHAR(CUR)) {
1.55      daniel   3692:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3693:            ctxt->sax->error(ctxt->userData, "CData section not finished\n%.50s\n", base);
1.59      daniel   3694:        ctxt->wellFormed = 0;
1.45      daniel   3695:         return;
1.3       veillard 3696:     }
1.16      daniel   3697: 
1.45      daniel   3698:     /*
                   3699:      * Ok the segment [base CUR_PTR] is to be consumed as chars.
                   3700:      */
                   3701:     if (ctxt->sax != NULL) {
1.72      daniel   3702:        if (areBlanks(ctxt, base, CUR_PTR - base)) {
                   3703:            if (ctxt->sax->ignorableWhitespace != NULL)
1.74      daniel   3704:                ctxt->sax->ignorableWhitespace(ctxt->userData, base,
1.72      daniel   3705:                                               (CUR_PTR - base) - 2);
                   3706:         } else {
                   3707:            if (ctxt->sax->characters != NULL)
1.74      daniel   3708:                ctxt->sax->characters(ctxt->userData, base, (CUR_PTR - base) - 2);
1.72      daniel   3709:         }
1.45      daniel   3710:     }
1.2       veillard 3711: }
                   3712: 
1.50      daniel   3713: /**
                   3714:  * xmlParseContent:
                   3715:  * @ctxt:  an XML parser context
                   3716:  *
                   3717:  * Parse a content:
1.2       veillard 3718:  *
1.27      daniel   3719:  * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
1.2       veillard 3720:  */
                   3721: 
1.55      daniel   3722: void
                   3723: xmlParseContent(xmlParserCtxtPtr ctxt) {
1.40      daniel   3724:     while ((CUR != '<') || (NXT(1) != '/')) {
                   3725:        const CHAR *test = CUR_PTR;
1.27      daniel   3726: 
                   3727:        /*
                   3728:         * First case : a Processing Instruction.
                   3729:         */
1.40      daniel   3730:        if ((CUR == '<') && (NXT(1) == '?')) {
1.27      daniel   3731:            xmlParsePI(ctxt);
                   3732:        }
1.72      daniel   3733: 
1.27      daniel   3734:        /*
                   3735:         * Second case : a CDSection
                   3736:         */
1.40      daniel   3737:        else if ((CUR == '<') && (NXT(1) == '!') &&
                   3738:            (NXT(2) == '[') && (NXT(3) == 'C') &&
                   3739:            (NXT(4) == 'D') && (NXT(5) == 'A') &&
                   3740:            (NXT(6) == 'T') && (NXT(7) == 'A') &&
                   3741:            (NXT(8) == '[')) {
1.45      daniel   3742:            xmlParseCDSect(ctxt);
1.27      daniel   3743:        }
1.72      daniel   3744: 
1.27      daniel   3745:        /*
                   3746:         * Third case :  a comment
                   3747:         */
1.40      daniel   3748:        else if ((CUR == '<') && (NXT(1) == '!') &&
                   3749:                 (NXT(2) == '-') && (NXT(3) == '-')) {
1.72      daniel   3750:            xmlParseComment(ctxt, 1);
1.27      daniel   3751:        }
1.72      daniel   3752: 
1.27      daniel   3753:        /*
                   3754:         * Fourth case :  a sub-element.
                   3755:         */
1.40      daniel   3756:        else if (CUR == '<') {
1.72      daniel   3757:            xmlParseElement(ctxt);
1.45      daniel   3758:        }
1.72      daniel   3759: 
1.45      daniel   3760:        /*
1.50      daniel   3761:         * Fifth case : a reference. If if has not been resolved,
                   3762:         *    parsing returns it's Name, create the node 
1.45      daniel   3763:         */
                   3764:        else if (CUR == '&') {
1.77      daniel   3765:            xmlParseReference(ctxt);
1.27      daniel   3766:        }
1.72      daniel   3767: 
1.27      daniel   3768:        /*
                   3769:         * Last case, text. Note that References are handled directly.
                   3770:         */
                   3771:        else {
1.45      daniel   3772:            xmlParseCharData(ctxt, 0);
1.3       veillard 3773:        }
1.14      veillard 3774: 
                   3775:        /*
1.45      daniel   3776:         * Pop-up of finished entities.
1.14      veillard 3777:         */
1.69      daniel   3778:        while ((CUR == 0) && (ctxt->inputNr > 1))
                   3779:            xmlPopInput(ctxt);
1.45      daniel   3780: 
1.40      daniel   3781:        if (test == CUR_PTR) {
1.55      daniel   3782:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3783:                ctxt->sax->error(ctxt->userData,
1.59      daniel   3784:                     "detected an error in element content\n");
                   3785:            ctxt->wellFormed = 0;
1.29      daniel   3786:             break;
                   3787:        }
1.3       veillard 3788:     }
1.2       veillard 3789: }
                   3790: 
1.50      daniel   3791: /**
                   3792:  * xmlParseElement:
                   3793:  * @ctxt:  an XML parser context
                   3794:  *
                   3795:  * parse an XML element, this is highly recursive
1.26      daniel   3796:  *
                   3797:  * [39] element ::= EmptyElemTag | STag content ETag
                   3798:  *
                   3799:  * [41] Attribute ::= Name Eq AttValue
1.2       veillard 3800:  */
1.26      daniel   3801: 
1.72      daniel   3802: void
1.69      daniel   3803: xmlParseElement(xmlParserCtxtPtr ctxt) {
1.40      daniel   3804:     const CHAR *openTag = CUR_PTR;
1.83      daniel   3805:     CHAR *name;
1.32      daniel   3806:     xmlParserNodeInfo node_info;
1.2       veillard 3807: 
1.32      daniel   3808:     /* Capture start position */
1.40      daniel   3809:     node_info.begin_pos = CUR_PTR - ctxt->input->base;
                   3810:     node_info.begin_line = ctxt->input->line;
1.32      daniel   3811: 
1.83      daniel   3812:     name = xmlParseStartTag(ctxt);
                   3813:     if (name == NULL) {
                   3814:         return;
                   3815:     }
1.2       veillard 3816: 
                   3817:     /*
                   3818:      * Check for an Empty Element.
                   3819:      */
1.40      daniel   3820:     if ((CUR == '/') && (NXT(1) == '>')) {
                   3821:         SKIP(2);
1.72      daniel   3822:        if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL))
1.83      daniel   3823:            ctxt->sax->endElement(ctxt->userData, name);
                   3824:        free(name);
1.72      daniel   3825:        return;
1.2       veillard 3826:     }
1.40      daniel   3827:     if (CUR == '>') NEXT;
1.2       veillard 3828:     else {
1.55      daniel   3829:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3830:            ctxt->sax->error(ctxt->userData, "Couldn't find end of Start Tag\n%.30s\n",
1.57      daniel   3831:                             openTag);
1.59      daniel   3832:        ctxt->wellFormed = 0;
1.45      daniel   3833: 
                   3834:        /*
                   3835:         * end of parsing of this node.
                   3836:         */
                   3837:        nodePop(ctxt);
1.83      daniel   3838:        free(name);
1.72      daniel   3839:        return;
1.2       veillard 3840:     }
                   3841: 
                   3842:     /*
                   3843:      * Parse the content of the element:
                   3844:      */
1.45      daniel   3845:     xmlParseContent(ctxt);
1.40      daniel   3846:     if (!IS_CHAR(CUR)) {
1.55      daniel   3847:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3848:            ctxt->sax->error(ctxt->userData,
1.57      daniel   3849:                 "Premature end of data in tag %.30s\n", openTag);
1.59      daniel   3850:        ctxt->wellFormed = 0;
1.45      daniel   3851: 
                   3852:        /*
                   3853:         * end of parsing of this node.
                   3854:         */
                   3855:        nodePop(ctxt);
1.83      daniel   3856:        free(name);
1.72      daniel   3857:        return;
1.2       veillard 3858:     }
                   3859: 
                   3860:     /*
1.27      daniel   3861:      * parse the end of tag: '</' should be here.
1.2       veillard 3862:      */
1.83      daniel   3863:     xmlParseEndTag(ctxt, name);
                   3864:     free(name);
1.2       veillard 3865: }
                   3866: 
1.50      daniel   3867: /**
                   3868:  * xmlParseVersionNum:
                   3869:  * @ctxt:  an XML parser context
                   3870:  *
                   3871:  * parse the XML version value.
1.29      daniel   3872:  *
                   3873:  * [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
1.68      daniel   3874:  *
                   3875:  * Returns the string giving the XML version number, or NULL
1.29      daniel   3876:  */
1.55      daniel   3877: CHAR *
                   3878: xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
1.40      daniel   3879:     const CHAR *q = CUR_PTR;
1.29      daniel   3880:     CHAR *ret;
                   3881: 
1.40      daniel   3882:     while (IS_CHAR(CUR) &&
                   3883:            (((CUR >= 'a') && (CUR <= 'z')) ||
                   3884:             ((CUR >= 'A') && (CUR <= 'Z')) ||
                   3885:             ((CUR >= '0') && (CUR <= '9')) ||
                   3886:             (CUR == '_') || (CUR == '.') ||
                   3887:            (CUR == ':') || (CUR == '-'))) NEXT;
                   3888:     ret = xmlStrndup(q, CUR_PTR - q);
1.29      daniel   3889:     return(ret);
                   3890: }
                   3891: 
1.50      daniel   3892: /**
                   3893:  * xmlParseVersionInfo:
                   3894:  * @ctxt:  an XML parser context
                   3895:  * 
                   3896:  * parse the XML version.
1.29      daniel   3897:  *
                   3898:  * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
                   3899:  * 
                   3900:  * [25] Eq ::= S? '=' S?
1.50      daniel   3901:  *
1.68      daniel   3902:  * Returns the version string, e.g. "1.0"
1.29      daniel   3903:  */
                   3904: 
1.55      daniel   3905: CHAR *
                   3906: xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
1.29      daniel   3907:     CHAR *version = NULL;
                   3908:     const CHAR *q;
                   3909: 
1.40      daniel   3910:     if ((CUR == 'v') && (NXT(1) == 'e') &&
                   3911:         (NXT(2) == 'r') && (NXT(3) == 's') &&
                   3912:        (NXT(4) == 'i') && (NXT(5) == 'o') &&
                   3913:        (NXT(6) == 'n')) {
                   3914:        SKIP(7);
1.42      daniel   3915:        SKIP_BLANKS;
1.40      daniel   3916:        if (CUR != '=') {
1.55      daniel   3917:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3918:                ctxt->sax->error(ctxt->userData, "xmlParseVersionInfo : expected '='\n");
1.59      daniel   3919:            ctxt->wellFormed = 0;
1.31      daniel   3920:            return(NULL);
                   3921:         }
1.40      daniel   3922:        NEXT;
1.42      daniel   3923:        SKIP_BLANKS;
1.40      daniel   3924:        if (CUR == '"') {
                   3925:            NEXT;
                   3926:            q = CUR_PTR;
1.29      daniel   3927:            version = xmlParseVersionNum(ctxt);
1.55      daniel   3928:            if (CUR != '"') {
                   3929:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3930:                    ctxt->sax->error(ctxt->userData, "String not closed\n%.50s\n", q);
1.59      daniel   3931:                ctxt->wellFormed = 0;
1.55      daniel   3932:            } else
1.40      daniel   3933:                NEXT;
                   3934:        } else if (CUR == '\''){
                   3935:            NEXT;
                   3936:            q = CUR_PTR;
1.29      daniel   3937:            version = xmlParseVersionNum(ctxt);
1.55      daniel   3938:            if (CUR != '\'') {
                   3939:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3940:                    ctxt->sax->error(ctxt->userData, "String not closed\n%.50s\n", q);
1.59      daniel   3941:                ctxt->wellFormed = 0;
1.55      daniel   3942:            } else
1.40      daniel   3943:                NEXT;
1.31      daniel   3944:        } else {
1.55      daniel   3945:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3946:                ctxt->sax->error(ctxt->userData,
1.59      daniel   3947:                      "xmlParseVersionInfo : expected ' or \"\n");
                   3948:                ctxt->wellFormed = 0;
1.29      daniel   3949:        }
                   3950:     }
                   3951:     return(version);
                   3952: }
                   3953: 
1.50      daniel   3954: /**
                   3955:  * xmlParseEncName:
                   3956:  * @ctxt:  an XML parser context
                   3957:  *
                   3958:  * parse the XML encoding name
1.29      daniel   3959:  *
                   3960:  * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
1.50      daniel   3961:  *
1.68      daniel   3962:  * Returns the encoding name value or NULL
1.29      daniel   3963:  */
1.55      daniel   3964: CHAR *
                   3965: xmlParseEncName(xmlParserCtxtPtr ctxt) {
1.40      daniel   3966:     const CHAR *q = CUR_PTR;
1.29      daniel   3967:     CHAR *ret = NULL;
                   3968: 
1.40      daniel   3969:     if (((CUR >= 'a') && (CUR <= 'z')) ||
                   3970:         ((CUR >= 'A') && (CUR <= 'Z'))) {
                   3971:        NEXT;
                   3972:        while (IS_CHAR(CUR) &&
                   3973:               (((CUR >= 'a') && (CUR <= 'z')) ||
                   3974:                ((CUR >= 'A') && (CUR <= 'Z')) ||
                   3975:                ((CUR >= '0') && (CUR <= '9')) ||
                   3976:                (CUR == '-'))) NEXT;
                   3977:        ret = xmlStrndup(q, CUR_PTR - q);
1.29      daniel   3978:     } else {
1.55      daniel   3979:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   3980:            ctxt->sax->error(ctxt->userData, "Invalid XML encoding name\n");
1.59      daniel   3981:        ctxt->wellFormed = 0;
1.29      daniel   3982:     }
                   3983:     return(ret);
                   3984: }
                   3985: 
1.50      daniel   3986: /**
                   3987:  * xmlParseEncodingDecl:
                   3988:  * @ctxt:  an XML parser context
                   3989:  * 
                   3990:  * parse the XML encoding declaration
1.29      daniel   3991:  *
                   3992:  * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
1.50      daniel   3993:  *
                   3994:  * TODO: this should setup the conversion filters.
                   3995:  *
1.68      daniel   3996:  * Returns the encoding value or NULL
1.29      daniel   3997:  */
                   3998: 
1.55      daniel   3999: CHAR *
                   4000: xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
1.29      daniel   4001:     CHAR *encoding = NULL;
                   4002:     const CHAR *q;
                   4003: 
1.42      daniel   4004:     SKIP_BLANKS;
1.40      daniel   4005:     if ((CUR == 'e') && (NXT(1) == 'n') &&
                   4006:         (NXT(2) == 'c') && (NXT(3) == 'o') &&
                   4007:        (NXT(4) == 'd') && (NXT(5) == 'i') &&
                   4008:        (NXT(6) == 'n') && (NXT(7) == 'g')) {
                   4009:        SKIP(8);
1.42      daniel   4010:        SKIP_BLANKS;
1.40      daniel   4011:        if (CUR != '=') {
1.55      daniel   4012:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4013:                ctxt->sax->error(ctxt->userData, "xmlParseEncodingDecl : expected '='\n");
1.59      daniel   4014:            ctxt->wellFormed = 0;
1.31      daniel   4015:            return(NULL);
                   4016:         }
1.40      daniel   4017:        NEXT;
1.42      daniel   4018:        SKIP_BLANKS;
1.40      daniel   4019:        if (CUR == '"') {
                   4020:            NEXT;
                   4021:            q = CUR_PTR;
1.29      daniel   4022:            encoding = xmlParseEncName(ctxt);
1.55      daniel   4023:            if (CUR != '"') {
                   4024:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4025:                    ctxt->sax->error(ctxt->userData, "String not closed\n%.50s\n", q);
1.59      daniel   4026:                ctxt->wellFormed = 0;
1.55      daniel   4027:            } else
1.40      daniel   4028:                NEXT;
                   4029:        } else if (CUR == '\''){
                   4030:            NEXT;
                   4031:            q = CUR_PTR;
1.29      daniel   4032:            encoding = xmlParseEncName(ctxt);
1.55      daniel   4033:            if (CUR != '\'') {
                   4034:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4035:                    ctxt->sax->error(ctxt->userData, "String not closed\n%.50s\n", q);
1.59      daniel   4036:                ctxt->wellFormed = 0;
1.55      daniel   4037:            } else
1.40      daniel   4038:                NEXT;
                   4039:        } else if (CUR == '"'){
1.55      daniel   4040:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4041:                ctxt->sax->error(ctxt->userData,
1.59      daniel   4042:                     "xmlParseEncodingDecl : expected ' or \"\n");
                   4043:            ctxt->wellFormed = 0;
1.29      daniel   4044:        }
                   4045:     }
                   4046:     return(encoding);
                   4047: }
                   4048: 
1.50      daniel   4049: /**
                   4050:  * xmlParseSDDecl:
                   4051:  * @ctxt:  an XML parser context
                   4052:  *
                   4053:  * parse the XML standalone declaration
1.29      daniel   4054:  *
                   4055:  * [32] SDDecl ::= S 'standalone' Eq
                   4056:  *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"')) 
1.68      daniel   4057:  *
                   4058:  * Returns 1 if standalone, 0 otherwise
1.29      daniel   4059:  */
                   4060: 
1.55      daniel   4061: int
                   4062: xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
1.29      daniel   4063:     int standalone = -1;
                   4064: 
1.42      daniel   4065:     SKIP_BLANKS;
1.40      daniel   4066:     if ((CUR == 's') && (NXT(1) == 't') &&
                   4067:         (NXT(2) == 'a') && (NXT(3) == 'n') &&
                   4068:        (NXT(4) == 'd') && (NXT(5) == 'a') &&
                   4069:        (NXT(6) == 'l') && (NXT(7) == 'o') &&
                   4070:        (NXT(8) == 'n') && (NXT(9) == 'e')) {
                   4071:        SKIP(10);
1.81      daniel   4072:         SKIP_BLANKS;
1.40      daniel   4073:        if (CUR != '=') {
1.55      daniel   4074:            if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4075:                ctxt->sax->error(ctxt->userData,
1.59      daniel   4076:                    "XML standalone declaration : expected '='\n");
                   4077:            ctxt->wellFormed = 0;
1.32      daniel   4078:            return(standalone);
                   4079:         }
1.40      daniel   4080:        NEXT;
1.42      daniel   4081:        SKIP_BLANKS;
1.40      daniel   4082:         if (CUR == '\''){
                   4083:            NEXT;
                   4084:            if ((CUR == 'n') && (NXT(1) == 'o')) {
1.29      daniel   4085:                standalone = 0;
1.40      daniel   4086:                 SKIP(2);
                   4087:            } else if ((CUR == 'y') && (NXT(1) == 'e') &&
                   4088:                       (NXT(2) == 's')) {
1.29      daniel   4089:                standalone = 1;
1.40      daniel   4090:                SKIP(3);
1.29      daniel   4091:             } else {
1.55      daniel   4092:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4093:                    ctxt->sax->error(ctxt->userData, "standalone accepts only 'yes' or 'no'\n");
1.59      daniel   4094:                ctxt->wellFormed = 0;
1.29      daniel   4095:            }
1.55      daniel   4096:            if (CUR != '\'') {
                   4097:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4098:                    ctxt->sax->error(ctxt->userData, "String not closed\n");
1.59      daniel   4099:                ctxt->wellFormed = 0;
1.55      daniel   4100:            } else
1.40      daniel   4101:                NEXT;
                   4102:        } else if (CUR == '"'){
                   4103:            NEXT;
                   4104:            if ((CUR == 'n') && (NXT(1) == 'o')) {
1.29      daniel   4105:                standalone = 0;
1.40      daniel   4106:                SKIP(2);
                   4107:            } else if ((CUR == 'y') && (NXT(1) == 'e') &&
                   4108:                       (NXT(2) == 's')) {
1.29      daniel   4109:                standalone = 1;
1.40      daniel   4110:                 SKIP(3);
1.29      daniel   4111:             } else {
1.55      daniel   4112:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4113:                    ctxt->sax->error(ctxt->userData,
1.59      daniel   4114:                        "standalone accepts only 'yes' or 'no'\n");
                   4115:                ctxt->wellFormed = 0;
1.29      daniel   4116:            }
1.55      daniel   4117:            if (CUR != '"') {
                   4118:                if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4119:                    ctxt->sax->error(ctxt->userData, "String not closed\n");
1.59      daniel   4120:                ctxt->wellFormed = 0;
1.55      daniel   4121:            } else
1.40      daniel   4122:                NEXT;
1.37      daniel   4123:        } else {
1.55      daniel   4124:             if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4125:                ctxt->sax->error(ctxt->userData, "Standalone value not found\n");
1.59      daniel   4126:            ctxt->wellFormed = 0;
1.37      daniel   4127:         }
1.29      daniel   4128:     }
                   4129:     return(standalone);
                   4130: }
                   4131: 
1.50      daniel   4132: /**
                   4133:  * xmlParseXMLDecl:
                   4134:  * @ctxt:  an XML parser context
                   4135:  * 
                   4136:  * parse an XML declaration header
1.29      daniel   4137:  *
                   4138:  * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
1.1       veillard 4139:  */
                   4140: 
1.55      daniel   4141: void
                   4142: xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
1.1       veillard 4143:     CHAR *version;
                   4144: 
                   4145:     /*
1.19      daniel   4146:      * We know that '<?xml' is here.
1.1       veillard 4147:      */
1.40      daniel   4148:     SKIP(5);
1.1       veillard 4149: 
1.59      daniel   4150:     if (!IS_BLANK(CUR)) {
                   4151:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4152:            ctxt->sax->error(ctxt->userData, "Blank needed after '<?xml'\n");
1.59      daniel   4153:        ctxt->wellFormed = 0;
                   4154:     }
1.42      daniel   4155:     SKIP_BLANKS;
1.1       veillard 4156: 
                   4157:     /*
1.29      daniel   4158:      * We should have the VersionInfo here.
1.1       veillard 4159:      */
1.29      daniel   4160:     version = xmlParseVersionInfo(ctxt);
                   4161:     if (version == NULL)
1.45      daniel   4162:        version = xmlCharStrdup(XML_DEFAULT_VERSION);
1.72      daniel   4163:     ctxt->version = xmlStrdup(version);
1.45      daniel   4164:     free(version);
1.29      daniel   4165: 
                   4166:     /*
                   4167:      * We may have the encoding declaration
                   4168:      */
1.59      daniel   4169:     if (!IS_BLANK(CUR)) {
                   4170:         if ((CUR == '?') && (NXT(1) == '>')) {
                   4171:            SKIP(2);
                   4172:            return;
                   4173:        }
                   4174:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4175:            ctxt->sax->error(ctxt->userData, "Blank needed here\n");
1.59      daniel   4176:        ctxt->wellFormed = 0;
                   4177:     }
1.72      daniel   4178:     ctxt->encoding = xmlParseEncodingDecl(ctxt);
1.1       veillard 4179: 
                   4180:     /*
1.29      daniel   4181:      * We may have the standalone status.
1.1       veillard 4182:      */
1.72      daniel   4183:     if ((ctxt->encoding != NULL) && (!IS_BLANK(CUR))) {
1.59      daniel   4184:         if ((CUR == '?') && (NXT(1) == '>')) {
                   4185:            SKIP(2);
                   4186:            return;
                   4187:        }
                   4188:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4189:            ctxt->sax->error(ctxt->userData, "Blank needed here\n");
1.59      daniel   4190:        ctxt->wellFormed = 0;
                   4191:     }
                   4192:     SKIP_BLANKS;
1.72      daniel   4193:     ctxt->standalone = xmlParseSDDecl(ctxt);
1.1       veillard 4194: 
1.42      daniel   4195:     SKIP_BLANKS;
1.40      daniel   4196:     if ((CUR == '?') && (NXT(1) == '>')) {
                   4197:         SKIP(2);
                   4198:     } else if (CUR == '>') {
1.31      daniel   4199:         /* Deprecated old WD ... */
1.55      daniel   4200:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4201:            ctxt->sax->error(ctxt->userData, "XML declaration must end-up with '?>'\n");
1.59      daniel   4202:        ctxt->wellFormed = 0;
1.40      daniel   4203:        NEXT;
1.29      daniel   4204:     } else {
1.55      daniel   4205:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4206:            ctxt->sax->error(ctxt->userData, "parsing XML declaration: '?>' expected\n");
1.59      daniel   4207:        ctxt->wellFormed = 0;
1.40      daniel   4208:        MOVETO_ENDTAG(CUR_PTR);
                   4209:        NEXT;
1.29      daniel   4210:     }
1.1       veillard 4211: }
                   4212: 
1.50      daniel   4213: /**
                   4214:  * xmlParseMisc:
                   4215:  * @ctxt:  an XML parser context
                   4216:  * 
                   4217:  * parse an XML Misc* optionnal field.
1.21      daniel   4218:  *
1.22      daniel   4219:  * [27] Misc ::= Comment | PI |  S
1.1       veillard 4220:  */
                   4221: 
1.55      daniel   4222: void
                   4223: xmlParseMisc(xmlParserCtxtPtr ctxt) {
1.40      daniel   4224:     while (((CUR == '<') && (NXT(1) == '?')) ||
                   4225:            ((CUR == '<') && (NXT(1) == '!') &&
                   4226:            (NXT(2) == '-') && (NXT(3) == '-')) ||
                   4227:            IS_BLANK(CUR)) {
                   4228:         if ((CUR == '<') && (NXT(1) == '?')) {
1.16      daniel   4229:            xmlParsePI(ctxt);
1.40      daniel   4230:        } else if (IS_BLANK(CUR)) {
                   4231:            NEXT;
1.1       veillard 4232:        } else
1.31      daniel   4233:            xmlParseComment(ctxt, 0);
1.1       veillard 4234:     }
                   4235: }
                   4236: 
1.50      daniel   4237: /**
                   4238:  * xmlParseDocument :
                   4239:  * @ctxt:  an XML parser context
                   4240:  * 
                   4241:  * parse an XML document (and build a tree if using the standard SAX
                   4242:  * interface).
1.21      daniel   4243:  *
1.22      daniel   4244:  * [1] document ::= prolog element Misc*
1.29      daniel   4245:  *
                   4246:  * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
1.50      daniel   4247:  *
1.68      daniel   4248:  * Returns 0, -1 in case of error. the parser context is augmented
1.50      daniel   4249:  *                as a result of the parsing.
1.1       veillard 4250:  */
                   4251: 
1.55      daniel   4252: int
                   4253: xmlParseDocument(xmlParserCtxtPtr ctxt) {
1.45      daniel   4254:     xmlDefaultSAXHandlerInit();
                   4255: 
1.14      veillard 4256:     /*
1.44      daniel   4257:      * SAX: beginning of the document processing.
                   4258:      */
1.72      daniel   4259:     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
1.74      daniel   4260:         ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
1.44      daniel   4261: 
                   4262:     /*
1.14      veillard 4263:      * We should check for encoding here and plug-in some
                   4264:      * conversion code TODO !!!!
                   4265:      */
1.1       veillard 4266: 
                   4267:     /*
                   4268:      * Wipe out everything which is before the first '<'
                   4269:      */
1.59      daniel   4270:     if (IS_BLANK(CUR)) {
                   4271:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4272:            ctxt->sax->error(ctxt->userData,
1.59      daniel   4273:            "Extra spaces at the beginning of the document are not allowed\n");
                   4274:        ctxt->wellFormed = 0;
                   4275:        SKIP_BLANKS;
                   4276:     }
                   4277: 
                   4278:     if (CUR == 0) {
                   4279:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4280:            ctxt->sax->error(ctxt->userData, "Document is empty\n");
1.59      daniel   4281:        ctxt->wellFormed = 0;
                   4282:     }
1.1       veillard 4283: 
                   4284:     /*
                   4285:      * Check for the XMLDecl in the Prolog.
                   4286:      */
1.40      daniel   4287:     if ((CUR == '<') && (NXT(1) == '?') &&
                   4288:         (NXT(2) == 'x') && (NXT(3) == 'm') &&
                   4289:        (NXT(4) == 'l')) {
1.19      daniel   4290:        xmlParseXMLDecl(ctxt);
                   4291:        /* SKIP_EOL(cur); */
1.42      daniel   4292:        SKIP_BLANKS;
1.40      daniel   4293:     } else if ((CUR == '<') && (NXT(1) == '?') &&
                   4294:         (NXT(2) == 'X') && (NXT(3) == 'M') &&
                   4295:        (NXT(4) == 'L')) {
1.19      daniel   4296:        /*
                   4297:         * The first drafts were using <?XML and the final W3C REC
                   4298:         * now use <?xml ...
                   4299:         */
1.16      daniel   4300:        xmlParseXMLDecl(ctxt);
1.1       veillard 4301:        /* SKIP_EOL(cur); */
1.42      daniel   4302:        SKIP_BLANKS;
1.1       veillard 4303:     } else {
1.72      daniel   4304:        ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
1.1       veillard 4305:     }
1.72      daniel   4306:     if ((ctxt->sax) && (ctxt->sax->startDocument))
1.74      daniel   4307:         ctxt->sax->startDocument(ctxt->userData);
1.1       veillard 4308: 
                   4309:     /*
                   4310:      * The Misc part of the Prolog
                   4311:      */
1.16      daniel   4312:     xmlParseMisc(ctxt);
1.1       veillard 4313: 
                   4314:     /*
1.29      daniel   4315:      * Then possibly doc type declaration(s) and more Misc
1.21      daniel   4316:      * (doctypedecl Misc*)?
                   4317:      */
1.40      daniel   4318:     if ((CUR == '<') && (NXT(1) == '!') &&
                   4319:        (NXT(2) == 'D') && (NXT(3) == 'O') &&
                   4320:        (NXT(4) == 'C') && (NXT(5) == 'T') &&
                   4321:        (NXT(6) == 'Y') && (NXT(7) == 'P') &&
                   4322:        (NXT(8) == 'E')) {
1.22      daniel   4323:        xmlParseDocTypeDecl(ctxt);
                   4324:        xmlParseMisc(ctxt);
1.21      daniel   4325:     }
                   4326: 
                   4327:     /*
                   4328:      * Time to start parsing the tree itself
1.1       veillard 4329:      */
1.72      daniel   4330:     xmlParseElement(ctxt);
1.33      daniel   4331: 
                   4332:     /*
                   4333:      * The Misc part at the end
                   4334:      */
                   4335:     xmlParseMisc(ctxt);
1.16      daniel   4336: 
1.59      daniel   4337:     if (CUR != 0) {
                   4338:        if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   4339:            ctxt->sax->error(ctxt->userData,
1.59      daniel   4340:                "Extra content at the end of the document\n");
                   4341:        ctxt->wellFormed = 0;
                   4342:     }
                   4343: 
1.44      daniel   4344:     /*
                   4345:      * SAX: end of the document processing.
                   4346:      */
1.72      daniel   4347:     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
1.74      daniel   4348:         ctxt->sax->endDocument(ctxt->userData);
1.59      daniel   4349:     if (! ctxt->wellFormed) return(-1);
1.16      daniel   4350:     return(0);
                   4351: }
                   4352: 
1.50      daniel   4353: /**
1.69      daniel   4354:  * xmlCreateFileParserCtxt :
1.50      daniel   4355:  * @cur:  a pointer to an array of CHAR
                   4356:  *
1.69      daniel   4357:  * Create a parser context for an XML in-memory document.
                   4358:  *
                   4359:  * Returns the new parser context or NULL
1.16      daniel   4360:  */
1.69      daniel   4361: xmlParserCtxtPtr
                   4362: xmlCreateDocParserCtxt(CHAR *cur) {
1.16      daniel   4363:     xmlParserCtxtPtr ctxt;
1.40      daniel   4364:     xmlParserInputPtr input;
1.75      daniel   4365:     xmlCharEncoding enc;
1.16      daniel   4366: 
                   4367:     ctxt = (xmlParserCtxtPtr) malloc(sizeof(xmlParserCtxt));
                   4368:     if (ctxt == NULL) {
                   4369:         perror("malloc");
                   4370:        return(NULL);
                   4371:     }
1.40      daniel   4372:     xmlInitParserCtxt(ctxt);
                   4373:     input = (xmlParserInputPtr) malloc(sizeof(xmlParserInput));
                   4374:     if (input == NULL) {
                   4375:         perror("malloc");
                   4376:        free(ctxt);
                   4377:        return(NULL);
                   4378:     }
                   4379: 
1.75      daniel   4380:     /*
                   4381:      * plug some encoding conversion routines here. !!!
                   4382:      */
                   4383:     enc = xmlDetectCharEncoding(cur);
                   4384:     xmlSwitchEncoding(ctxt, enc);
                   4385: 
1.40      daniel   4386:     input->filename = NULL;
                   4387:     input->line = 1;
                   4388:     input->col = 1;
                   4389:     input->base = cur;
                   4390:     input->cur = cur;
1.69      daniel   4391:     input->free = NULL;
1.40      daniel   4392: 
                   4393:     inputPush(ctxt, input);
1.69      daniel   4394:     return(ctxt);
                   4395: }
                   4396: 
                   4397: /**
                   4398:  * xmlSAXParseDoc :
                   4399:  * @sax:  the SAX handler block
                   4400:  * @cur:  a pointer to an array of CHAR
                   4401:  * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
                   4402:  *             documents
                   4403:  *
                   4404:  * parse an XML in-memory document and build a tree.
                   4405:  * It use the given SAX function block to handle the parsing callback.
                   4406:  * If sax is NULL, fallback to the default DOM tree building routines.
                   4407:  * 
                   4408:  * Returns the resulting document tree
                   4409:  */
                   4410: 
                   4411: xmlDocPtr
                   4412: xmlSAXParseDoc(xmlSAXHandlerPtr sax, CHAR *cur, int recovery) {
                   4413:     xmlDocPtr ret;
                   4414:     xmlParserCtxtPtr ctxt;
                   4415: 
                   4416:     if (cur == NULL) return(NULL);
1.16      daniel   4417: 
                   4418: 
1.69      daniel   4419:     ctxt = xmlCreateDocParserCtxt(cur);
                   4420:     if (ctxt == NULL) return(NULL);
1.74      daniel   4421:     if (sax != NULL) { 
                   4422:         ctxt->sax = sax;
                   4423:         ctxt->userData = NULL;
                   4424:     }
1.69      daniel   4425: 
1.16      daniel   4426:     xmlParseDocument(ctxt);
1.72      daniel   4427:     if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
1.59      daniel   4428:     else {
                   4429:        ret = NULL;
1.72      daniel   4430:        xmlFreeDoc(ctxt->myDoc);
                   4431:        ctxt->myDoc = NULL;
1.59      daniel   4432:     }
1.69      daniel   4433:     xmlFreeParserCtxt(ctxt);
1.16      daniel   4434:     
1.1       veillard 4435:     return(ret);
                   4436: }
                   4437: 
1.50      daniel   4438: /**
1.55      daniel   4439:  * xmlParseDoc :
                   4440:  * @cur:  a pointer to an array of CHAR
                   4441:  *
                   4442:  * parse an XML in-memory document and build a tree.
                   4443:  * 
1.68      daniel   4444:  * Returns the resulting document tree
1.55      daniel   4445:  */
                   4446: 
1.69      daniel   4447: xmlDocPtr
                   4448: xmlParseDoc(CHAR *cur) {
1.59      daniel   4449:     return(xmlSAXParseDoc(NULL, cur, 0));
1.76      daniel   4450: }
                   4451: 
                   4452: /**
                   4453:  * xmlSAXParseDTD :
                   4454:  * @sax:  the SAX handler block
                   4455:  * @ExternalID:  a NAME* containing the External ID of the DTD
                   4456:  * @SystemID:  a NAME* containing the URL to the DTD
                   4457:  *
                   4458:  * Load and parse an external subset.
                   4459:  * 
                   4460:  * Returns the resulting xmlDtdPtr or NULL in case of error.
                   4461:  */
                   4462: 
                   4463: xmlDtdPtr
                   4464: xmlSAXParseDTD(xmlSAXHandlerPtr sax, const CHAR *ExternalID,
                   4465:                           const CHAR *SystemID) {
                   4466:     xmlDtdPtr ret = NULL;
                   4467:     xmlParserCtxtPtr ctxt;
1.83      daniel   4468:     xmlParserInputPtr input = NULL;
1.76      daniel   4469:     xmlCharEncoding enc;
                   4470: 
                   4471:     if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
                   4472: 
                   4473:     ctxt = (xmlParserCtxtPtr) malloc(sizeof(xmlParserCtxt));
                   4474:     if (ctxt == NULL) {
                   4475:         perror("malloc");
                   4476:        return(NULL);
                   4477:     }
                   4478:     xmlInitParserCtxt(ctxt);
                   4479: 
                   4480:     /*
                   4481:      * Set-up the SAX context
                   4482:      */
                   4483:     if (ctxt == NULL) return(NULL);
                   4484:     if (sax != NULL) { 
                   4485:         ctxt->sax = sax;
                   4486:         ctxt->userData = NULL;
                   4487:     }
                   4488: 
                   4489:     /*
                   4490:      * Ask the Entity resolver to load the damn thing
                   4491:      */
                   4492: 
                   4493:     if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
                   4494:        input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID, SystemID);
                   4495:     if (input == NULL) {
                   4496:        xmlFreeParserCtxt(ctxt);
                   4497:        return(NULL);
                   4498:     }
                   4499: 
                   4500:     /*
                   4501:      * plug some encoding conversion routines here. !!!
                   4502:      */
                   4503:     xmlPushInput(ctxt, input);
                   4504:     enc = xmlDetectCharEncoding(ctxt->input->cur);
                   4505:     xmlSwitchEncoding(ctxt, enc);
                   4506: 
                   4507:     input->filename = xmlStrdup(SystemID);
                   4508:     input->line = 1;
                   4509:     input->col = 1;
                   4510:     input->base = ctxt->input->cur;
                   4511:     input->cur = ctxt->input->cur;
                   4512:     input->free = NULL;
                   4513: 
                   4514:     /*
                   4515:      * let's parse that entity knowing it's an external subset.
                   4516:      */
1.79      daniel   4517:     xmlParseExternalSubset(ctxt, ExternalID, SystemID);
1.76      daniel   4518: 
                   4519:     if (ctxt->myDoc != NULL) {
                   4520:        if (ctxt->wellFormed) {
                   4521:            ret = ctxt->myDoc->intSubset;
                   4522:            ctxt->myDoc->intSubset = NULL;
                   4523:        } else {
                   4524:            ret = NULL;
                   4525:        }
                   4526:         xmlFreeDoc(ctxt->myDoc);
                   4527:         ctxt->myDoc = NULL;
                   4528:     }
                   4529:     xmlFreeParserCtxt(ctxt);
                   4530:     
                   4531:     return(ret);
                   4532: }
                   4533: 
                   4534: /**
                   4535:  * xmlParseDTD :
                   4536:  * @ExternalID:  a NAME* containing the External ID of the DTD
                   4537:  * @SystemID:  a NAME* containing the URL to the DTD
                   4538:  *
                   4539:  * Load and parse an external subset.
                   4540:  * 
                   4541:  * Returns the resulting xmlDtdPtr or NULL in case of error.
                   4542:  */
                   4543: 
                   4544: xmlDtdPtr
                   4545: xmlParseDTD(const CHAR *ExternalID, const CHAR *SystemID) {
                   4546:     return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
1.59      daniel   4547: }
                   4548: 
                   4549: /**
                   4550:  * xmlRecoverDoc :
                   4551:  * @cur:  a pointer to an array of CHAR
                   4552:  *
                   4553:  * parse an XML in-memory document and build a tree.
                   4554:  * In the case the document is not Well Formed, a tree is built anyway
                   4555:  * 
1.68      daniel   4556:  * Returns the resulting document tree
1.59      daniel   4557:  */
                   4558: 
1.69      daniel   4559: xmlDocPtr
                   4560: xmlRecoverDoc(CHAR *cur) {
1.59      daniel   4561:     return(xmlSAXParseDoc(NULL, cur, 1));
1.55      daniel   4562: }
                   4563: 
                   4564: /**
1.69      daniel   4565:  * xmlCreateFileParserCtxt :
1.50      daniel   4566:  * @filename:  the filename
                   4567:  *
1.69      daniel   4568:  * Create a parser context for a file content. 
                   4569:  * Automatic support for ZLIB/Compress compressed document is provided
                   4570:  * by default if found at compile-time.
1.50      daniel   4571:  *
1.69      daniel   4572:  * Returns the new parser context or NULL
1.9       httpng   4573:  */
1.69      daniel   4574: xmlParserCtxtPtr
                   4575: xmlCreateFileParserCtxt(const char *filename)
                   4576: {
                   4577:     xmlParserCtxtPtr ctxt;
1.20      daniel   4578: #ifdef HAVE_ZLIB_H
                   4579:     gzFile input;
                   4580: #else
1.9       httpng   4581:     int input;
1.20      daniel   4582: #endif
1.9       httpng   4583:     int res;
1.55      daniel   4584:     int len;
1.9       httpng   4585:     struct stat buf;
                   4586:     char *buffer;
1.40      daniel   4587:     xmlParserInputPtr inputStream;
1.75      daniel   4588:     xmlCharEncoding enc;
1.9       httpng   4589: 
1.11      veillard 4590:     res = stat(filename, &buf);
1.9       httpng   4591:     if (res < 0) return(NULL);
                   4592: 
1.20      daniel   4593: #ifdef HAVE_ZLIB_H
1.55      daniel   4594:     len = (buf.st_size * 8) + 1000;
1.20      daniel   4595: retry_bigger:
1.55      daniel   4596:     buffer = malloc(len);
1.20      daniel   4597: #else
1.55      daniel   4598:     len = buf.st_size + 100;
                   4599:     buffer = malloc(len);
1.20      daniel   4600: #endif
1.9       httpng   4601:     if (buffer == NULL) {
                   4602:        perror("malloc");
                   4603:         return(NULL);
                   4604:     }
                   4605: 
1.55      daniel   4606:     memset(buffer, 0, len);
1.20      daniel   4607: #ifdef HAVE_ZLIB_H
                   4608:     input = gzopen (filename, "r");
                   4609:     if (input == NULL) {
                   4610:         fprintf (stderr, "Cannot read file %s :\n", filename);
                   4611:        perror ("gzopen failed");
                   4612:        return(NULL);
                   4613:     }
                   4614: #else
1.72      daniel   4615: #ifdef WIN32
                   4616:     input = _open (filename, O_RDONLY | _O_BINARY);
                   4617: #else
1.9       httpng   4618:     input = open (filename, O_RDONLY);
1.72      daniel   4619: #endif
1.9       httpng   4620:     if (input < 0) {
                   4621:         fprintf (stderr, "Cannot read file %s :\n", filename);
                   4622:        perror ("open failed");
                   4623:        return(NULL);
                   4624:     }
1.20      daniel   4625: #endif
                   4626: #ifdef HAVE_ZLIB_H
1.55      daniel   4627:     res = gzread(input, buffer, len);
1.20      daniel   4628: #else
1.9       httpng   4629:     res = read(input, buffer, buf.st_size);
1.20      daniel   4630: #endif
1.9       httpng   4631:     if (res < 0) {
                   4632:         fprintf (stderr, "Cannot read file %s :\n", filename);
1.20      daniel   4633: #ifdef HAVE_ZLIB_H
                   4634:        perror ("gzread failed");
                   4635: #else
1.9       httpng   4636:        perror ("read failed");
1.20      daniel   4637: #endif
1.9       httpng   4638:        return(NULL);
                   4639:     }
1.20      daniel   4640: #ifdef HAVE_ZLIB_H
                   4641:     gzclose(input);
1.55      daniel   4642:     if (res >= len) {
1.20      daniel   4643:         free(buffer);
1.55      daniel   4644:        len *= 2;
1.20      daniel   4645:        goto retry_bigger;
                   4646:     }
                   4647:     buf.st_size = res;
                   4648: #else
1.9       httpng   4649:     close(input);
1.20      daniel   4650: #endif
                   4651: 
1.40      daniel   4652:     buffer[buf.st_size] = '\0';
1.9       httpng   4653: 
1.16      daniel   4654:     ctxt = (xmlParserCtxtPtr) malloc(sizeof(xmlParserCtxt));
                   4655:     if (ctxt == NULL) {
                   4656:         perror("malloc");
                   4657:        return(NULL);
                   4658:     }
1.40      daniel   4659:     xmlInitParserCtxt(ctxt);
                   4660:     inputStream = (xmlParserInputPtr) malloc(sizeof(xmlParserInput));
                   4661:     if (inputStream == NULL) {
                   4662:         perror("malloc");
                   4663:        free(ctxt);
                   4664:        return(NULL);
                   4665:     }
                   4666: 
                   4667:     inputStream->filename = strdup(filename);
                   4668:     inputStream->line = 1;
                   4669:     inputStream->col = 1;
1.45      daniel   4670: 
                   4671:     /*
1.75      daniel   4672:      * plug some encoding conversion routines here. !!!
1.45      daniel   4673:      */
1.75      daniel   4674:     enc = xmlDetectCharEncoding(buffer);
                   4675:     xmlSwitchEncoding(ctxt, enc);
                   4676: 
1.40      daniel   4677:     inputStream->base = buffer;
                   4678:     inputStream->cur = buffer;
1.69      daniel   4679:     inputStream->free = (xmlParserInputDeallocate) free;
1.16      daniel   4680: 
1.40      daniel   4681:     inputPush(ctxt, inputStream);
1.69      daniel   4682:     return(ctxt);
                   4683: }
                   4684: 
                   4685: /**
                   4686:  * xmlSAXParseFile :
                   4687:  * @sax:  the SAX handler block
                   4688:  * @filename:  the filename
                   4689:  * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
                   4690:  *             documents
                   4691:  *
                   4692:  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
                   4693:  * compressed document is provided by default if found at compile-time.
                   4694:  * It use the given SAX function block to handle the parsing callback.
                   4695:  * If sax is NULL, fallback to the default DOM tree building routines.
                   4696:  *
                   4697:  * Returns the resulting document tree
                   4698:  */
                   4699: 
1.79      daniel   4700: xmlDocPtr
                   4701: xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
1.69      daniel   4702:                           int recovery) {
                   4703:     xmlDocPtr ret;
                   4704:     xmlParserCtxtPtr ctxt;
                   4705: 
                   4706:     ctxt = xmlCreateFileParserCtxt(filename);
                   4707:     if (ctxt == NULL) return(NULL);
1.74      daniel   4708:     if (sax != NULL) {
                   4709:         ctxt->sax = sax;
                   4710:         ctxt->userData = NULL;
                   4711:     }
1.16      daniel   4712: 
                   4713:     xmlParseDocument(ctxt);
1.40      daniel   4714: 
1.72      daniel   4715:     if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
1.59      daniel   4716:     else {
                   4717:        ret = NULL;
1.72      daniel   4718:        xmlFreeDoc(ctxt->myDoc);
                   4719:        ctxt->myDoc = NULL;
1.59      daniel   4720:     }
1.69      daniel   4721:     xmlFreeParserCtxt(ctxt);
1.20      daniel   4722:     
                   4723:     return(ret);
                   4724: }
                   4725: 
1.55      daniel   4726: /**
                   4727:  * xmlParseFile :
                   4728:  * @filename:  the filename
                   4729:  *
                   4730:  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
                   4731:  * compressed document is provided by default if found at compile-time.
                   4732:  *
1.68      daniel   4733:  * Returns the resulting document tree
1.55      daniel   4734:  */
                   4735: 
1.79      daniel   4736: xmlDocPtr
                   4737: xmlParseFile(const char *filename) {
1.59      daniel   4738:     return(xmlSAXParseFile(NULL, filename, 0));
                   4739: }
                   4740: 
                   4741: /**
                   4742:  * xmlRecoverFile :
                   4743:  * @filename:  the filename
                   4744:  *
                   4745:  * parse an XML file and build a tree. Automatic support for ZLIB/Compress
                   4746:  * compressed document is provided by default if found at compile-time.
                   4747:  * In the case the document is not Well Formed, a tree is built anyway
                   4748:  *
1.68      daniel   4749:  * Returns the resulting document tree
1.59      daniel   4750:  */
                   4751: 
1.79      daniel   4752: xmlDocPtr
                   4753: xmlRecoverFile(const char *filename) {
1.59      daniel   4754:     return(xmlSAXParseFile(NULL, filename, 1));
1.55      daniel   4755: }
1.32      daniel   4756: 
1.50      daniel   4757: /**
1.82      daniel   4758:  * xmlSubstituteEntitiesDefault :
                   4759:  * @val:  int 0 or 1 
1.79      daniel   4760:  *
                   4761:  * Set and return the previous value for default entity support.
                   4762:  * Initially the parser always keep entity references instead of substituting
                   4763:  * entity values in the output. This function has to be used to change the
                   4764:  * default parser behaviour
                   4765:  * SAX::subtituteEntities() has to be used for changing that on a file by
                   4766:  * file basis.
                   4767:  *
                   4768:  * Returns the last value for 0 for no substitution, 1 for substitution.
                   4769:  */
                   4770: 
                   4771: int
                   4772: xmlSubstituteEntitiesDefault(int val) {
                   4773:     int old = xmlSubstituteEntitiesDefaultValue;
                   4774: 
                   4775:     xmlSubstituteEntitiesDefaultValue = val;
                   4776:     return(old);
                   4777: }
                   4778: 
                   4779: /**
1.69      daniel   4780:  * xmlCreateMemoryParserCtxt :
1.68      daniel   4781:  * @buffer:  an pointer to a char array
1.50      daniel   4782:  * @size:  the siwe of the array
                   4783:  *
1.69      daniel   4784:  * Create a parser context for an XML in-memory document.
1.50      daniel   4785:  *
1.69      daniel   4786:  * Returns the new parser context or NULL
1.20      daniel   4787:  */
1.69      daniel   4788: xmlParserCtxtPtr
                   4789: xmlCreateMemoryParserCtxt(char *buffer, int size) {
1.20      daniel   4790:     xmlParserCtxtPtr ctxt;
1.40      daniel   4791:     xmlParserInputPtr input;
1.75      daniel   4792:     xmlCharEncoding enc;
1.40      daniel   4793: 
                   4794:     buffer[size - 1] = '\0';
                   4795: 
1.20      daniel   4796:     ctxt = (xmlParserCtxtPtr) malloc(sizeof(xmlParserCtxt));
                   4797:     if (ctxt == NULL) {
                   4798:         perror("malloc");
                   4799:        return(NULL);
                   4800:     }
1.40      daniel   4801:     xmlInitParserCtxt(ctxt);
                   4802:     input = (xmlParserInputPtr) malloc(sizeof(xmlParserInput));
                   4803:     if (input == NULL) {
                   4804:         perror("malloc");
1.50      daniel   4805:         free(ctxt->nodeTab);
                   4806:        free(ctxt->inputTab);
1.40      daniel   4807:        free(ctxt);
                   4808:        return(NULL);
                   4809:     }
1.20      daniel   4810: 
1.40      daniel   4811:     input->filename = NULL;
                   4812:     input->line = 1;
                   4813:     input->col = 1;
1.45      daniel   4814: 
                   4815:     /*
1.75      daniel   4816:      * plug some encoding conversion routines here. !!!
1.45      daniel   4817:      */
1.75      daniel   4818:     enc = xmlDetectCharEncoding(buffer);
                   4819:     xmlSwitchEncoding(ctxt, enc);
                   4820: 
1.40      daniel   4821:     input->base = buffer;
                   4822:     input->cur = buffer;
1.69      daniel   4823:     input->free = NULL;
1.20      daniel   4824: 
1.40      daniel   4825:     inputPush(ctxt, input);
1.69      daniel   4826:     return(ctxt);
                   4827: }
                   4828: 
                   4829: /**
                   4830:  * xmlSAXParseMemory :
                   4831:  * @sax:  the SAX handler block
                   4832:  * @buffer:  an pointer to a char array
                   4833:  * @size:  the siwe of the array
                   4834:  * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
                   4835:  *             documents
                   4836:  *
                   4837:  * parse an XML in-memory block and use the given SAX function block
                   4838:  * to handle the parsing callback. If sax is NULL, fallback to the default
                   4839:  * DOM tree building routines.
                   4840:  * 
                   4841:  * Returns the resulting document tree
                   4842:  */
                   4843: xmlDocPtr
                   4844: xmlSAXParseMemory(xmlSAXHandlerPtr sax, char *buffer, int size, int recovery) {
                   4845:     xmlDocPtr ret;
                   4846:     xmlParserCtxtPtr ctxt;
                   4847: 
                   4848:     ctxt = xmlCreateMemoryParserCtxt(buffer, size);
                   4849:     if (ctxt == NULL) return(NULL);
1.74      daniel   4850:     if (sax != NULL) {
                   4851:         ctxt->sax = sax;
                   4852:         ctxt->userData = NULL;
                   4853:     }
1.20      daniel   4854: 
                   4855:     xmlParseDocument(ctxt);
1.40      daniel   4856: 
1.72      daniel   4857:     if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
1.59      daniel   4858:     else {
                   4859:        ret = NULL;
1.72      daniel   4860:        xmlFreeDoc(ctxt->myDoc);
                   4861:        ctxt->myDoc = NULL;
1.59      daniel   4862:     }
1.69      daniel   4863:     xmlFreeParserCtxt(ctxt);
1.16      daniel   4864:     
1.9       httpng   4865:     return(ret);
1.17      daniel   4866: }
                   4867: 
1.55      daniel   4868: /**
                   4869:  * xmlParseMemory :
1.68      daniel   4870:  * @buffer:  an pointer to a char array
1.55      daniel   4871:  * @size:  the size of the array
                   4872:  *
                   4873:  * parse an XML in-memory block and build a tree.
                   4874:  * 
1.68      daniel   4875:  * Returns the resulting document tree
1.55      daniel   4876:  */
                   4877: 
                   4878: xmlDocPtr xmlParseMemory(char *buffer, int size) {
1.59      daniel   4879:    return(xmlSAXParseMemory(NULL, buffer, size, 0));
                   4880: }
                   4881: 
                   4882: /**
                   4883:  * xmlRecoverMemory :
1.68      daniel   4884:  * @buffer:  an pointer to a char array
1.59      daniel   4885:  * @size:  the size of the array
                   4886:  *
                   4887:  * parse an XML in-memory block and build a tree.
                   4888:  * In the case the document is not Well Formed, a tree is built anyway
                   4889:  * 
1.68      daniel   4890:  * Returns the resulting document tree
1.59      daniel   4891:  */
                   4892: 
                   4893: xmlDocPtr xmlRecoverMemory(char *buffer, int size) {
                   4894:    return(xmlSAXParseMemory(NULL, buffer, size, 1));
1.55      daniel   4895: }
1.17      daniel   4896: 
1.50      daniel   4897: /**
                   4898:  * xmlInitParserCtxt:
                   4899:  * @ctxt:  an XML parser context
                   4900:  *
                   4901:  * Initialize a parser context
                   4902:  */
                   4903: 
1.55      daniel   4904: void
                   4905: xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
1.17      daniel   4906: {
1.69      daniel   4907:     /* Allocate the Input stack */
                   4908:     ctxt->inputTab = (xmlParserInputPtr *) malloc(5 * sizeof(xmlParserInputPtr));
                   4909:     ctxt->inputNr = 0;
                   4910:     ctxt->inputMax = 5;
                   4911:     ctxt->input = NULL;
1.72      daniel   4912:     ctxt->version = NULL;
                   4913:     ctxt->encoding = NULL;
                   4914:     ctxt->standalone = -1;
1.69      daniel   4915: 
                   4916:     /* Allocate the Node stack */
                   4917:     ctxt->nodeTab = (xmlNodePtr *) malloc(10 * sizeof(xmlNodePtr));
                   4918:     ctxt->nodeNr = 0;
                   4919:     ctxt->nodeMax = 10;
                   4920:     ctxt->node = NULL;
                   4921: 
                   4922:     ctxt->sax = &xmlDefaultSAXHandler;
1.74      daniel   4923:     ctxt->userData = ctxt;
1.72      daniel   4924:     ctxt->myDoc = NULL;
1.69      daniel   4925:     ctxt->wellFormed = 1;
1.79      daniel   4926:     ctxt->replaceEntities = xmlSubstituteEntitiesDefaultValue;
1.69      daniel   4927:     ctxt->record_info = 0;
                   4928:     xmlInitNodeInfoSeq(&ctxt->node_seq);
                   4929: }
                   4930: 
                   4931: /**
                   4932:  * xmlFreeParserCtxt:
                   4933:  * @ctxt:  an XML parser context
                   4934:  *
                   4935:  * Free all the memory used by a parser context. However the parsed
1.72      daniel   4936:  * document in ctxt->myDoc is not freed.
1.69      daniel   4937:  */
                   4938: 
                   4939: void
                   4940: xmlFreeParserCtxt(xmlParserCtxtPtr ctxt)
                   4941: {
                   4942:     xmlParserInputPtr input;
                   4943: 
                   4944:     if (ctxt == NULL) return;
                   4945: 
                   4946:     while ((input = inputPop(ctxt)) != NULL) {
                   4947:         xmlFreeInputStream(input);
                   4948:     }
                   4949: 
                   4950:     if (ctxt->nodeTab != NULL) free(ctxt->nodeTab);
                   4951:     if (ctxt->inputTab != NULL) free(ctxt->inputTab);
1.73      daniel   4952:     if (ctxt->version != NULL) free((char *) ctxt->version);
1.69      daniel   4953:     free(ctxt);
1.17      daniel   4954: }
                   4955: 
1.50      daniel   4956: /**
                   4957:  * xmlClearParserCtxt:
                   4958:  * @ctxt:  an XML parser context
                   4959:  *
                   4960:  * Clear (release owned resources) and reinitialize a parser context
                   4961:  */
1.17      daniel   4962: 
1.55      daniel   4963: void
                   4964: xmlClearParserCtxt(xmlParserCtxtPtr ctxt)
1.17      daniel   4965: {
1.32      daniel   4966:   xmlClearNodeInfoSeq(&ctxt->node_seq);
                   4967:   xmlInitParserCtxt(ctxt);
1.17      daniel   4968: }
                   4969: 
                   4970: 
1.50      daniel   4971: /**
                   4972:  * xmlSetupParserForBuffer:
                   4973:  * @ctxt:  an XML parser context
                   4974:  * @buffer:  a CHAR * buffer
                   4975:  * @filename:  a file name
                   4976:  *
1.19      daniel   4977:  * Setup the parser context to parse a new buffer; Clears any prior
                   4978:  * contents from the parser context. The buffer parameter must not be
                   4979:  * NULL, but the filename parameter can be
                   4980:  */
1.55      daniel   4981: void
                   4982: xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const CHAR* buffer,
1.17      daniel   4983:                              const char* filename)
                   4984: {
1.40      daniel   4985:   xmlParserInputPtr input;
                   4986: 
                   4987:   input = (xmlParserInputPtr) malloc(sizeof(xmlParserInput));
                   4988:   if (input == NULL) {
                   4989:       perror("malloc");
                   4990:       free(ctxt);
                   4991:       exit(1);
                   4992:   }
                   4993: 
1.17      daniel   4994:   xmlClearParserCtxt(ctxt);
1.40      daniel   4995:   if (input->filename != NULL)
                   4996:       input->filename = strdup(filename);
                   4997:   else
                   4998:       input->filename = NULL;
                   4999:   input->line = 1;
                   5000:   input->col = 1;
                   5001:   input->base = buffer;
                   5002:   input->cur = buffer;
                   5003: 
                   5004:   inputPush(ctxt, input);
1.17      daniel   5005: }
                   5006: 
1.32      daniel   5007: 
1.50      daniel   5008: /**
                   5009:  * xmlParserFindNodeInfo:
                   5010:  * @ctxt:  an XML parser context
                   5011:  * @node:  an XML node within the tree
                   5012:  *
                   5013:  * Find the parser node info struct for a given node
                   5014:  * 
1.68      daniel   5015:  * Returns an xmlParserNodeInfo block pointer or NULL
1.32      daniel   5016:  */
                   5017: const xmlParserNodeInfo* xmlParserFindNodeInfo(const xmlParserCtxt* ctx,
                   5018:                                                const xmlNode* node)
                   5019: {
                   5020:   unsigned long pos;
                   5021: 
                   5022:   /* Find position where node should be at */
                   5023:   pos = xmlParserFindNodeInfoIndex(&ctx->node_seq, node);
                   5024:   if ( ctx->node_seq.buffer[pos].node == node )
                   5025:     return &ctx->node_seq.buffer[pos];
                   5026:   else
                   5027:     return NULL;
                   5028: }
                   5029: 
                   5030: 
1.50      daniel   5031: /**
                   5032:  * xmlInitNodeInfoSeq :
                   5033:  * @seq:  a node info sequence pointer
                   5034:  *
                   5035:  * -- Initialize (set to initial state) node info sequence
1.32      daniel   5036:  */
1.55      daniel   5037: void
                   5038: xmlInitNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
1.32      daniel   5039: {
                   5040:   seq->length = 0;
                   5041:   seq->maximum = 0;
                   5042:   seq->buffer = NULL;
                   5043: }
                   5044: 
1.50      daniel   5045: /**
                   5046:  * xmlClearNodeInfoSeq :
                   5047:  * @seq:  a node info sequence pointer
                   5048:  *
                   5049:  * -- Clear (release memory and reinitialize) node
1.32      daniel   5050:  *   info sequence
                   5051:  */
1.55      daniel   5052: void
                   5053: xmlClearNodeInfoSeq(xmlParserNodeInfoSeqPtr seq)
1.32      daniel   5054: {
                   5055:   if ( seq->buffer != NULL )
                   5056:     free(seq->buffer);
                   5057:   xmlInitNodeInfoSeq(seq);
                   5058: }
                   5059: 
                   5060: 
1.50      daniel   5061: /**
                   5062:  * xmlParserFindNodeInfoIndex:
                   5063:  * @seq:  a node info sequence pointer
                   5064:  * @node:  an XML node pointer
                   5065:  *
                   5066:  * 
1.32      daniel   5067:  * xmlParserFindNodeInfoIndex : Find the index that the info record for
                   5068:  *   the given node is or should be at in a sorted sequence
1.68      daniel   5069:  *
                   5070:  * Returns a long indicating the position of the record
1.32      daniel   5071:  */
                   5072: unsigned long xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeq* seq,
                   5073:                                          const xmlNode* node)
                   5074: {
                   5075:   unsigned long upper, lower, middle;
                   5076:   int found = 0;
                   5077: 
                   5078:   /* Do a binary search for the key */
                   5079:   lower = 1;
                   5080:   upper = seq->length;
                   5081:   middle = 0;
                   5082:   while ( lower <= upper && !found) {
                   5083:     middle = lower + (upper - lower) / 2;
                   5084:     if ( node == seq->buffer[middle - 1].node )
                   5085:       found = 1;
                   5086:     else if ( node < seq->buffer[middle - 1].node )
                   5087:       upper = middle - 1;
                   5088:     else
                   5089:       lower = middle + 1;
                   5090:   }
                   5091: 
                   5092:   /* Return position */
                   5093:   if ( middle == 0 || seq->buffer[middle - 1].node < node )
                   5094:     return middle;
                   5095:   else 
                   5096:     return middle - 1;
                   5097: }
                   5098: 
                   5099: 
1.50      daniel   5100: /**
                   5101:  * xmlParserAddNodeInfo:
                   5102:  * @ctxt:  an XML parser context
1.68      daniel   5103:  * @info:  a node info sequence pointer
1.50      daniel   5104:  *
                   5105:  * Insert node info record into the sorted sequence
1.32      daniel   5106:  */
1.55      daniel   5107: void
                   5108: xmlParserAddNodeInfo(xmlParserCtxtPtr ctxt, 
1.68      daniel   5109:                      const xmlParserNodeInfo* info)
1.32      daniel   5110: {
                   5111:   unsigned long pos;
                   5112:   static unsigned int block_size = 5;
                   5113: 
                   5114:   /* Find pos and check to see if node is already in the sequence */
1.55      daniel   5115:   pos = xmlParserFindNodeInfoIndex(&ctxt->node_seq, info->node);
                   5116:   if ( pos < ctxt->node_seq.length
                   5117:        && ctxt->node_seq.buffer[pos].node == info->node ) {
                   5118:     ctxt->node_seq.buffer[pos] = *info;
1.32      daniel   5119:   }
                   5120: 
                   5121:   /* Otherwise, we need to add new node to buffer */
                   5122:   else {
                   5123:     /* Expand buffer by 5 if needed */
1.55      daniel   5124:     if ( ctxt->node_seq.length + 1 > ctxt->node_seq.maximum ) {
1.32      daniel   5125:       xmlParserNodeInfo* tmp_buffer;
1.55      daniel   5126:       unsigned int byte_size = (sizeof(*ctxt->node_seq.buffer)
                   5127:                                 *(ctxt->node_seq.maximum + block_size));
1.32      daniel   5128: 
1.55      daniel   5129:       if ( ctxt->node_seq.buffer == NULL )
1.32      daniel   5130:         tmp_buffer = (xmlParserNodeInfo*)malloc(byte_size);
                   5131:       else 
1.55      daniel   5132:         tmp_buffer = (xmlParserNodeInfo*)realloc(ctxt->node_seq.buffer, byte_size);
1.32      daniel   5133: 
                   5134:       if ( tmp_buffer == NULL ) {
1.55      daniel   5135:         if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
1.74      daniel   5136:            ctxt->sax->error(ctxt->userData, "Out of memory\n");
1.32      daniel   5137:         return;
                   5138:       }
1.55      daniel   5139:       ctxt->node_seq.buffer = tmp_buffer;
                   5140:       ctxt->node_seq.maximum += block_size;
1.32      daniel   5141:     }
                   5142: 
                   5143:     /* If position is not at end, move elements out of the way */
1.55      daniel   5144:     if ( pos != ctxt->node_seq.length ) {
1.32      daniel   5145:       unsigned long i;
                   5146: 
1.55      daniel   5147:       for ( i = ctxt->node_seq.length; i > pos; i-- )
                   5148:         ctxt->node_seq.buffer[i] = ctxt->node_seq.buffer[i - 1];
1.32      daniel   5149:     }
                   5150:   
                   5151:     /* Copy element and increase length */
1.55      daniel   5152:     ctxt->node_seq.buffer[pos] = *info;
                   5153:     ctxt->node_seq.length++;
1.32      daniel   5154:   }   
                   5155: }
1.77      daniel   5156: 
                   5157: 

Webmaster