Annotation of XML/parser.c, revision 1.90

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

Webmaster