Annotation of XML/entities.c, revision 1.29

1.1       httpng      1: /*
                      2:  * entities.c : implementation for the XML entities handking
1.9       veillard    3:  *
                      4:  * See Copyright for the status of this software.
                      5:  *
1.23      daniel      6:  * Daniel.Veillard@w3.org
1.1       httpng      7:  */
                      8: 
                      9: #include <stdio.h>
1.17      daniel     10: #include <stdlib.h>
1.10      daniel     11: #include <string.h>
1.1       httpng     12: #include "entities.h"
                     13: 
                     14: /*
1.15      daniel     15:  * The XML predefined entities.
                     16:  */
                     17: 
                     18: struct xmlPredefinedEntityValue {
                     19:     const char *name;
                     20:     const char *value;
                     21: };
                     22: struct xmlPredefinedEntityValue xmlPredefinedEntityValues[] = {
                     23:     { "lt", "<" },
                     24:     { "gt", ">" },
                     25:     { "apos", "'" },
                     26:     { "quot", "\"" },
                     27:     { "amp", "&" }
                     28: };
                     29: 
                     30: xmlEntitiesTablePtr xmlPredefinedEntities = NULL;
                     31: 
                     32: /*
1.2       httpng     33:  * xmlFreeEntity : clean-up an entity record.
1.1       httpng     34:  */
1.2       httpng     35: void xmlFreeEntity(xmlEntityPtr entity) {
                     36:     if (entity == NULL) return;
                     37: 
1.11      daniel     38:     if (entity->name != NULL)
                     39:        free((char *) entity->name);
1.14      daniel     40:     if (entity->ExternalID != NULL)
                     41:         free((char *) entity->ExternalID);
                     42:     if (entity->SystemID != NULL)
                     43:         free((char *) entity->SystemID);
                     44:     if (entity->content != NULL)
                     45:         free((char *) entity->content);
1.27      daniel     46:     if (entity->orig != NULL)
                     47:         free((char *) entity->orig);
1.14      daniel     48:     memset(entity, -1, sizeof(xmlEntity));
1.2       httpng     49: }
1.1       httpng     50: 
                     51: /*
1.22      daniel     52:  * xmlAddEntity : register a new entity for an entities table.
1.13      daniel     53:  *
                     54:  * TODO !!! We should check here that the combination of type
                     55:  *          ExternalID and SystemID is valid.
1.1       httpng     56:  */
1.22      daniel     57: static void
                     58: xmlAddEntity(xmlEntitiesTablePtr table, const CHAR *name, int type,
1.13      daniel     59:               const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
1.2       httpng     60:     int i;
                     61:     xmlEntityPtr cur;
1.14      daniel     62:     int len;
1.1       httpng     63: 
1.2       httpng     64:     for (i = 0;i < table->nb_entities;i++) {
                     65:         cur = &table->table[i];
1.11      daniel     66:        if (!xmlStrcmp(cur->name, name)) {
1.13      daniel     67:            /*
                     68:             * The entity is already defined in this Dtd, the spec says to NOT
                     69:             * override it ... Is it worth a Warning ??? !!!
                     70:             */
                     71:            return;
1.7       veillard   72:        }
1.2       httpng     73:     }
                     74:     if (table->nb_entities >= table->max_entities) {
                     75:         /*
                     76:         * need more elements.
                     77:         */
                     78:        table->max_entities *= 2;
                     79:        table->table = (xmlEntityPtr) 
                     80:            realloc(table->table, table->max_entities * sizeof(xmlEntity));
1.29    ! daniel     81:        if (table->table == NULL) {
1.2       httpng     82:            perror("realloc failed");
1.29    ! daniel     83:            return;
1.2       httpng     84:        }
                     85:     }
                     86:     cur = &table->table[table->nb_entities];
1.11      daniel     87:     cur->name = xmlStrdup(name);
1.14      daniel     88:     for (len = 0;name[0] != 0;name++)len++;
                     89:     cur->len = len;
1.13      daniel     90:     cur->type = type;
                     91:     if (ExternalID != NULL)
                     92:        cur->ExternalID = xmlStrdup(ExternalID);
1.14      daniel     93:     else
                     94:         cur->ExternalID = NULL;
1.13      daniel     95:     if (SystemID != NULL)
1.14      daniel     96:        cur->SystemID = xmlStrdup(SystemID);
                     97:     else
                     98:         cur->SystemID = NULL;
1.13      daniel     99:     if (content != NULL)
                    100:        cur->content = xmlStrdup(content);
1.14      daniel    101:     else
                    102:         cur->content = NULL;
1.27      daniel    103:     cur->orig = NULL;
1.2       httpng    104:     table->nb_entities++;
                    105: }
1.1       httpng    106: 
1.22      daniel    107: /**
                    108:  * xmlInitializePredefinedEntities:
                    109:  *
                    110:  * Set up the predefined entities.
1.15      daniel    111:  */
                    112: void xmlInitializePredefinedEntities(void) {
                    113:     int i;
                    114:     CHAR name[50];
                    115:     CHAR value[50];
                    116:     const char *in;
                    117:     CHAR *out;
                    118: 
                    119:     if (xmlPredefinedEntities != NULL) return;
                    120: 
                    121:     xmlPredefinedEntities = xmlCreateEntitiesTable();
                    122:     for (i = 0;i < sizeof(xmlPredefinedEntityValues) / 
                    123:                    sizeof(xmlPredefinedEntityValues[0]);i++) {
                    124:         in = xmlPredefinedEntityValues[i].name;
                    125:        out = &name[0];
                    126:        for (;(*out++ = (CHAR) *in);)in++;
                    127:         in = xmlPredefinedEntityValues[i].value;
                    128:        out = &value[0];
                    129:        for (;(*out++ = (CHAR) *in);)in++;
                    130:         xmlAddEntity(xmlPredefinedEntities, (const CHAR *) &name[0],
1.18      daniel    131:                     XML_INTERNAL_PREDEFINED_ENTITY, NULL, NULL,
1.15      daniel    132:                     &value[0]);
                    133:     }
                    134: }
1.17      daniel    135: 
                    136: /**
                    137:  * xmlGetPredefinedEntity:
                    138:  * @name:  the entity name
                    139:  *
                    140:  * Check whether this name is an predefined entity.
                    141:  *
1.24      daniel    142:  * Returns NULL if not, othervise the entity
1.17      daniel    143:  */
                    144: xmlEntityPtr
                    145: xmlGetPredefinedEntity(const CHAR *name) {
                    146:     int i;
                    147:     xmlEntityPtr cur;
                    148: 
                    149:     if (xmlPredefinedEntities == NULL)
                    150:         xmlInitializePredefinedEntities();
                    151:     for (i = 0;i < xmlPredefinedEntities->nb_entities;i++) {
                    152:        cur = &xmlPredefinedEntities->table[i];
                    153:        if (!xmlStrcmp(cur->name, name)) return(cur);
                    154:     }
                    155:     return(NULL);
                    156: }
                    157: 
1.22      daniel    158: /**
                    159:  * xmlAddDtdEntity:
                    160:  * @doc:  the document
                    161:  * @name:  the entity name
                    162:  * @type:  the entity type XML_xxx_yyy_ENTITY
                    163:  * @ExternalID:  the entity external ID if available
                    164:  * @SystemID:  the entity system ID if available
                    165:  * @content:  the entity content
                    166:  *
                    167:  * Register a new entity for this document DTD.
1.1       httpng    168:  */
1.22      daniel    169: void
                    170: xmlAddDtdEntity(xmlDocPtr doc, const CHAR *name, int type,
1.13      daniel    171:               const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
1.2       httpng    172:     xmlEntitiesTablePtr table;
1.1       httpng    173: 
1.22      daniel    174:     if (doc->extSubset == NULL) {
                    175:         fprintf(stderr,
                    176:                "xmlAddDtdEntity: document without external subset !\n");
1.16      daniel    177:        return;
                    178:     }
1.22      daniel    179:     table = (xmlEntitiesTablePtr) doc->extSubset->entities;
1.2       httpng    180:     if (table == NULL) {
                    181:         table = xmlCreateEntitiesTable();
1.22      daniel    182:        doc->extSubset->entities = table;
1.1       httpng    183:     }
1.13      daniel    184:     xmlAddEntity(table, name, type, ExternalID, SystemID, content);
1.1       httpng    185: }
                    186: 
1.22      daniel    187: /**
                    188:  * xmlAddDocEntity:
                    189:  * @doc:  the document
                    190:  * @name:  the entity name
                    191:  * @type:  the entity type XML_xxx_yyy_ENTITY
                    192:  * @ExternalID:  the entity external ID if available
                    193:  * @SystemID:  the entity system ID if available
                    194:  * @content:  the entity content
                    195:  *
                    196:  * Register a new entity for this document.
1.1       httpng    197:  */
1.22      daniel    198: void
                    199: xmlAddDocEntity(xmlDocPtr doc, const CHAR *name, int type,
1.13      daniel    200:               const CHAR *ExternalID, const CHAR *SystemID, CHAR *content) {
1.16      daniel    201:     xmlEntitiesTablePtr table;
                    202: 
1.22      daniel    203:     if (doc == NULL) {
                    204:         fprintf(stderr,
                    205:                "xmlAddDocEntity: document is NULL !\n");
                    206:        return;
                    207:     }
                    208:     if (doc->intSubset == NULL) {
                    209:         fprintf(stderr,
                    210:                "xmlAddDtdEntity: document without internal subset !\n");
                    211:        return;
                    212:     }
                    213:     table = (xmlEntitiesTablePtr) doc->intSubset->entities;
1.16      daniel    214:     if (table == NULL) {
                    215:         table = xmlCreateEntitiesTable();
1.22      daniel    216:        doc->intSubset->entities = table;
1.2       httpng    217:     }
1.22      daniel    218:     xmlAddEntity(table, name, type, ExternalID, SystemID, content);
1.1       httpng    219: }
                    220: 
1.22      daniel    221: /**
                    222:  * xmlGetDtdEntity:
                    223:  * @doc:  the document referencing the entity
                    224:  * @name:  the entity name
                    225:  *
                    226:  * Do an entity lookup in the Dtd entity hash table and
                    227:  * returns the corresponding entity, if found.
                    228:  * 
1.24      daniel    229:  * Returns A pointer to the entity structure or NULL if not found.
1.1       httpng    230:  */
1.22      daniel    231: xmlEntityPtr
                    232: xmlGetDtdEntity(xmlDocPtr doc, const CHAR *name) {
1.2       httpng    233:     int i;
                    234:     xmlEntityPtr cur;
                    235:     xmlEntitiesTablePtr table;
                    236: 
1.22      daniel    237:     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
                    238:        table = (xmlEntitiesTablePtr) doc->extSubset->entities;
1.15      daniel    239:        for (i = 0;i < table->nb_entities;i++) {
                    240:            cur = &table->table[i];
                    241:            if (!xmlStrcmp(cur->name, name)) return(cur);
                    242:        }
                    243:     }
1.7       veillard  244:     return(NULL);
1.3       httpng    245: }
                    246: 
1.22      daniel    247: /**
                    248:  * xmlGetDocEntity:
                    249:  * @doc:  the document referencing the entity
                    250:  * @name:  the entity name
                    251:  *
                    252:  * Do an entity lookup in the document entity hash table and
                    253:  * returns the corrsponding entity, otherwise a lookup is done
                    254:  * in the predefined entities too.
                    255:  * 
1.24      daniel    256:  * Returns A pointer to the entity structure or NULL if not found.
1.14      daniel    257:  */
1.22      daniel    258: xmlEntityPtr
                    259: xmlGetDocEntity(xmlDocPtr doc, const CHAR *name) {
1.14      daniel    260:     int i;
1.16      daniel    261:     xmlEntityPtr cur;
1.14      daniel    262:     xmlEntitiesTablePtr table;
                    263: 
1.22      daniel    264:     if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
                    265:        table = (xmlEntitiesTablePtr) doc->intSubset->entities;
1.16      daniel    266:        for (i = 0;i < table->nb_entities;i++) {
                    267:            cur = &table->table[i];
                    268:            if (!xmlStrcmp(cur->name, name)) return(cur);
                    269:        }
                    270:     }
1.15      daniel    271:     if (xmlPredefinedEntities == NULL)
                    272:         xmlInitializePredefinedEntities();
1.16      daniel    273:     table = xmlPredefinedEntities;
                    274:     for (i = 0;i < table->nb_entities;i++) {
                    275:        cur = &table->table[i];
                    276:        if (!xmlStrcmp(cur->name, name)) return(cur);
1.14      daniel    277:     }
                    278: 
                    279:     return(NULL);
1.1       httpng    280: }
                    281: 
                    282: /*
1.21      daniel    283:  * [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
                    284:  *                  | [#x10000-#x10FFFF]
                    285:  * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
                    286:  */
                    287: #define IS_CHAR(c)                                                     \
                    288:     (((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) ||                        \
                    289:      (((c) >= 0x20) && ((c) != 0xFFFE) && ((c) != 0xFFFF)))
                    290: 
1.28      daniel    291: /*
                    292:  * A buffer used for converting entities to their equivalent and back.
                    293:  *
                    294:  * TODO: remove this, this helps performances but forbid reentrancy in a 
                    295:  *       stupid way.
                    296:  */
                    297: static int buffer_size = 0;
                    298: static CHAR *buffer = NULL;
                    299: 
                    300: void growBuffer(void) {
                    301:     buffer_size *= 2;
                    302:     buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));
                    303:     if (buffer == NULL) {
                    304:         perror("realloc failed");
                    305:         exit(1);
                    306:     }
                    307: }
                    308: 
                    309: 
1.22      daniel    310: /**
                    311:  * xmlEncodeEntities:
                    312:  * @doc:  the document containing the string
                    313:  * @input:  A string to convert to XML.
                    314:  *
                    315:  * Do a global encoding of a string, replacing the predefined entities
                    316:  * and non ASCII values with their entities and CharRef counterparts.
                    317:  *
1.19      daniel    318:  * TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii
                    319:  *           get erroneous.
1.22      daniel    320:  *
1.28      daniel    321:  * TODO This routine is not reentrant, the interface
                    322:  *      should not be modified though.
                    323:  *
                    324:  * People must migrate their code to xmlEncodeEntitiesReentrant !
                    325:  * 
                    326:  * Returns A newly allocated string with the substitution done.
                    327:  */
                    328: const CHAR *
                    329: xmlEncodeEntities(xmlDocPtr doc, const CHAR *input) {
                    330:     const CHAR *cur = input;
                    331:     CHAR *out = buffer;
                    332: 
                    333:     if (input == NULL) return(NULL);
                    334:     if (buffer == NULL) {
                    335:         buffer_size = 1000;
                    336:         buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
                    337:        if (buffer == NULL) {
                    338:            perror("malloc failed");
                    339:             exit(1);
                    340:        }
                    341:        out = buffer;
                    342:     }
                    343:     while (*cur != '\0') {
                    344:         if (out - buffer > buffer_size - 100) {
                    345:            int index = out - buffer;
                    346: 
                    347:            growBuffer();
                    348:            out = &buffer[index];
                    349:        }
                    350: 
                    351:        /*
                    352:         * By default one have to encode at least '<', '>', '"' and '&' !
                    353:         */
                    354:        if (*cur == '<') {
                    355:            *out++ = '&';
                    356:            *out++ = 'l';
                    357:            *out++ = 't';
                    358:            *out++ = ';';
                    359:        } else if (*cur == '>') {
                    360:            *out++ = '&';
                    361:            *out++ = 'g';
                    362:            *out++ = 't';
                    363:            *out++ = ';';
                    364:        } else if (*cur == '&') {
                    365:            *out++ = '&';
                    366:            *out++ = 'a';
                    367:            *out++ = 'm';
                    368:            *out++ = 'p';
                    369:            *out++ = ';';
                    370:        } else if (*cur == '"') {
                    371:            *out++ = '&';
                    372:            *out++ = 'q';
                    373:            *out++ = 'u';
                    374:            *out++ = 'o';
                    375:            *out++ = 't';
                    376:            *out++ = ';';
                    377:        } else if (*cur == '\'') {
                    378:            *out++ = '&';
                    379:            *out++ = 'a';
                    380:            *out++ = 'p';
                    381:            *out++ = 'o';
                    382:            *out++ = 's';
                    383:            *out++ = ';';
                    384:        } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
                    385:            (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
                    386:            /*
                    387:             * default case, just copy !
                    388:             */
                    389:            *out++ = *cur;
                    390: #ifndef USE_UTF_8
                    391:        } else if ((sizeof(CHAR) == 1) && (*cur >= 0x80)) {
                    392:            char buf[10], *ptr;
                    393: #ifdef HAVE_SNPRINTF
                    394:            snprintf(buf, 9, "&#%d;", *cur);
                    395: #else
                    396:            sprintf(buf, "&#%d;", *cur);
                    397: #endif
                    398:             ptr = buf;
                    399:            while (*ptr != 0) *out++ = *ptr++;
                    400: #endif
                    401:        } else if (IS_CHAR(*cur)) {
                    402:            char buf[10], *ptr;
                    403: 
                    404: #ifdef HAVE_SNPRINTF
                    405:            snprintf(buf, 9, "&#%d;", *cur);
                    406: #else
                    407:            sprintf(buf, "&#%d;", *cur);
                    408: #endif
                    409:             ptr = buf;
                    410:            while (*ptr != 0) *out++ = *ptr++;
                    411:        }
                    412: #if 0
                    413:        else {
                    414:            /*
                    415:             * default case, this is not a valid char !
                    416:             * Skip it...
                    417:             */
                    418:            fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
                    419:        }
                    420: #endif
                    421:        cur++;
                    422:     }
                    423:     *out++ = 0;
                    424:     return(buffer);
                    425: }
                    426: 
                    427: /*
                    428:  * Macro used to grow the current buffer.
                    429:  */
                    430: #define growBufferReentrant() {                                                \
                    431:     buffer_size *= 2;                                                  \
                    432:     buffer = (CHAR *) realloc(buffer, buffer_size * sizeof(CHAR));     \
                    433:     if (buffer == NULL) {                                              \
                    434:        perror("realloc failed");                                       \
                    435:        exit(1);                                                        \
                    436:     }                                                                  \
                    437: }
                    438: 
                    439: 
                    440: /**
                    441:  * xmlEncodeEntitiesReentrant:
                    442:  * @doc:  the document containing the string
                    443:  * @input:  A string to convert to XML.
                    444:  *
                    445:  * Do a global encoding of a string, replacing the predefined entities
                    446:  * and non ASCII values with their entities and CharRef counterparts.
                    447:  * Contrary to xmlEncodeEntities, this routine is reentrant, and result
                    448:  * must be deallocated.
                    449:  *
                    450:  * TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii
                    451:  *           get erroneous.
                    452:  *
1.24      daniel    453:  * Returns A newly allocated string with the substitution done.
1.1       httpng    454:  */
1.22      daniel    455: CHAR *
1.28      daniel    456: xmlEncodeEntitiesReentrant(xmlDocPtr doc, const CHAR *input) {
1.7       veillard  457:     const CHAR *cur = input;
1.26      daniel    458:     CHAR *buffer = NULL;
                    459:     CHAR *out = NULL;
                    460:     int buffer_size = 0;
1.3       httpng    461: 
1.19      daniel    462:     if (input == NULL) return(NULL);
1.26      daniel    463: 
                    464:     /*
                    465:      * allocate an translation buffer.
                    466:      */
                    467:     buffer_size = 1000;
                    468:     buffer = (CHAR *) malloc(buffer_size * sizeof(CHAR));
1.3       httpng    469:     if (buffer == NULL) {
1.26      daniel    470:        perror("malloc failed");
                    471:        exit(1);
1.3       httpng    472:     }
1.26      daniel    473:     out = buffer;
                    474: 
1.6       veillard  475:     while (*cur != '\0') {
                    476:         if (out - buffer > buffer_size - 100) {
                    477:            int index = out - buffer;
                    478: 
1.28      daniel    479:            growBufferReentrant();
1.6       veillard  480:            out = &buffer[index];
                    481:        }
                    482: 
                    483:        /*
1.7       veillard  484:         * By default one have to encode at least '<', '>', '"' and '&' !
1.6       veillard  485:         */
                    486:        if (*cur == '<') {
                    487:            *out++ = '&';
                    488:            *out++ = 'l';
                    489:            *out++ = 't';
                    490:            *out++ = ';';
1.7       veillard  491:        } else if (*cur == '>') {
                    492:            *out++ = '&';
                    493:            *out++ = 'g';
                    494:            *out++ = 't';
                    495:            *out++ = ';';
1.6       veillard  496:        } else if (*cur == '&') {
                    497:            *out++ = '&';
                    498:            *out++ = 'a';
                    499:            *out++ = 'm';
                    500:            *out++ = 'p';
1.7       veillard  501:            *out++ = ';';
                    502:        } else if (*cur == '"') {
                    503:            *out++ = '&';
                    504:            *out++ = 'q';
                    505:            *out++ = 'u';
                    506:            *out++ = 'o';
                    507:            *out++ = 't';
                    508:            *out++ = ';';
                    509:        } else if (*cur == '\'') {
                    510:            *out++ = '&';
                    511:            *out++ = 'a';
                    512:            *out++ = 'p';
                    513:            *out++ = 'o';
                    514:            *out++ = 's';
1.6       veillard  515:            *out++ = ';';
1.21      daniel    516:        } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
                    517:            (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
                    518:            /*
                    519:             * default case, just copy !
                    520:             */
                    521:            *out++ = *cur;
1.19      daniel    522: #ifndef USE_UTF_8
                    523:        } else if ((sizeof(CHAR) == 1) && (*cur >= 0x80)) {
                    524:            char buf[10], *ptr;
                    525: #ifdef HAVE_SNPRINTF
                    526:            snprintf(buf, 9, "&#%d;", *cur);
                    527: #else
                    528:            sprintf(buf, "&#%d;", *cur);
                    529: #endif
                    530:             ptr = buf;
                    531:            while (*ptr != 0) *out++ = *ptr++;
                    532: #endif
1.21      daniel    533:        } else if (IS_CHAR(*cur)) {
1.20      daniel    534:            char buf[10], *ptr;
                    535: 
                    536: #ifdef HAVE_SNPRINTF
                    537:            snprintf(buf, 9, "&#%d;", *cur);
                    538: #else
                    539:            sprintf(buf, "&#%d;", *cur);
                    540: #endif
                    541:             ptr = buf;
                    542:            while (*ptr != 0) *out++ = *ptr++;
1.21      daniel    543:        }
                    544: #if 0
                    545:        else {
1.6       veillard  546:            /*
1.21      daniel    547:             * default case, this is not a valid char !
                    548:             * Skip it...
1.6       veillard  549:             */
1.21      daniel    550:            fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
1.6       veillard  551:        }
1.21      daniel    552: #endif
1.6       veillard  553:        cur++;
                    554:     }
                    555:     *out++ = 0;
                    556:     return(buffer);
1.2       httpng    557: }
                    558: 
1.22      daniel    559: /**
                    560:  * xmlCreateEntitiesTable:
                    561:  *
                    562:  * create and initialize an empty entities hash table.
                    563:  *
1.24      daniel    564:  * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
1.2       httpng    565:  */
1.22      daniel    566: xmlEntitiesTablePtr
                    567: xmlCreateEntitiesTable(void) {
1.2       httpng    568:     xmlEntitiesTablePtr ret;
1.1       httpng    569: 
1.2       httpng    570:     ret = (xmlEntitiesTablePtr) 
                    571:          malloc(sizeof(xmlEntitiesTable));
1.1       httpng    572:     if (ret == NULL) {
1.28      daniel    573:         fprintf(stderr, "xmlCreateEntitiesTable : malloc(%ld) failed\n",
                    574:                (long)sizeof(xmlEntitiesTable));
1.2       httpng    575:         return(NULL);
                    576:     }
                    577:     ret->max_entities = XML_MIN_ENTITIES_TABLE;
                    578:     ret->nb_entities = 0;
                    579:     ret->table = (xmlEntityPtr ) 
                    580:          malloc(ret->max_entities * sizeof(xmlEntity));
                    581:     if (ret == NULL) {
1.28      daniel    582:         fprintf(stderr, "xmlCreateEntitiesTable : malloc(%ld) failed\n",
                    583:                ret->max_entities * (long)sizeof(xmlEntity));
1.2       httpng    584:        free(ret);
1.1       httpng    585:         return(NULL);
                    586:     }
                    587:     return(ret);
                    588: }
                    589: 
1.22      daniel    590: /**
                    591:  * xmlFreeEntitiesTable:
                    592:  * @table:  An entity table
                    593:  *
                    594:  * Deallocate the memory used by an entities hash table.
1.1       httpng    595:  */
1.22      daniel    596: void
                    597: xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
1.1       httpng    598:     int i;
                    599: 
                    600:     if (table == NULL) return;
                    601: 
1.2       httpng    602:     for (i = 0;i < table->nb_entities;i++) {
                    603:         xmlFreeEntity(&table->table[i]);
1.1       httpng    604:     }
1.2       httpng    605:     free(table->table);
1.1       httpng    606:     free(table);
                    607: }
                    608: 
1.22      daniel    609: /**
                    610:  * xmlCopyEntitiesTable:
                    611:  * @table:  An entity table
                    612:  *
                    613:  * Build a copy of an entity table.
                    614:  * 
1.24      daniel    615:  * Returns the new xmlEntitiesTablePtr or NULL in case of error.
1.22      daniel    616:  */
                    617: xmlEntitiesTablePtr
                    618: xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
                    619:     xmlEntitiesTablePtr ret;
                    620:     xmlEntityPtr cur, ent;
                    621:     int i;
                    622: 
                    623:     ret = (xmlEntitiesTablePtr) malloc(sizeof(xmlEntitiesTable));
                    624:     if (ret == NULL) {
                    625:         fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
                    626:        return(NULL);
                    627:     }
                    628:     ret->table = (xmlEntityPtr) malloc(table->max_entities *
                    629:                                          sizeof(xmlEntity));
                    630:     if (ret->table == NULL) {
                    631:         fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
                    632:        free(ret);
                    633:        return(NULL);
                    634:     }
                    635:     ret->max_entities = table->max_entities;
                    636:     ret->nb_entities = table->nb_entities;
                    637:     for (i = 0;i < ret->nb_entities;i++) {
                    638:        cur = &ret->table[i];
                    639:        ent = &table->table[i];
                    640:        cur->len = ent->len;
                    641:        cur->type = ent->type;
                    642:        if (ent->name != NULL)
                    643:            cur->name = xmlStrdup(ent->name);
                    644:        else
                    645:            cur->name = NULL;
                    646:        if (ent->ExternalID != NULL)
                    647:            cur->ExternalID = xmlStrdup(ent->ExternalID);
                    648:        else
                    649:            cur->ExternalID = NULL;
                    650:        if (ent->SystemID != NULL)
                    651:            cur->SystemID = xmlStrdup(ent->SystemID);
                    652:        else
                    653:            cur->SystemID = NULL;
                    654:        if (ent->content != NULL)
                    655:            cur->content = xmlStrdup(ent->content);
                    656:        else
                    657:            cur->content = NULL;
1.27      daniel    658:        if (ent->orig != NULL)
                    659:            cur->orig = xmlStrdup(ent->orig);
                    660:        else
                    661:            cur->orig = NULL;
1.22      daniel    662:     }
                    663:     return(ret);
                    664: }
                    665: 
                    666: /**
                    667:  * xmlDumpEntitiesTable:
1.25      daniel    668:  * @buf:  An XML buffer.
1.22      daniel    669:  * @table:  An entity table
                    670:  *
                    671:  * This will dump the content of the entity table as an XML DTD definition
1.13      daniel    672:  */
1.22      daniel    673: void
1.25      daniel    674: xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
1.14      daniel    675:     int i;
                    676:     xmlEntityPtr cur;
                    677: 
                    678:     if (table == NULL) return;
                    679: 
                    680:     for (i = 0;i < table->nb_entities;i++) {
                    681:         cur = &table->table[i];
                    682:         switch (cur->type) {
                    683:            case XML_INTERNAL_GENERAL_ENTITY:
1.25      daniel    684:                xmlBufferWriteChar(buf, "<!ENTITY ");
                    685:                xmlBufferWriteCHAR(buf, cur->name);
1.27      daniel    686:                xmlBufferWriteChar(buf, " ");
                    687:                if (cur->orig != NULL)
                    688:                    xmlBufferWriteQuotedString(buf, cur->orig);
                    689:                else
                    690:                    xmlBufferWriteQuotedString(buf, cur->content);
                    691:                xmlBufferWriteChar(buf, ">\n");
1.14      daniel    692:                break;
                    693:            case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1.25      daniel    694:                xmlBufferWriteChar(buf, "<!ENTITY ");
                    695:                xmlBufferWriteCHAR(buf, cur->name);
1.14      daniel    696:                if (cur->ExternalID != NULL) {
1.27      daniel    697:                     xmlBufferWriteChar(buf, " PUBLIC ");
                    698:                     xmlBufferWriteQuotedString(buf, cur->ExternalID);
                    699:                     xmlBufferWriteChar(buf, " ");
                    700:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    701:                } else {
1.27      daniel    702:                     xmlBufferWriteChar(buf, " SYSTEM ");
                    703:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    704:                }
1.25      daniel    705:                xmlBufferWriteChar(buf, ">\n");
1.14      daniel    706:                break;
                    707:            case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1.25      daniel    708:                xmlBufferWriteChar(buf, "<!ENTITY ");
                    709:                xmlBufferWriteCHAR(buf, cur->name);
1.14      daniel    710:                if (cur->ExternalID != NULL) {
1.27      daniel    711:                     xmlBufferWriteChar(buf, " PUBLIC ");
                    712:                     xmlBufferWriteQuotedString(buf, cur->ExternalID);
                    713:                     xmlBufferWriteChar(buf, " ");
                    714:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    715:                } else {
1.27      daniel    716:                     xmlBufferWriteChar(buf, " SYSTEM ");
                    717:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    718:                }
                    719:                if (cur->content != NULL) { /* Should be true ! */
1.25      daniel    720:                    xmlBufferWriteChar(buf, " NDATA ");
1.27      daniel    721:                    if (cur->orig != NULL)
                    722:                        xmlBufferWriteCHAR(buf, cur->orig);
                    723:                    else
                    724:                        xmlBufferWriteCHAR(buf, cur->content);
1.14      daniel    725:                }
1.25      daniel    726:                xmlBufferWriteChar(buf, ">\n");
1.14      daniel    727:                break;
                    728:            case XML_INTERNAL_PARAMETER_ENTITY:
1.25      daniel    729:                xmlBufferWriteChar(buf, "<!ENTITY % ");
                    730:                xmlBufferWriteCHAR(buf, cur->name);
1.27      daniel    731:                xmlBufferWriteChar(buf, " ");
                    732:                if (cur->orig == NULL)
                    733:                    xmlBufferWriteQuotedString(buf, cur->content);
                    734:                else
                    735:                    xmlBufferWriteQuotedString(buf, cur->orig);
                    736:                xmlBufferWriteChar(buf, ">\n");
1.14      daniel    737:                break;
                    738:            case XML_EXTERNAL_PARAMETER_ENTITY:
1.25      daniel    739:                xmlBufferWriteChar(buf, "<!ENTITY % ");
                    740:                xmlBufferWriteCHAR(buf, cur->name);
1.14      daniel    741:                if (cur->ExternalID != NULL) {
1.27      daniel    742:                     xmlBufferWriteChar(buf, " PUBLIC ");
                    743:                     xmlBufferWriteQuotedString(buf, cur->ExternalID);
                    744:                     xmlBufferWriteChar(buf, " ");
                    745:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    746:                } else {
1.27      daniel    747:                     xmlBufferWriteChar(buf, " SYSTEM ");
                    748:                     xmlBufferWriteQuotedString(buf, cur->SystemID);
1.14      daniel    749:                }
1.25      daniel    750:                xmlBufferWriteChar(buf, ">\n");
1.14      daniel    751:                break;
                    752:            default:
                    753:                fprintf(stderr,
                    754:                    "xmlDumpEntitiesTable: internal: unknown type %d\n",
                    755:                        cur->type);
                    756:        }
                    757:     }
1.13      daniel    758: }

Webmaster