Annotation of gpl/axl/src/axl_dtd.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  *  LibAxl:  Another XML library
        !             3:  *  Copyright (C) 2006 Advanced Software Production Line, S.L.
        !             4:  *
        !             5:  *  This program is free software; you can redistribute it and/or
        !             6:  *  modify it under the terms of the GNU Lesser General Public License
        !             7:  *  as published by the Free Software Foundation; either version 2.1 of
        !             8:  *  the License, or (at your option) any later version.
        !             9:  *
        !            10:  *  This program is distributed in the hope that it will be useful,
        !            11:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
        !            12:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
        !            13:  *  GNU Lesser General Public License for more details.
        !            14:  *
        !            15:  *  You should have received a copy of the GNU Lesser General Public
        !            16:  *  License along with this program; if not, write to the Free
        !            17:  *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
        !            18:  *  02111-1307 USA
        !            19:  *  
        !            20:  *  You may find a copy of the license under this software is released
        !            21:  *  at COPYING file. This is LGPL software: you are welcome to
        !            22:  *  develop proprietary applications using this library without any
        !            23:  *  royalty or fee but returning back any change, improvement or
        !            24:  *  addition in the form of source code, project image, documentation
        !            25:  *  patches, etc. 
        !            26:  *
        !            27:  *  For commercial support on build XML enabled solutions contact us:
        !            28:  *          
        !            29:  *      Postal address:
        !            30:  *         Advanced Software Production Line, S.L.
        !            31:  *         Edificio Alius A, Oficina 102,
        !            32:  *         C/ Antonio Suarez Nº 10,
        !            33:  *         Alcalá de Henares 28802 Madrid
        !            34:  *         Spain
        !            35:  *
        !            36:  *      Email address:
        !            37:  *         info@aspl.es - http://www.aspl.es/xml
        !            38:  */
        !            39: #include <axl_decl.h>
        !            40: #include <axl.h>
        !            41: 
        !            42: #define LOG_DOMAIN "axl-dtd"
        !            43: 
        !            44: struct _axlDtdElementListNode {
        !            45:        NodeType     type;
        !            46:        AxlDtdTimes  times;
        !            47:        axlPointer   data;
        !            48: };
        !            49: 
        !            50: struct _axlDtdElementList {
        !            51:        /** 
        !            52:         * @brief Allows to configure how is given top level
        !            53:         * configuration for nodes to be defined inside the xml
        !            54:         * document being configured. As defined in the XML 1.0
        !            55:         * Recomendation, available top level choices are: choice or
        !            56:         * sequence. 
        !            57:         *
        !            58:         * They allow to configure allowed nodes to be selected as
        !            59:         * childs, from a set of node names, called choice or to
        !            60:         * configure which are the set of nodes to be used, in a
        !            61:         * particular order, called sequence.
        !            62:         *
        !            63:         * This variable allows to configure which is the top level
        !            64:         * section configuration: either a choice or a sequence.
        !            65:         *
        !            66:         * Keep in mind that, having only one element inside the
        !            67:         * itemList, there is no difference between the sequence and
        !            68:         * the choice.
        !            69:         */
        !            70:        AxlDtdNestedType      type;
        !            71:        
        !            72:        /** 
        !            73:         * @brief Allows to configure how many times is repeated a
        !            74:         * selection provided (by this element).
        !            75:         */
        !            76:        AxlDtdTimes           times;
        !            77: 
        !            78:        /** 
        !            79:         * @brief Item list, which contains more axlDtdElementList
        !            80:         * nodes, configuring elements allowed.
        !            81:         */
        !            82:        axlList             * itemList;
        !            83: };
        !            84: 
        !            85: struct _axlDtdElement {
        !            86:        /** 
        !            87:         * @brief The document type element declaration name. This is
        !            88:         * the name of the xml node being constrained.
        !            89:         */
        !            90:        char                * name;
        !            91: 
        !            92:        /** 
        !            93:         * @brief This is the type of the xml node being constrained.
        !            94:         */
        !            95:        AxlDtdElementType     type;
        !            96:        /** 
        !            97:         * @brief List of available items.
        !            98:         * 
        !            99:         * This variable holds current top level list selection. See
        !           100:         * axlDtdElementList.type variable.
        !           101:         */
        !           102:        axlDtdElementList   * list;
        !           103: 
        !           104:        /** 
        !           105:         * @brief Minimum item list count to be matched while using
        !           106:         * this DTD element rule.
        !           107:         */
        !           108:        int                    minimum_match;
        !           109: };
        !           110: 
        !           111: struct _axlDtdAttributeDecl {
        !           112:        /** 
        !           113:         * @brief Attribute name. This is the attribute value defined
        !           114:         * for the node.
        !           115:         */
        !           116:        char                     * name;
        !           117:        
        !           118:        /** 
        !           119:         * @brief This is the attribute declaration type. It shows if 
        !           120:         */
        !           121:        AxlDtdAttributeType        type;
        !           122: 
        !           123:        /** 
        !           124:         * @brief Allows to model whoe is 
        !           125:         */
        !           126:        AxlDtdAttributeDefaults    defaults;
        !           127:        
        !           128:        /** 
        !           129:         * @brief This is a default value for the <!ATTLIST
        !           130:         * declaration received, in the case a FIXED value is required
        !           131:         * or a default value is declarted.
        !           132:         */
        !           133:        char                     * default_value;
        !           134: 
        !           135:        /** 
        !           136:         * @brief Internal declaration for enum values defined for
        !           137:         * this rule. This list is only initialized in the case enum
        !           138:         * values are defined.
        !           139:         */
        !           140:        axlList                  * enumvalues;
        !           141: 
        !           142: };
        !           143: 
        !           144: struct _axlDtdAttribute {
        !           145:        /** 
        !           146:         * @brief The document attribute list declaration name. This
        !           147:         * is the name of the node that will receive the constrain
        !           148:         * defined.
        !           149:         */
        !           150:        char           * name;
        !           151:        
        !           152:        /** 
        !           153:         * @brief This is the list of constrains defined for the
        !           154:         * node. It as list of \ref axlDtdAttributeDecl which defines
        !           155:         * the attribute that is declarted, if it is required, and the
        !           156:         * type of its content.
        !           157:         */
        !           158:        axlList        * list;
        !           159: };
        !           160: 
        !           161: struct _axlDtdEntityExternalData {
        !           162:        /** 
        !           163:         * @brief Contains the system literal reference. This is a URI
        !           164:         * reference to the resource pointed by the \ref axlDtdEntity
        !           165:         * definition.
        !           166:         */
        !           167:        char * system_literal;
        !           168:        /** 
        !           169:         * @brief Contains the public literal information associated
        !           170:         * to the entity definition.
        !           171:         */
        !           172:        char * public_literal;
        !           173:        /** 
        !           174:         * @brief Contains the NDATA information (a notation name
        !           175:         * reference).
        !           176:         */
        !           177:        char * ndata;
        !           178: };
        !           179: 
        !           180: struct _axlDtdEntity {
        !           181:        /** 
        !           182:         * @brief Contains the entity name.
        !           183:         */
        !           184:        char           * name;
        !           185:        
        !           186:        /** 
        !           187:         * @brief Contains the entity type.
        !           188:         */
        !           189:        axlDtdEntityType type;
        !           190: 
        !           191:        /** 
        !           192:         * @brief Content of the entity definition ([9] EntityValue).
        !           193:         */
        !           194:        char           * content;
        !           195:        
        !           196:        /** 
        !           197:         * @brief An entity definition can have a reference to a
        !           198:         * external resource. The following pointer contains
        !           199:         * information for the external resource pointed.
        !           200:         */
        !           201:        axlDtdEntityExternalData * data;
        !           202: };
        !           203: 
        !           204: struct _axlDtd {
        !           205:        /** 
        !           206:         * @brief Holds all entity definitions inside the DTD
        !           207:         * declaration (<!ENTITY..>).
        !           208:         */
        !           209:        axlList       * entities;
        !           210: 
        !           211:        /** 
        !           212:         * @brief All elements inside the DTD declaration
        !           213:         * (<!ELEMENT..> ).
        !           214:         */
        !           215:        axlList       * elements;
        !           216: 
        !           217:        /** 
        !           218:         * @brief All attribute type declerations inside the DTD
        !           219:         * (<!ATTLIST..>)
        !           220:         */
        !           221:        axlList       * attributes;
        !           222: 
        !           223:        /** 
        !           224:         * @brief The element root, for the given DTD declaration.
        !           225:         */
        !           226:        axlDtdElement * root;
        !           227: 
        !           228:        /** 
        !           229:         * @brief Internal flag that allows to notify that the DTD
        !           230:         * contains ID attribute declaration, making the DTD this
        !           231:         * references. 
        !           232:         */
        !           233:        axl_bool       haveIdDecl;
        !           234: 
        !           235:        /** 
        !           236:         * @brief Flag that the dtd declaration have attributes which
        !           237:         * are flaged as IDREF.
        !           238:         */
        !           239:        axl_bool      haveIdRefDecl;
        !           240: };
        !           241: 
        !           242: /**
        !           243:  * \defgroup axl_dtd_module Axl DTD: Document type declaration interface (functions, validation, and DTD parsing)
        !           244:  */
        !           245: 
        !           246: 
        !           247: /** 
        !           248:  * \addtogroup axl_dtd_module
        !           249:  * @{
        !           250:  */
        !           251: 
        !           252: 
        !           253: /** 
        !           254:  * @internal
        !           255:  *
        !           256:  * Allows to create a new dtd element list item, which represents a
        !           257:  * content particule inside an item list or a item list. This allows
        !           258:  * the recursion defined on the XML 1.0 standard.
        !           259:  *
        !           260:  * The function receives the node name and a reference list. According
        !           261:  * to the values the function creates a node which contains a leaf
        !           262:  * value or a node which contains a reference to the a new list which
        !           263:  * is nested.
        !           264:  */
        !           265: axlDtdElementListNode * __create_axl_dtd_element_list (char * node_name,
        !           266:                                                       axlDtdElementList * list)
        !           267: {
        !           268:        axlDtdElementListNode * node;
        !           269: 
        !           270:        node = axl_new (axlDtdElementListNode, 1);
        !           271: 
        !           272:        /* create a node element reference */
        !           273:        if (node_name != NULL) {
        !           274:                node->data = node_name;
        !           275:                node->type = AXL_ELEMENT_NODE;
        !           276:                return node;
        !           277:        }
        !           278: 
        !           279:        /* create an element list reference */
        !           280:        if (list != NULL) {
        !           281:                node->data = list;
        !           282:                node->type = AXL_ELEMENT_LIST;
        !           283:                return node;
        !           284:        }
        !           285: 
        !           286:        /* if another type is requested, return NULL */
        !           287:        return NULL;
        !           288: }
        !           289: 
        !           290: /** 
        !           291:  * @internal
        !           292:  *
        !           293:  * Support function used to destroy all items stored on a item list.
        !           294:  * 
        !           295:  * @param node 
        !           296:  */
        !           297: void __destroy_axl_dtd_element_list (axlDtdElementListNode * node)
        !           298: {
        !           299:        if (node == NULL)
        !           300:                return;
        !           301:        /* free the reference to the leaf node if defined */
        !           302:        if (node->type == AXL_ELEMENT_NODE)
        !           303:                axl_free (node->data);
        !           304:        
        !           305:        /* do not do nothing if the reference is not element list */
        !           306:        if (node->type == AXL_ELEMENT_LIST)
        !           307:                axl_dtd_item_list_free (node->data);
        !           308: 
        !           309:        /* free de node itself */
        !           310:        axl_free (node);
        !           311:        return;
        !           312: }
        !           313: 
        !           314: /** 
        !           315:  * @internal
        !           316:  *
        !           317:  * @brief Support function to \ref axl_dtd_parse which creates a new
        !           318:  * empty DTD reference.
        !           319:  * 
        !           320:  * 
        !           321:  * @return A newly allocated \ref axlDtd reference.
        !           322:  */
        !           323: axlDtd * __axl_dtd_new (void)
        !           324: {
        !           325:        axlDtd * dtd;
        !           326: 
        !           327:        /* create the DTD element and nothing else. The rest of items
        !           328:         * created on demand */
        !           329:        dtd           = axl_new (axlDtd, 1);
        !           330: 
        !           331:        return dtd;
        !           332: }
        !           333: 
        !           334: axl_bool __queue_items (axlPointer data, axlPointer _stack)
        !           335: {
        !           336:        axlStack * stack = _stack;
        !           337: 
        !           338:        /* queue the data */
        !           339:        axl_stack_push (stack, data);
        !           340: 
        !           341:        /* return axl_false to make the function to not stop */
        !           342:        return axl_false;
        !           343: }
        !           344: 
        !           345: void __axl_dtd_queue_childs (axlStack * stack, axlNode * parent)
        !           346: {
        !           347:        axlNode * child;
        !           348: 
        !           349:        /* get the first child */
        !           350:        child = axl_node_get_first_child (parent);
        !           351:        while (child != NULL) {
        !           352: 
        !           353:                /* queue the child */
        !           354:                axl_stack_push (stack, child);
        !           355:                
        !           356:                /* get the next child */
        !           357:                child = axl_node_get_next (child);
        !           358:        } /* end while */
        !           359: 
        !           360:        return;
        !           361: }
        !           362: 
        !           363: /** 
        !           364:  * @internal
        !           365:  *
        !           366:  * Support internal function which allows to queue all items inside an
        !           367:  * axlDtdElementList to be checked.
        !           368:  * 
        !           369:  * @param stack The stack where all data will be placed.
        !           370:  *
        !           371:  * @param dtd_element_list The dtd element list where the data will be
        !           372:  * extracted.
        !           373:  */
        !           374: void __axl_dtd_queue_items (axlStack * stack, axlList * list) 
        !           375: {
        !           376:        /* call to queue items */
        !           377:        axl_list_lookup (list, __queue_items, stack);
        !           378: 
        !           379:        /* nothing more */
        !           380:        return;
        !           381: }
        !           382: 
        !           383: /** 
        !           384:  * @internal
        !           385:  *
        !           386:  * Support function which allows to check if the provided two dtd
        !           387:  * elements are in fact, parent and child.
        !           388:  *
        !           389:  * DTD element have a parent-child relation based in the fact that the
        !           390:  * first define top level xml nodes that are followed, in the form of
        !           391:  * childs nodes, by other DTD elements that define more childs, etc...
        !           392:  *
        !           393:  * This function allows to check if the provided parent dtd element
        !           394:  * have references inside its content specification that proves that
        !           395:  * it is indeed a parent definition.
        !           396:  * 
        !           397:  * @param dtd_element_parent The supposed DTD parent element.
        !           398:  * @param dtd_element_child  The supposedd DTD child element.
        !           399:  * 
        !           400:  * @return \ref axl_true if the function can confirm that the parent-child
        !           401:  * relation exists, \ref axl_false if not or it could be proved.
        !           402:  */
        !           403: axl_bool     __axl_dtd_get_is_parent (axlDtdElement * dtd_element_parent,
        !           404:                                      axlDtdElement * dtd_element_child)
        !           405: {
        !           406:        axlStack               * stack;
        !           407:        axlDtdElementListNode  * node;
        !           408:        axlDtdElementList      * list;
        !           409: 
        !           410:        /* check for leaf nodes, that, by definition, could be a
        !           411:         * parent of nothing. */
        !           412:        if (dtd_element_parent->list == NULL || dtd_element_parent->list->itemList == NULL) {
        !           413:                return axl_false;
        !           414:        }
        !           415: 
        !           416:        /* prepare all elements inside the stack to be checked */
        !           417:        stack = axl_stack_new (NULL);
        !           418:        __axl_dtd_queue_items (stack, dtd_element_parent->list->itemList);
        !           419:        
        !           420: 
        !           421:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "stack size to operate: %d, list: %d", 
        !           422:                   axl_stack_size (stack),
        !           423:                   axl_list_length (dtd_element_parent->list->itemList));
        !           424: 
        !           425:        /* now search for a content particule that makes are reference
        !           426:         * to the child DTD element */
        !           427:        do {
        !           428:                node = axl_stack_pop (stack);
        !           429:                switch (node->type) {
        !           430:                case AXL_ELEMENT_NODE:
        !           431:                        /* leaf node case */
        !           432:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a leaf node, checking it");
        !           433: 
        !           434:                        /* seems this is a final node */
        !           435:                        if (axl_cmp (node->data, dtd_element_child->name)) {
        !           436:                                /* seems that the content
        !           437:                                 * specification makes a reference to
        !           438:                                 * the child node. */
        !           439:                                axl_stack_free (stack);
        !           440:                                return axl_true;
        !           441:                        }
        !           442:                        break;
        !           443:                case AXL_ELEMENT_LIST:
        !           444:                        /* a nested list case */
        !           445:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a complex node queuing its internal elements, while checking parent=%s for child=%s",
        !           446:                                   dtd_element_parent->name, dtd_element_child->name);
        !           447:                        /* the item list read, is a complex value,
        !           448:                         * queue all items inside to be inspected */
        !           449:                        list = node->data;
        !           450:                        __axl_dtd_queue_items (stack, list->itemList);
        !           451:                        break;
        !           452:                case AXL_ELEMENT_NOT_DEFINED:
        !           453:                        /* do nothing */
        !           454:                        break;
        !           455:                }
        !           456:                
        !           457:                /* iterate until all elements are evaluated */
        !           458:        }while (! axl_stack_is_empty (stack));
        !           459: 
        !           460:        /* deallocates no longer used stack */
        !           461:        axl_stack_free (stack);
        !           462:        
        !           463:        /* either it isn't the parent or it can't be proved. */
        !           464:        return axl_false;
        !           465: }
        !           466: 
        !           467: 
        !           468: /** 
        !           469:  * @internal
        !           470:  * 
        !           471:  * Support function which allows to get which is the most top root
        !           472:  * node for the provided set of DTD elements.
        !           473:  */
        !           474: axlDtdElement * __axl_dtd_get_new_root (axlDtd * dtd) 
        !           475: {
        !           476:        int             iterator;
        !           477:        axl_bool        change_detected;
        !           478: 
        !           479:        axlDtdElement * dtd_element_aux;
        !           480:        axlDtdElement * dtd_element_the_root_is_on_fire;
        !           481: 
        !           482:        /* set the very first root node */
        !           483:        dtd_element_the_root_is_on_fire = axl_list_get_nth (dtd->elements, 0);
        !           484:        
        !           485:        do {
        !           486:                /* check which is the top */
        !           487:                iterator        = 0;
        !           488:                change_detected = axl_false;
        !           489:                while (iterator < axl_list_length (dtd->elements)) {
        !           490:                        
        !           491:                        /* get the next reference */
        !           492:                        dtd_element_aux = axl_list_get_nth (dtd->elements, iterator);
        !           493:                        
        !           494:                        /* check which is the top */
        !           495:                        if (__axl_dtd_get_is_parent (dtd_element_aux,
        !           496:                                                     dtd_element_the_root_is_on_fire)) {
        !           497:                                /* it seems that the new element is the root
        !           498:                                 * one, update the reference */
        !           499:                                dtd_element_the_root_is_on_fire = dtd_element_aux;
        !           500:                                change_detected = axl_true;
        !           501:                        }
        !           502:                        
        !           503:                        /* update inner loop iterator */
        !           504:                        iterator ++;
        !           505:                } /* while end */
        !           506:        }while (change_detected);
        !           507: 
        !           508:        /* return the root found */
        !           509:        return dtd_element_the_root_is_on_fire;
        !           510: }
        !           511: 
        !           512: /** 
        !           513:  * @internal 
        !           514:  *
        !           515:  * @brief Adds the axlDtdElement into the given axlDtd definition,
        !           516:  * checking that everything is properly configured, and ensuring that
        !           517:  * the root element gets properly configured.
        !           518:  * 
        !           519:  * @param dtd The \ref axlDtd object that will receive the
        !           520:  * axlDtdElement.
        !           521:  *
        !           522:  * @param stream The \ref axlStream object that will be destroyed if
        !           523:  * something wrong is found.
        !           524:  *
        !           525:  * @param element The axlDtdElement to be added to the give axlDtd
        !           526:  * object.
        !           527:  * 
        !           528:  * @return axl_true if the given axlDtdElement is compatible inside
        !           529:  * the axlDtd declaration or axl_false if a error is found.
        !           530:  */
        !           531: axl_bool     __axl_dtd_add_element (axlDtd * dtd, axlDtdElement * element, 
        !           532:                                    axlStream * stream, axlError ** error)
        !           533: {
        !           534:        int             iterator        = 0;
        !           535:        axlDtdElement * dtd_element_aux = NULL;
        !           536: 
        !           537:        /* check that there is no element already named like the
        !           538:         * element received. If it is the case drop an error */
        !           539:        while (iterator < axl_list_length (dtd->elements)) {
        !           540:                dtd_element_aux = axl_list_get_nth (dtd->elements, iterator);
        !           541:                if (axl_cmp (dtd_element_aux->name, element->name)) {
        !           542:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "DTD element for <%s> == <%s> was defined twice", 
        !           543:                                   dtd_element_aux->name, element->name);
        !           544: 
        !           545:                        axl_error_new (-1, "Find that an DTD element was defined twice (no more than one time is allowed)", 
        !           546:                                       stream, error);
        !           547:                        axl_stream_free (stream);
        !           548:                        return axl_false;
        !           549:                }
        !           550: 
        !           551:                /* update current iterator */
        !           552:                iterator++;
        !           553:        }
        !           554:        
        !           555:        /* add the new DTD element to the list */
        !           556:        axl_list_add (dtd->elements, element);
        !           557:        return axl_true;
        !           558: }
        !           559: 
        !           560: /** 
        !           561:  * @internal
        !           562:  * 
        !           563:  * Internal support function which adds the provided content particule
        !           564:  * to the dtd item list received. It also perform all operations
        !           565:  * required for the chunk_matched option received.
        !           566:  *
        !           567:  * In the case the function fails to do its work, it will deallocate
        !           568:  * the stream, filling the error received.
        !           569:  *
        !           570:  * According to the chunk matched value, the function will react
        !           571:  * adding the element and configuring current element list.
        !           572:  *
        !           573:  */
        !           574: axl_bool     __axl_dtd_element_content_particule_add (axlDtdElementList  * dtd_item_list, 
        !           575:                                                      char               * string_aux, 
        !           576:                                                      int                  chunk_matched, 
        !           577:                                                      axlStream          * stream, 
        !           578:                                                      axlError          **error)
        !           579: {
        !           580:        axlDtdElementListNode * node;
        !           581: 
        !           582:        /* check if the item list was creted or not */
        !           583:        if (dtd_item_list->itemList == NULL) {
        !           584:                dtd_item_list->itemList = axl_list_new (axl_list_always_return_1, 
        !           585:                                                        (axlDestroyFunc) __destroy_axl_dtd_element_list);
        !           586:        }
        !           587: 
        !           588:        /* create the node to be added */
        !           589:        node = __create_axl_dtd_element_list (string_aux, NULL);
        !           590: 
        !           591:        /* know add the element found */
        !           592:        axl_list_add (dtd_item_list->itemList, node);
        !           593: 
        !           594:        /* set configuration for item repetition */
        !           595:        switch (chunk_matched) {
        !           596:        case 4:
        !           597:                /* one or many times */
        !           598:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting one to many repeat pattern: (+)");
        !           599:                node->times = ONE_OR_MANY;
        !           600:                break;
        !           601:        case 5:
        !           602:                /* zero or many times */
        !           603:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting zero to many repeat pattern: (*)");
        !           604:                node->times = ZERO_OR_MANY;
        !           605:                break;
        !           606:        case 6:
        !           607:                /* zero or one time */
        !           608:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting one to one repeat pattern: (?)");
        !           609:                node->times = ZERO_OR_ONE;
        !           610:                break;
        !           611:        default:
        !           612:                /* one and only one time */
        !           613:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "setting one and only one repeat pattern: ()");
        !           614:                node->times = ONE_AND_ONLY_ONE;
        !           615:        }
        !           616: 
        !           617:        /* return that all is ok */
        !           618:        return axl_true;
        !           619: }
        !           620: 
        !           621: 
        !           622: /** 
        !           623:  * @internal
        !           624:  * 
        !           625:  * @brief Support function which allows to get current repetition
        !           626:  * configuration.
        !           627:  * 
        !           628:  * @param stream The stream where the operation will be performed.
        !           629:  * 
        !           630:  * @return Current configuration read, the function will properly work
        !           631:  * if it is called when it is espected to find a content specification
        !           632:  * repetition. If not found, the \ref ONE_AND_ONLY_ONE is returned.
        !           633:  */
        !           634: AxlDtdTimes __axl_dtd_get_repetition_conf (axlStream * stream)
        !           635: {
        !           636:        axl_return_val_if_fail (stream, ONE_AND_ONLY_ONE);
        !           637: 
        !           638:        if (axl_stream_inspect (stream, "?", 1) > 0) {
        !           639: 
        !           640:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found '?' repetition conf");
        !           641:                /* seems the content specification could appear zero
        !           642:                 * or one time */
        !           643:                return ZERO_OR_ONE;
        !           644: 
        !           645:        } else if (axl_stream_inspect (stream, "+", 1) > 0) {
        !           646: 
        !           647:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found '+' repetition conf");
        !           648:                /* seems the content specification must appear one up
        !           649:                 * to many */
        !           650:                return ONE_OR_MANY;
        !           651: 
        !           652:        } else if (axl_stream_inspect (stream, "*", 1) > 0) {
        !           653: 
        !           654:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found '*' repetition conf");
        !           655:                /* seems the content specification could appear zero
        !           656:                 * up to many */
        !           657:                return ZERO_OR_MANY;
        !           658:        } 
        !           659: 
        !           660:        /* the content specification must appear */
        !           661:        return ONE_AND_ONLY_ONE;
        !           662: }
        !           663: 
        !           664: /** 
        !           665:  * @internal
        !           666:  *
        !           667:  * Support function which creates a child item list, insert it to the
        !           668:  * parent item list received.
        !           669:  * 
        !           670:  * @param parent 
        !           671:  * 
        !           672:  * @return 
        !           673:  */
        !           674: axlDtdElementList * __axl_dtd_create_and_queue (axlDtdElementList * parent)
        !           675: {
        !           676:        axlDtdElementList     * child;
        !           677:        axlDtdElementListNode * node;
        !           678:        
        !           679:        /* create the DTD item list */
        !           680:        child       = axl_new (axlDtdElementList, 1);
        !           681: 
        !           682:        /* make by default the item list to be defined as "not
        !           683:         * defined" until the first separator is found */
        !           684:        child->type = STILL_UNDEF; 
        !           685:        
        !           686:        /* create a node that */
        !           687:        node = __create_axl_dtd_element_list (NULL, child);
        !           688: 
        !           689:        /* create the parent list reference if weren't */
        !           690:        if (parent->itemList == NULL) {
        !           691:                parent->itemList = axl_list_new (axl_list_always_return_1, 
        !           692:                                                 (axlDestroyFunc) __destroy_axl_dtd_element_list);
        !           693:        }
        !           694: 
        !           695:        /* add the node */
        !           696:        axl_list_add (parent->itemList, node);
        !           697: 
        !           698:        /* return the new child created */
        !           699:        return child;
        !           700: }
        !           701: 
        !           702: /** 
        !           703:  * @internal
        !           704:  *
        !           705:  * Updates current chunk readed information to allow perform a better
        !           706:  * code after calling this function.
        !           707:  *
        !           708:  */
        !           709: void __axl_dtd_element_spec_update_chunk_matched (axlStream * stream, 
        !           710:                                                  int * chunk_matched)
        !           711: {
        !           712:        /* check for for sequence or choice characters */
        !           713:        if (axl_stream_inspect (stream, ",", 1) > 0) {
        !           714:                /* flag that we have found a , (choice)
        !           715:                 * separator */
        !           716:                (*chunk_matched) = 1;
        !           717:                
        !           718:        } else if (axl_stream_inspect (stream, "|", 1) > 0) {
        !           719:                /* flag that we have found a | (sequence)
        !           720:                 * separator */
        !           721:                (*chunk_matched) = 2;
        !           722: 
        !           723:        } else if (axl_stream_inspect (stream, ")", 1) > 0) {
        !           724:                /* flag that we have found a | (sequence)
        !           725:                 * separator */
        !           726:                (*chunk_matched) = 3;
        !           727:                
        !           728:        } else if (axl_stream_inspect (stream, "+", 1) > 0) {
        !           729:                /* flag that we have found a | (sequence)
        !           730:                 * separator */
        !           731:                (*chunk_matched) = 4;
        !           732:                
        !           733:        } else if (axl_stream_inspect (stream, "*", 1) > 0) {
        !           734:                /* flag that we have found a | (sequence)
        !           735:                 * separator */
        !           736:                (*chunk_matched) = 5;
        !           737:                
        !           738:        } else if (axl_stream_inspect (stream, "?", 1) > 0) {
        !           739:                /* flag that we have found a | (sequence)
        !           740:                 * separator */
        !           741:                (*chunk_matched) = 6;
        !           742:        }
        !           743: 
        !           744:        return;
        !           745: }
        !           746: 
        !           747: /** 
        !           748:  * @internal
        !           749:  *
        !           750:  * Support function to read the content particule separator once the
        !           751:  * repeat pattern was found 
        !           752:  * 
        !           753:  */
        !           754: axl_bool     __axl_dtd_element_spec_update_chunk_matched_for_cp_separator (axlStream * stream, 
        !           755:                                                                           int * chunk_matched)
        !           756: {
        !           757:        /* consume previous white spaces */
        !           758:        AXL_CONSUME_SPACES (stream);
        !           759: 
        !           760:        /* check for for sequence or choice characters */
        !           761:        if (axl_stream_inspect (stream, ",", 1) > 0) {
        !           762:                /* flag that we have found a , (choice)
        !           763:                 * separator */
        !           764:                (*chunk_matched) = 1;
        !           765:                return axl_true;
        !           766:                
        !           767:        } else if (axl_stream_inspect (stream, "|", 1) > 0) {
        !           768:                /* flag that we have found a | (sequence)
        !           769:                 * separator */
        !           770:                (*chunk_matched) = 2;
        !           771:                return axl_true;
        !           772: 
        !           773:        } else if (axl_stream_inspect (stream, ")", 1) > 0) {
        !           774:                /* flag that we have found a | (sequence)
        !           775:                 * separator */
        !           776:                (*chunk_matched) = 3;
        !           777:                return axl_true;
        !           778:        }
        !           779:        
        !           780:        return axl_false;
        !           781: }
        !           782: 
        !           783: /** 
        !           784:  * @internal
        !           785:  *
        !           786:  * Support function which allows to read the next content particule.
        !           787:  */
        !           788: char * __axl_dtd_read_content_particule (axlStream  * stream, 
        !           789:                                         int        * chunk_matched,
        !           790:                                         axlStack   * dtd_item_stack, 
        !           791:                                         axlError  ** error)
        !           792: {
        !           793:        char * string_aux;
        !           794: 
        !           795:        /* read the spec particule stopping when a white space
        !           796:         * or other character is found */
        !           797:        string_aux = axl_stream_get_until (stream, NULL, chunk_matched, axl_true, 8, 
        !           798:                                           /* basic, default delimiters: 0, 1, 2, 3 */
        !           799:                                           " ", ",", "|", ")",
        !           800:                                           /* repetition configuration: 4, 5, 6 */
        !           801:                                           "+", "*", "?",
        !           802:                                           /* new dtd item list being opened: 8 */
        !           803:                                           "(");
        !           804:        if (string_aux == NULL) {
        !           805:                axl_error_new (-1, "Expected to find a element content specification particule, but it wasn't found",
        !           806:                               stream, error);
        !           807:                axl_stack_free (dtd_item_stack);
        !           808:                axl_stream_free (stream);
        !           809:                return NULL;
        !           810:        }
        !           811:        
        !           812:        /* check the user doesn't nest item list in a not
        !           813:         * proper way */
        !           814:        if (*chunk_matched == 8) {
        !           815:                axl_error_new (-1, "Found a not proper nesting item list for a DTD element, before using ( a separator must be used (CHOICE: |, SEQUENCE: ,)",
        !           816:                               stream, error);
        !           817:                axl_stack_free (dtd_item_stack);
        !           818:                axl_stream_free (stream);
        !           819:                return NULL;
        !           820:        }
        !           821: 
        !           822:        /* nullify stream internal reference */
        !           823:        axl_stream_nullify (stream, LAST_CHUNK);
        !           824:        
        !           825:        /* return the content particule found */
        !           826:        return string_aux;
        !           827: }
        !           828: 
        !           829: /** 
        !           830:  * @internal
        !           831:  *
        !           832:  * Support function which reads current <!ELEMENT specification,
        !           833:  * configuring it to the received axlDtdElement.
        !           834:  * 
        !           835:  * @param stream The stream where the axlDtdElement spec will be read.
        !           836:  *
        !           837:  * @param dtd_element The axlDtdElement that will receive the content
        !           838:  * spec.
        !           839:  *
        !           840:  * @param error An optional \ref axlError, where errors will be
        !           841:  * reported.
        !           842:  * 
        !           843:  * @return \ref axl_true if the content spec was properly read or \ref
        !           844:  * axl_false if not.
        !           845:  */
        !           846: axl_bool     __axl_dtd_read_element_spec (axlStream * stream, axlDtdElement * dtd_element, axlError ** error)
        !           847: {
        !           848:        char              * string_aux;
        !           849:        axl_bool            is_pcdata;
        !           850:        int                 chunk_matched = -1;
        !           851:        axlStack          * dtd_item_stack;
        !           852:        axlDtdElementList * dtd_item_list;
        !           853:        axl_bool            is_empty;
        !           854:        
        !           855:        
        !           856:        /* create the stack used to control which is
        !           857:         * the current context for the items read for
        !           858:         * the xml DTD especification (pd, pd2, (pr|po), ..) */
        !           859:        dtd_item_stack = axl_stack_new (NULL);
        !           860: 
        !           861:        /* create the DTD item list */
        !           862:        dtd_item_list       = axl_new (axlDtdElementList, 1);
        !           863: 
        !           864:        /* by default, set still undef to change it once a separator
        !           865:         * is detected or the function ends. This will help to detect
        !           866:         * problems produced by people mixing content element
        !           867:         * separators. */
        !           868:        dtd_item_list->type = STILL_UNDEF; 
        !           869: 
        !           870:        /* set the content spec list to the dtd element read */
        !           871:        dtd_element->list   = dtd_item_list;
        !           872:           
        !           873:        /* push the item created */
        !           874:        /* axl_stack_push (dtd_item_stack, dtd_item_list); */
        !           875:        
        !           876:        /* consume previous white spaces */
        !           877:        AXL_CONSUME_SPACES (stream);
        !           878: 
        !           879:        /* check that the content specification have an ( */
        !           880:        if (! (axl_stream_inspect (stream, "(", 1))) {
        !           881:                axl_error_new (-1, "Expected to find a element content specification opener \"(\", but it wasn't found",
        !           882:                               stream, error);
        !           883:                axl_stack_free (dtd_item_stack);
        !           884:                axl_stream_free (stream);               
        !           885:                return axl_false;
        !           886:        }
        !           887:        
        !           888:        do {
        !           889:                /* consume previous white spaces */
        !           890:                AXL_CONSUME_SPACES (stream);
        !           891: 
        !           892:                /* a new item list have been opened */
        !           893:                if (axl_stream_inspect (stream, "(", 1) > 0) {
        !           894: 
        !           895:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a DTD item list openining: %d",
        !           896:                                   axl_stack_size (dtd_item_stack));
        !           897: 
        !           898:                        /* a new item list is being defined, we have
        !           899:                         * to queue current dtd_item_list and create a
        !           900:                         * new item list */
        !           901:                        axl_stack_push (dtd_item_stack, dtd_item_list);
        !           902:                        
        !           903:                        /* create the DTD item list */
        !           904:                        dtd_item_list        = __axl_dtd_create_and_queue (dtd_item_list);
        !           905: 
        !           906:                        /* let's continue at the begining */
        !           907:                        continue;
        !           908:                }
        !           909:                
        !           910: 
        !           911:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "iterating again to get a new content particule (item list size: %d)",
        !           912:                           axl_dtd_item_list_count (dtd_item_list));
        !           913: 
        !           914:                /* read the next content particule: here is the chunk
        !           915:                 * matched codes found: 
        !           916:                 * basic, default delimiters: 
        !           917:                 * 0, 1, 2, 3 -> " ", ",", "|", ")" 
        !           918:                 * repetition configuration: 
        !           919:                 * 4, 5, 6  -> "+", "*", "?",
        !           920:                 * new dtd item list being opened: 
        !           921:                 * 8 -> "(" */
        !           922:                string_aux = __axl_dtd_read_content_particule (stream, &chunk_matched, dtd_item_stack, error);
        !           923:                if (string_aux == NULL)
        !           924:                        return axl_false;
        !           925:                
        !           926:                /* check, and record, that the string read is
        !           927:                 * PCDATA */
        !           928:                is_pcdata = axl_cmp (string_aux, "#PCDATA");
        !           929: 
        !           930:                /* add the item read if have something defined */
        !           931: 
        !           932:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found content spec particule: (size: %d) '%s'", 
        !           933:                           strlen (string_aux),
        !           934:                           string_aux);
        !           935: 
        !           936:                /* check if the have matched a white space: next check is
        !           937:                 * based on the call to axl_stream_get_until at the caller
        !           938:                 * function: " " */
        !           939:                if (chunk_matched == 0) {
        !           940: 
        !           941:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, 
        !           942:                                   "found white spaces as delimiter, consuming them (current chunk matched: %d)",
        !           943:                                   chunk_matched);
        !           944:                        
        !           945:                        /* consume previous white spaces */
        !           946:                        AXL_CONSUME_SPACES (stream);
        !           947: 
        !           948:                        /* update current chunk_matched to conform to
        !           949:                         * an stream that have all elements really
        !           950:                         * close: the following function tries to read
        !           951:                         * and update chunk_matched variable to point
        !           952:                         * to the value read for ",", "|", "+", "*",
        !           953:                         * "?" and ")" because white spaces were found */
        !           954:                        __axl_dtd_element_spec_update_chunk_matched (stream, &chunk_matched);
        !           955: 
        !           956: 
        !           957:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, 
        !           958:                                   "current chunk matched before update (%d)",
        !           959:                                   chunk_matched);
        !           960:                }
        !           961: 
        !           962:                /* add the content particule found, this function
        !           963:                 * already detect that a white space was found and
        !           964:                 * consumes all white spaces found */
        !           965:                if (!__axl_dtd_element_content_particule_add (dtd_item_list, string_aux, chunk_matched, stream, error))
        !           966:                        return axl_false;
        !           967: 
        !           968:                if (chunk_matched == 4 || chunk_matched == 5 || chunk_matched == 6) {
        !           969:                        /* found a repetition pattern */
        !           970:                        if (! __axl_dtd_element_spec_update_chunk_matched_for_cp_separator (stream, &chunk_matched)) {
        !           971:                                axl_error_new (-1, "Before a repetition pattern (*,+,?) expected to find a content particule separator",
        !           972:                                               stream, error);
        !           973:                                axl_stack_free (dtd_item_stack);
        !           974:                                axl_stream_free (stream);               
        !           975:                                return axl_false;
        !           976:                        }
        !           977:                }
        !           978: 
        !           979:                /* set current sequence type accoring to separators
        !           980:                 * used */
        !           981:                switch (chunk_matched) {
        !           982:                case 1:
        !           983:                        if (dtd_item_list->type == CHOICE) {
        !           984:                                axl_error_new (-1, "Detected that the DTD definition is mixing content particules separators at the same level ('|' and ','). First detected a sequence spec (,) but then detected a choice element (|)",
        !           985:                                               stream, error);
        !           986:                                axl_stack_free (dtd_item_stack);
        !           987:                                axl_stream_free (stream);               
        !           988:                                return axl_false;
        !           989:                        }
        !           990:                        dtd_item_list->type = SEQUENCE;
        !           991:                        break;
        !           992:                case 2:
        !           993:                        if (dtd_item_list->type == SEQUENCE) {
        !           994:                                axl_error_new (-1, "Detected that the DTD definition is mixing content particules separators at the same level ('|' and ','). First detected a choice spec (|) but then detected a sequence element (,)",
        !           995:                                               stream, error);
        !           996:                                axl_stack_free (dtd_item_stack);
        !           997:                                axl_stream_free (stream);               
        !           998:                                return axl_false;
        !           999:                        }
        !          1000:                        dtd_item_list->type = CHOICE;
        !          1001:                        break;
        !          1002:                }
        !          1003: 
        !          1004:                /* set element type if a element list terminator was
        !          1005:                 * found ( 3 = ')' = chunk_matched) */
        !          1006:                if ((chunk_matched == 3) && is_pcdata) {
        !          1007:                        if (axl_list_length (dtd_item_list->itemList) == 1)
        !          1008:                                dtd_element->type = ELEMENT_TYPE_PCDATA;
        !          1009:                        else if (axl_list_length (dtd_item_list->itemList) > 1)
        !          1010:                                dtd_element->type = ELEMENT_TYPE_MIXED;
        !          1011:                }
        !          1012: 
        !          1013:                /* pop current element list header */
        !          1014:                if (chunk_matched == 3) {
        !          1015:                        do {
        !          1016:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a DTD item list termination: stack status: %d",
        !          1017:                                           axl_stack_size (dtd_item_stack));
        !          1018:                                /* consume previous white spaces */
        !          1019:                                AXL_CONSUME_SPACES (stream);
        !          1020:                                dtd_item_list->times = __axl_dtd_get_repetition_conf (stream);
        !          1021: 
        !          1022:                                /* consume previous white spaces */
        !          1023:                                AXL_CONSUME_SPACES (stream);
        !          1024: 
        !          1025:                                if (axl_stream_inspect (stream, ",", 1) > 0) {
        !          1026:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a sequence (,) separator while reading terminator list");
        !          1027: 
        !          1028:                                        chunk_matched = 1;
        !          1029:                                }
        !          1030:                                else if (axl_stream_inspect (stream, "|", 1) > 0) {
        !          1031:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a choice (|) separator while reading terminator list");
        !          1032:                                        chunk_matched = 2;
        !          1033:                                }
        !          1034:                                
        !          1035:                                /* this means that a ) was found, we have to
        !          1036:                                 * pop current queue */
        !          1037:                                is_empty              = axl_stack_is_empty (dtd_item_stack);
        !          1038:                                if (! is_empty) {
        !          1039:                                        dtd_item_list = axl_stack_pop (dtd_item_stack);
        !          1040:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "getting the next item list in the stack, stack status: %d",
        !          1041:                                                   axl_stack_size (dtd_item_stack));
        !          1042:                                }
        !          1043: 
        !          1044:                                /* special case: check if the next element to
        !          1045:                                 * be read is a new ) */
        !          1046:                                /* consume previous white spaces */
        !          1047:                                AXL_CONSUME_SPACES (stream);
        !          1048: 
        !          1049:                        }while ((axl_stream_inspect (stream, ")", 1) > 0) && !is_empty);
        !          1050: 
        !          1051:                        /* drop a log */
        !          1052:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "terminator sequence status: chunk matched=%d ans stack status: %d",
        !          1053:                                   chunk_matched, axl_stack_size (dtd_item_stack));
        !          1054: 
        !          1055:                }
        !          1056: 
        !          1057:                /* check if we have finished */
        !          1058:        } while (chunk_matched != 3 || (! axl_stack_is_empty (dtd_item_stack)));
        !          1059: 
        !          1060: 
        !          1061:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "content spec terminated, now lookup for the termination");
        !          1062:                
        !          1063:        /* consume previous white spaces */
        !          1064:        /* AXL_CONSUME_SPACES (stream);*/
        !          1065: 
        !          1066:        /* read here repetition specification */
        !          1067:        /* dtd_item_list->times = __axl_dtd_get_repetition_conf (stream); */
        !          1068:        
        !          1069:        /* set default content element separator */
        !          1070:        if (dtd_item_list->type == STILL_UNDEF)
        !          1071:                dtd_item_list->type = SEQUENCE;
        !          1072:                
        !          1073:        /* free the stack used */
        !          1074:        axl_stack_free (dtd_item_stack);
        !          1075: 
        !          1076: 
        !          1077:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "DTD content element specification found and parsed ok");
        !          1078: 
        !          1079: 
        !          1080:        /* content spec readed properly */
        !          1081:        return axl_true;
        !          1082: }
        !          1083: 
        !          1084: /** 
        !          1085:  * @internal
        !          1086:  * 
        !          1087:  * Calculates the number of nodes to be matched at minimum for the
        !          1088:  * provided DTD element. 
        !          1089:  * 
        !          1090:  * @param element The DTD element to configure with its minimum item
        !          1091:  * count to be matched.
        !          1092:  */
        !          1093: int __axl_dtd_parse_element_get_compulsory_num (axlDtdElementList * list)
        !          1094: {
        !          1095:        axlDtdElementListNode * itemNode;
        !          1096:        int                     count    = 0;
        !          1097:        int                     iterator = 0;
        !          1098: 
        !          1099:        /* check for null parameters */
        !          1100:        if (list == NULL)
        !          1101:                return 0;
        !          1102: 
        !          1103:        /* only count for repetitiong patterns that makes obligatory
        !          1104:         * to have childs */
        !          1105:        if (list->times == ONE_AND_ONLY_ONE ||
        !          1106:            list->times == ONE_OR_MANY) {
        !          1107:                
        !          1108:                while (iterator < axl_list_length (list->itemList)) {
        !          1109:                        /* get the reference for the item node */
        !          1110:                        itemNode = axl_list_get_nth (list->itemList, iterator);
        !          1111:                        
        !          1112:                        /* check if the repetitiong patter is
        !          1113:                         * compulsory */
        !          1114:                        if (itemNode->times == ONE_OR_MANY ||
        !          1115:                            itemNode->times == ONE_AND_ONLY_ONE) {
        !          1116:                                /* check if we have an itemNode that has an
        !          1117:                                 * Node or a list */
        !          1118:                                if (itemNode->type == AXL_ELEMENT_NODE) {
        !          1119:                                        /* we have an item node */
        !          1120:                                        count++;
        !          1121:                                        if (list->type == CHOICE) {
        !          1122:                                                /* because we have a
        !          1123:                                                 * choice list, once
        !          1124:                                                 * validated one item,
        !          1125:                                                 * it is the minimum
        !          1126:                                                 * requirement. */
        !          1127:                                                return count;
        !          1128:                                        }
        !          1129:                                } else {
        !          1130:                                        /* we have a list */
        !          1131:                                        count += __axl_dtd_parse_element_get_compulsory_num (itemNode->data);
        !          1132:                                }
        !          1133:                        }
        !          1134:                        
        !          1135:                        /* update the index */
        !          1136:                        iterator++;
        !          1137:                }
        !          1138:        }
        !          1139:                
        !          1140:        /* return current count */
        !          1141:        return count;
        !          1142: }
        !          1143: 
        !          1144: 
        !          1145: /** 
        !          1146:  * @internal
        !          1147:  *
        !          1148:  * Parses a document type element that it is expected to be found at
        !          1149:  * the given stream.
        !          1150:  * 
        !          1151:  * @param dtd The axlDtd where the element type readed must be added.
        !          1152:  *
        !          1153:  * @param stream The stream where the element type if expected to be found.
        !          1154:  *
        !          1155:  * @param error An axlError, optional, reference where error will be
        !          1156:  * reported.
        !          1157:  * 
        !          1158:  * @return axl_true if the element was parsed properly, axl_false if
        !          1159:  * not. The stream associated will be unrefered and the axlError
        !          1160:  * provided will be filled if an error is found.
        !          1161:  */
        !          1162: axl_bool     __axl_dtd_parse_element (axlDtd * dtd, axlStream * stream, axlError ** error)
        !          1163: {
        !          1164:        char              * string_aux;
        !          1165:        int                 matched_chunk = -1;
        !          1166:        axlDtdElement     * element;
        !          1167: 
        !          1168:        /* init the dtd element list */
        !          1169:        if (dtd->elements == NULL)
        !          1170:                dtd->elements = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_dtd_element_free);
        !          1171: 
        !          1172:        /* consume previous white spaces */
        !          1173:        AXL_CONSUME_SPACES (stream);
        !          1174: 
        !          1175:        /* get for the first element declaration */
        !          1176:        if (! (axl_stream_inspect (stream, "<!ELEMENT", 9) > 0)) {
        !          1177:                axl_error_new (-1, "Expected to receive a <!ELEMENT, but it wasn't found", stream, error);
        !          1178:                axl_stream_free (stream);
        !          1179:                return axl_false;
        !          1180:        }
        !          1181: 
        !          1182:        /* consume previous white spaces */
        !          1183:        AXL_CONSUME_SPACES (stream);
        !          1184:        
        !          1185:        /* get the element name */
        !          1186:        string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_false, 3, ">", "(", " ", "<!ELEMENT");
        !          1187:        if (string_aux == NULL) {
        !          1188:                axl_error_new (-1, "Expected to receive a DTD element name for <!ELEMENT declaration, but not found", stream, error);
        !          1189:                axl_stream_free (stream);
        !          1190:                return axl_false;
        !          1191:        }
        !          1192: 
        !          1193:        /* check that the DTD have an element name and an element type */
        !          1194:        if ((matched_chunk == 0) || (matched_chunk == 3)) {
        !          1195:                axl_error_new (-1, "Found a DTD <!ELEMENT declaration, without content specification. Missing value, examples: EMPTY, ANY, (..)", stream, error);
        !          1196:                axl_stream_free (stream);
        !          1197:                return axl_false;
        !          1198:        }
        !          1199: 
        !          1200:        /* nullify internal stream content */
        !          1201:        axl_stream_nullify (stream, LAST_CHUNK);
        !          1202:        
        !          1203:        /* create the DTD element */
        !          1204:        element           = axl_new (axlDtdElement, 1);
        !          1205:        element->name     = string_aux;
        !          1206: 
        !          1207:        /* consume previous white spaces */
        !          1208:        AXL_CONSUME_SPACES (stream);
        !          1209: 
        !          1210:        /* now, check for the basic cases: ANY and EMPTY */
        !          1211:        if (axl_stream_peek (stream, "EMPTY", 5) > 0) {
        !          1212:                /* accept previous peek */
        !          1213:                axl_stream_accept (stream);
        !          1214: 
        !          1215:                /* found empty declaration */
        !          1216:                element->type = ELEMENT_TYPE_EMPTY;
        !          1217: 
        !          1218:        } else if (axl_stream_peek (stream, "ANY", 3) > 0) {
        !          1219:                /* accept previous peek */
        !          1220:                axl_stream_accept (stream);
        !          1221: 
        !          1222:                /* found any declaration */
        !          1223:                element->type = ELEMENT_TYPE_ANY;
        !          1224:        } else {
        !          1225:                /* complex element type declaration, let's roll now
        !          1226:                 * get the element content type read current dtd
        !          1227:                 * element spec. 
        !          1228:                 *
        !          1229:                 * By default, any comple element type definition,
        !          1230:                 * have childrens, until PC data definition is found,
        !          1231:                 * which leads to the two possible values: Mixed and
        !          1232:                 * PcData */
        !          1233:                element->type = ELEMENT_TYPE_CHILDREN;
        !          1234:                if (!__axl_dtd_read_element_spec (stream, element, error))
        !          1235:                        return axl_false;
        !          1236:        }
        !          1237: 
        !          1238:        /* add element found */
        !          1239:        if (! __axl_dtd_add_element (dtd, element, stream, error))
        !          1240:                return axl_false;
        !          1241:        
        !          1242:        /* consume previous white spaces */
        !          1243:        AXL_CONSUME_SPACES (stream);
        !          1244: 
        !          1245:        /* check for the last DTD declaration */
        !          1246:        if (! (axl_stream_inspect (stream, ">", 1))) {
        !          1247:                axl_error_new (-1, "Unable to find last, > terminator for the DTD <!ELEMENT declaration", stream, error);
        !          1248:                axl_stream_free (stream);
        !          1249:                return axl_false;
        !          1250:        }
        !          1251: 
        !          1252:        /* now, count the number of obligatory elements, required for
        !          1253:         * the validation process */
        !          1254:        element->minimum_match = __axl_dtd_parse_element_get_compulsory_num (element->list);
        !          1255: 
        !          1256:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found DTD element declaration read complete: minimum matching elements: %d",
        !          1257:                   element->minimum_match);
        !          1258: 
        !          1259:        /* element type declaration completely read */
        !          1260:        return axl_true;
        !          1261: }
        !          1262: 
        !          1263: /** 
        !          1264:  * @internal
        !          1265:  * 
        !          1266:  * Destroy the provided reference and its associated data.
        !          1267:  * 
        !          1268:  * @param decl The reference declaration.
        !          1269:  */
        !          1270: void axl_dtd_attribute_decl_free (axlDtdAttributeDecl * decl)
        !          1271: {
        !          1272:        /* free the rule name */
        !          1273:        if (decl->name != NULL)
        !          1274:                axl_free (decl->name);
        !          1275: 
        !          1276:        /* free the default value */
        !          1277:        if (decl->default_value != NULL)
        !          1278:                axl_free (decl->default_value);
        !          1279: 
        !          1280:        /* free enum declaration list if defined */
        !          1281:        if (decl->enumvalues != NULL)
        !          1282:                axl_list_free (decl->enumvalues);
        !          1283: 
        !          1284:        /* free the node itself */
        !          1285:        axl_free (decl);
        !          1286:        
        !          1287:        /* nothing more to do */
        !          1288:        return;
        !          1289: }
        !          1290: 
        !          1291: /** 
        !          1292:  * @internal function to dealloc an single attribute set decleration.
        !          1293:  * 
        !          1294:  * @param attribute The reference to dealloc.
        !          1295:  */
        !          1296: void axl_dtd_attribute_free (axlDtdAttribute * attribute)
        !          1297: {
        !          1298:        /* free the attribute list, name and the node itself */
        !          1299:        axl_free (attribute->name);
        !          1300:        axl_list_free (attribute->list);
        !          1301:        axl_free (attribute);
        !          1302: 
        !          1303:        return;
        !          1304: }
        !          1305: 
        !          1306: axl_bool __find_attr_decl (axlPointer _element, axlPointer data)
        !          1307: {
        !          1308:        axlDtdAttributeDecl * decl = _element;
        !          1309:        char                * name = data;
        !          1310: 
        !          1311:        /* check the name */
        !          1312:        if (axl_cmp (decl->name, name))
        !          1313:                return axl_true;
        !          1314: 
        !          1315:        /* it is not the element */
        !          1316:        return axl_false;
        !          1317: }
        !          1318: 
        !          1319: /** 
        !          1320:  * @brief Allows to check if the stream contains a reference to a
        !          1321:  * entity, calling the resolver to get the replacement text to be
        !          1322:  * placed.
        !          1323:  * 
        !          1324:  * @param resolver The function to be called with the replacement
        !          1325:  * text. This function must return the replacement text or NULL if it
        !          1326:  * fails. Failing to return a reference resolution will make the
        !          1327:  * entity reference to appear as is.
        !          1328:  *
        !          1329:  * @param resolver The entity reference resolver function to be called
        !          1330:  * to solve references found.
        !          1331:  *
        !          1332:  * @param data User defined data provided to the function, passed
        !          1333:  * directly to the resolver function once executed.
        !          1334:  *
        !          1335:  * @param stream The stream where the entity reference could appear.
        !          1336:  *
        !          1337:  * @param prefix The reference prefix to recognize. Values allowed
        !          1338:  * are: % (DTD references) and & (general entity references).
        !          1339:  *
        !          1340:  * @param error Optional reference to the axlError to report textual
        !          1341:  * diagnostic errors.
        !          1342:  *
        !          1343:  * @return The function return \ref axl_false if some error while
        !          1344:  * resolving entity references was found. Otherwise the function
        !          1345:  * return axl_true.
        !          1346:  */
        !          1347: axl_bool axl_dtd_check_entity_ref_and_expand (axlDtdEntityResolver   resolver, 
        !          1348:                                              axlPointer             data,
        !          1349:                                              axlStream            * stream, 
        !          1350:                                              const char           * prefix,
        !          1351:                                              axlError            ** error)
        !          1352:                                          
        !          1353: {
        !          1354:        char       * string_aux;
        !          1355:        char       * new_value;
        !          1356:        int          index;
        !          1357: 
        !          1358:        /* check if we have an entity reference using the provided prefix */
        !          1359:        index = axl_stream_get_index (stream);
        !          1360:        if (! (axl_stream_inspect (stream, prefix, 1) > 0))
        !          1361:                return axl_true;
        !          1362: 
        !          1363:        /* get the entity reference until the end */
        !          1364:        string_aux = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, ";");
        !          1365:        if (string_aux == NULL) {
        !          1366:                axl_error_new (-1, "null value received while expecting to find the entity reference to resolve.", stream, error);
        !          1367:                axl_stream_free (stream);
        !          1368:                return axl_false;
        !          1369:        } /* end if */
        !          1370: 
        !          1371:        axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found entity reference: %s%s;...resolving", prefix, string_aux);
        !          1372: 
        !          1373:        /* resolve the reference */
        !          1374:        new_value = (char *) resolver (string_aux, data);
        !          1375:        if (new_value == NULL) {
        !          1376:                axl_stream_move (stream, index);
        !          1377:                return axl_true;
        !          1378:        } /* end if */
        !          1379: 
        !          1380:        /* accept content consumed */
        !          1381:        axl_stream_accept (stream);
        !          1382: 
        !          1383:        axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "entity resolved to: %s", new_value);
        !          1384: 
        !          1385:        /* place the replacement data at the start of the stream */
        !          1386:        new_value = axl_strdup_printf ("%s ", new_value);
        !          1387:        axl_stream_push (stream, new_value, strlen (new_value));
        !          1388:        axl_free (new_value);
        !          1389:        
        !          1390:        return axl_true;
        !          1391: }
        !          1392: 
        !          1393: /** 
        !          1394:  * @internal Entity resolver used by __axl_dtd_parse_attlist.
        !          1395:  */
        !          1396: const char * __axl_dtd_entity_resolver (const char * entityName, axlPointer data)
        !          1397: {
        !          1398:        /* return the entity resolution */
        !          1399:        return axl_dtd_entity_value ((axlDtd *) data, entityName, PARAMETER_ENTITY);
        !          1400: } /* end if */
        !          1401: 
        !          1402: axlList * __axl_dtd_parse_enumvalues (const char * _enum_values)
        !          1403: {
        !          1404:        char    ** result;
        !          1405:        int        iterator;
        !          1406:        axlList  * list;
        !          1407: 
        !          1408:        result   = axl_stream_split (_enum_values, 1, "|");
        !          1409:        iterator = 0;
        !          1410:        list     = axl_list_new (axl_list_always_return_1, axl_free);
        !          1411: 
        !          1412:        
        !          1413:        while (result[iterator]) {
        !          1414:                /* clean the enum value */
        !          1415:                axl_stream_trim (result[iterator]);
        !          1416: 
        !          1417:                /* add to the list */
        !          1418:                axl_list_add (list, axl_strdup (result[iterator]));
        !          1419: 
        !          1420:                /* update the iterator value */
        !          1421:                iterator++;
        !          1422: 
        !          1423:        } /* end while */
        !          1424:        
        !          1425:        /* free tokens */
        !          1426:        axl_stream_freev (result);
        !          1427:        
        !          1428:        /* return the list */
        !          1429:        return list;
        !          1430: }
        !          1431: 
        !          1432: /** 
        !          1433:  * @internal function used by \ref axl_dtd_attr_validation function to
        !          1434:  * lookup ATTLIST contraints flaged as unique ID.
        !          1435:  */
        !          1436: axl_bool __find_id_decl (axlPointer _element, axlPointer data)
        !          1437: {
        !          1438:        /* return the comparision */
        !          1439:        return (((axlDtdAttributeDecl *) _element)->type == TOKENIZED_TYPE_ID);
        !          1440:        
        !          1441: } /* end __find_id_decl */
        !          1442: 
        !          1443: 
        !          1444: /** 
        !          1445:  * @internal
        !          1446:  * 
        !          1447:  * Parse the <!ATTLIST decleration, registering it into the provided
        !          1448:  * dtd element.
        !          1449:  */
        !          1450: axl_bool __axl_dtd_parse_attlist (axlDtd * dtd, axlStream * stream, axlError ** error)
        !          1451: {
        !          1452:        char                * string_aux    = NULL;
        !          1453:        int                   matched_chunk = -1;
        !          1454:        axlDtdAttribute     * attribute     = NULL;
        !          1455:        axlDtdAttributeDecl * decl          = NULL;
        !          1456:        axlDtdAttributeDecl * declAux       = NULL;
        !          1457:        char                * err_msg;
        !          1458: 
        !          1459:        /* init the dtd attr list */
        !          1460:        if (dtd->attributes == NULL)
        !          1461:                dtd->attributes = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_dtd_attribute_free);
        !          1462: 
        !          1463:        /* consume previous white spaces */
        !          1464:        AXL_CONSUME_SPACES (stream);
        !          1465: 
        !          1466:        /* get the element name */
        !          1467:        string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_false, 1, " ");
        !          1468:        if (string_aux == NULL) {
        !          1469:                axl_error_new (-1, "Expected to receive a DTD attribute name for <!ATTLIST declaration, but not found", stream, error);
        !          1470:                axl_stream_free (stream);
        !          1471:                return axl_false;
        !          1472:        }
        !          1473: 
        !          1474:        axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found dtd attr declaration for node: <%s>", string_aux);
        !          1475: 
        !          1476:        /* find the node that holds all attr declarations for the node found */
        !          1477:        attribute         = axl_dtd_get_attr (dtd, string_aux);
        !          1478: 
        !          1479:        /* check if found */
        !          1480:        if (attribute == NULL) {
        !          1481:                /* create the axlDtdAttribute holder */
        !          1482:                attribute = axl_new (axlDtdAttribute, 1);
        !          1483: 
        !          1484:                /* record the node to which the list of rules applies */
        !          1485:                axl_stream_nullify (stream, LAST_CHUNK);
        !          1486:                attribute->name   = string_aux;
        !          1487: 
        !          1488:                /* init the attribute rule list */
        !          1489:                attribute->list   = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_dtd_attribute_decl_free);
        !          1490: 
        !          1491:                /* now configure this new attribute inside the dtd */
        !          1492:                axl_list_add (dtd->attributes, attribute);
        !          1493:        } /* end if */
        !          1494: 
        !          1495:        /* now get the list of attributes */
        !          1496:        while (1) {
        !          1497:                axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "finding next att declaration");
        !          1498: 
        !          1499:                /* consume previous white spaces */
        !          1500:                AXL_CONSUME_SPACES (stream);
        !          1501: 
        !          1502:                /* check if we have finished */
        !          1503:                if (axl_stream_inspect (stream, ">", 1) > 0)
        !          1504:                        break;
        !          1505: 
        !          1506:                /* get the attribute name the rules applies */
        !          1507:                string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_false, 1, " ");
        !          1508:                if (string_aux == NULL) {
        !          1509:                        axl_error_new (-1, "Expected to receive an attribute name for <!ATTLIST declaration, but not found", stream, error);
        !          1510:                        axl_stream_free (stream);
        !          1511:                        return axl_false;
        !          1512:                }
        !          1513: 
        !          1514:                /* nully the string and store it new rule created */
        !          1515:                axl_stream_nullify (stream, LAST_CHUNK);
        !          1516: 
        !          1517:                /* create a new attribute single constraint */
        !          1518:                decl            = axl_new (axlDtdAttributeDecl, 1);
        !          1519:                decl->name      = string_aux;
        !          1520: 
        !          1521:                /* add the attribute constraint to the list */
        !          1522:                axl_list_add (attribute->list, decl);
        !          1523: 
        !          1524:                axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "find constraint for attribute name=%s", decl->name);
        !          1525: 
        !          1526:                /* consume previous white spaces */
        !          1527:                AXL_CONSUME_SPACES (stream);
        !          1528: 
        !          1529:                axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking constraint type..");
        !          1530: 
        !          1531:                /* check for an entity reference and expand the stream
        !          1532:                 * content with its resolution */
        !          1533:                if (! axl_dtd_check_entity_ref_and_expand (__axl_dtd_entity_resolver, dtd, stream, "%", error))
        !          1534:                        return axl_false;
        !          1535: 
        !          1536:                axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "about to check attr constraint type, stream status: '%s'",
        !          1537:                         axl_stream_get_following (stream, 30));
        !          1538:                
        !          1539:                /* now check the contraint type */
        !          1540:                if (axl_stream_inspect (stream, "NOTATION", 8) > 0) {
        !          1541:                        /* parse notation declaration */
        !          1542:                }else if (axl_stream_inspect (stream, "(", 1) > 0) {
        !          1543:                        /* parse enum declaration */
        !          1544:                        string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_true, 1, ")");
        !          1545:                        if (string_aux == NULL) {
        !          1546:                                axl_error_new (-1, "expected to find enum declaration but termination caracter ')' was not found", stream, error);
        !          1547:                                axl_stream_free (stream);
        !          1548:                                return axl_false;
        !          1549:                        } /* end if */
        !          1550:                        decl->type       = ENUMERATION_TYPE;
        !          1551:                        decl->enumvalues = __axl_dtd_parse_enumvalues (string_aux);
        !          1552:                }else {
        !          1553:                        /* set the attribute type */
        !          1554:                        if (axl_stream_inspect (stream, "CDATA", 5) > 0) {
        !          1555:                                decl->type = CDATA_ATTRIBUTE;
        !          1556:                        } else if (axl_stream_inspect (stream, "IDREFS", 6) > 0) {
        !          1557:                                
        !          1558:                                /* flag the type */
        !          1559:                                decl->type = TOKENIZED_TYPE_IDREFS;
        !          1560: 
        !          1561:                                /* flag the dtd to have a IDREF declaration */
        !          1562:                                dtd->haveIdRefDecl = axl_true;
        !          1563:                        } else if (axl_stream_inspect (stream, "IDREF", 5) > 0) {
        !          1564:                                /* notify type found */
        !          1565:                                decl->type = TOKENIZED_TYPE_IDREF;
        !          1566: 
        !          1567:                                /* flag the dtd to have a IDREF declaration */
        !          1568:                                dtd->haveIdRefDecl = axl_true;
        !          1569:                                
        !          1570:                        } else if (axl_stream_inspect (stream, "ID", 2) > 0) {
        !          1571:                                
        !          1572:                                /* notify the type found */
        !          1573:                                decl->type      = TOKENIZED_TYPE_ID;
        !          1574: 
        !          1575:                                /* flag the dtd to have a ID declaration */
        !          1576:                                dtd->haveIdDecl = axl_true;
        !          1577:                                
        !          1578:                        } else if (axl_stream_inspect (stream, "ENTITY", 6) > 0)
        !          1579:                                decl->type = TOKENIZED_TYPE_ENTITY;
        !          1580:                        else if (axl_stream_inspect (stream, "ENTITIES", 8) > 0)
        !          1581:                                decl->type = TOKENIZED_TYPE_ENTITIES;
        !          1582:                        else if (axl_stream_inspect (stream, "NMTOKENS", 8) > 0)
        !          1583:                                decl->type = TOKENIZED_TYPE_NMTOKENS;
        !          1584:                        else if (axl_stream_inspect (stream, "NMTOKEN", 7) > 0)
        !          1585:                                decl->type = TOKENIZED_TYPE_NMTOKEN;
        !          1586:                        else {
        !          1587:                                axl_error_new (-1, "Unrecognied attr type declaration found, check your <!ATTLIST declaration", stream, error);
        !          1588:                                axl_stream_free (stream);
        !          1589:                                return axl_false;
        !          1590:                        } /* end if */
        !          1591:                } /* end if */
        !          1592: 
        !          1593:                /* consume previous white spaces */
        !          1594:                AXL_CONSUME_SPACES (stream);
        !          1595: 
        !          1596:                axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking default value declaration, stream status: '%s'",
        !          1597:                         axl_stream_get_following (stream, 30));
        !          1598: 
        !          1599:                /* get default declaration value */
        !          1600:                if (axl_stream_inspect (stream, "#REQUIRED", 9) > 0) {
        !          1601:                        decl->defaults = ATT_REQUIRED;
        !          1602:                } else if (axl_stream_inspect (stream, "#IMPLIED", 8) > 0) {
        !          1603:                        decl->defaults = ATT_IMPLIED;
        !          1604:                } else {
        !          1605:                        decl->defaults = ATT_IMPLIED;
        !          1606:                        if (axl_stream_inspect (stream, "#FIXED", 6) > 0) {
        !          1607:                                decl->defaults = ATT_FIXED;
        !          1608: 
        !          1609:                                /* consume previous white spaces */
        !          1610:                                AXL_CONSUME_SPACES (stream);
        !          1611:                        }
        !          1612: 
        !          1613:                        /* check default value for this case */
        !          1614:                        if (! (axl_stream_peek (stream, "\"", 1) > 0 ||
        !          1615:                               axl_stream_peek (stream, "'", 1) > 0)) {
        !          1616:                                err_msg = axl_strdup_printf ("Unable to find default attribute declaration (#REQUIRED, #IMPLIED, #FIXED)  for attribute %s, node <%s>",
        !          1617:                                                             decl->name, attribute->name);
        !          1618:                                axl_error_new (-1, err_msg, stream, error);
        !          1619:                                axl_stream_free (stream);
        !          1620:                                axl_free (err_msg);
        !          1621:                                return axl_false;
        !          1622:                        } /* end if */
        !          1623:                } /* end if */
        !          1624: 
        !          1625:                /* check constraint for ID types */
        !          1626:                if (decl->type == TOKENIZED_TYPE_ID) {
        !          1627:                        /* check that the node doesn't have any unique
        !          1628:                         * id declared */
        !          1629: 
        !          1630:                        /* check if the node have TOKENIZED_TYPE_ID */
        !          1631:                        declAux = axl_list_lookup (attribute->list, __find_id_decl, NULL);
        !          1632:                        if (declAux != NULL && !axl_cmp (declAux->name, decl->name)) {
        !          1633:                                err_msg = axl_strdup_printf ("Found ATTLIST declaration, with several ID declarations <ATTLIST %s %s..",
        !          1634:                                                             attribute->name, decl->name);
        !          1635:                                axl_error_new (-1, err_msg, stream, error);
        !          1636:                                axl_stream_free (stream);
        !          1637:                                axl_free (err_msg);
        !          1638:                                return axl_false;
        !          1639:                        } /* end if */
        !          1640:                        
        !          1641:                        /* check required and implied */
        !          1642:                        if (decl->defaults != ATT_REQUIRED && decl->defaults != ATT_IMPLIED) {
        !          1643:                                err_msg = axl_strdup_printf ("Found ATTLIST declaration, with ID, that don't have configured either #IMPLICIT or #REQUIRED for attribute %s, node <%s>",
        !          1644:                                                             decl->name, attribute->name);
        !          1645:                                axl_error_new (-1, err_msg, stream, error);
        !          1646:                                axl_stream_free (stream);
        !          1647:                                axl_free (err_msg);
        !          1648:                                return axl_false;
        !          1649:                        } /* end if */
        !          1650:                } /* end if */
        !          1651: 
        !          1652:                /* consume previous white spaces */
        !          1653:                AXL_CONSUME_SPACES (stream);
        !          1654: 
        !          1655:                /* nullify to check this value later */
        !          1656:                string_aux = NULL;
        !          1657:                if (axl_stream_inspect (stream, "\"", 1) > 0) {
        !          1658:                        /* get until */
        !          1659:                        string_aux = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, "\"");
        !          1660:                } else if (axl_stream_inspect (stream, "'", 1) > 0) {
        !          1661:                        /* get until */
        !          1662:                        string_aux = axl_stream_get_until (stream, NULL, NULL, axl_true, 1, "\'");
        !          1663:                } /* end if */
        !          1664: 
        !          1665:                /* check if default value was found */
        !          1666:                if (string_aux != NULL) {
        !          1667: 
        !          1668:                        /* found default value, check if we have an
        !          1669:                         * enumeration type, enforcing that the value
        !          1670:                         * defined to be inside the enumeration */
        !          1671:                        if (decl->type == ENUMERATION_TYPE) {
        !          1672:                                if (axl_list_lookup (decl->enumvalues, axl_list_find_string, string_aux) == NULL) {
        !          1673:                                        axl_error_new (-1, 
        !          1674:                                                       "Configured a default value for an attribute list which only accepts a set of enum values that do not containt it.",
        !          1675:                                                       stream, error);
        !          1676:                                        axl_stream_free (stream);
        !          1677:                                        return axl_false;
        !          1678:                                } /* end if */
        !          1679:                        } /* end if */
        !          1680: 
        !          1681:                        /* nullify value and make string_aux to be
        !          1682:                         * owned by the axlDtdAttributeDecl
        !          1683:                         * reference */
        !          1684:                        axl_stream_nullify (stream, LAST_CHUNK);
        !          1685:                        decl->default_value = string_aux;
        !          1686:                } /* end if */
        !          1687: 
        !          1688:        } /* end while */
        !          1689:                
        !          1690:        /* properly parsed */
        !          1691:        return axl_true;
        !          1692: }
        !          1693: 
        !          1694: /** 
        !          1695:  * @internal
        !          1696:  * 
        !          1697:  * Destroy the provided entity reference and all allocated memory.
        !          1698:  * 
        !          1699:  * @param entity The entity the deallocate.
        !          1700:  */
        !          1701: void axl_dtd_entity_free (axlDtdEntity * entity)
        !          1702: {
        !          1703:        /* the entity reference */
        !          1704:        axl_return_if_fail (entity);
        !          1705: 
        !          1706:        /* free the entity name */
        !          1707:        if (entity->name)
        !          1708:                axl_free (entity->name);
        !          1709:        
        !          1710:        /* free the content */
        !          1711:        if (entity->content)
        !          1712:                axl_free (entity->content);
        !          1713: 
        !          1714:        /* free external data if defined */
        !          1715:        if (entity->data) {
        !          1716:                /* free system literal */
        !          1717:                if (entity->data->system_literal)
        !          1718:                        axl_free (entity->data->system_literal);
        !          1719:                
        !          1720:                /* free public literal */
        !          1721:                if (entity->data->public_literal)
        !          1722:                        axl_free (entity->data->public_literal);
        !          1723: 
        !          1724:                /* free ndata literal */
        !          1725:                if (entity->data->ndata)
        !          1726:                        axl_free (entity->data->ndata);
        !          1727: 
        !          1728:                /* free the node itself */
        !          1729:                axl_free (entity->data);
        !          1730:        }
        !          1731: 
        !          1732:        /* free the node */
        !          1733:        axl_free (entity);
        !          1734: 
        !          1735:        return;
        !          1736: }
        !          1737: 
        !          1738: /** 
        !          1739:  * @internal
        !          1740:  *
        !          1741:  * Parses an entity definition from the current status of the stream
        !          1742:  * provided.
        !          1743:  */
        !          1744: axl_bool __axl_dtd_parse_entity (axlDtd * dtd, axlStream * stream, axlError ** error)
        !          1745: {
        !          1746:        char         * string_aux;
        !          1747:        int            matched_chunk;
        !          1748:        axlDtdEntity * entity;
        !          1749: 
        !          1750:        /* init the dtd element list */
        !          1751:        if (dtd->entities == NULL)
        !          1752:                dtd->entities = axl_list_new (axl_list_always_return_1, (axlDestroyFunc) axl_dtd_entity_free);
        !          1753:        
        !          1754:        /* consume previous white spaces */
        !          1755:        AXL_CONSUME_SPACES (stream);
        !          1756: 
        !          1757:        /* get for the first element declaration */
        !          1758:        if (! (axl_stream_inspect (stream, "<!ENTITY", 8) > 0)) {
        !          1759:                axl_error_new (-1, "Expected to receive a <!ENTITY, but it wasn't found", stream, error);
        !          1760:                axl_stream_free (stream);
        !          1761:                return axl_false;
        !          1762:        }
        !          1763: 
        !          1764:        /* consume previous white spaces */
        !          1765:        AXL_CONSUME_SPACES (stream);
        !          1766: 
        !          1767:        /* create a new entity */
        !          1768:        entity = axl_new (axlDtdEntity, 1);
        !          1769: 
        !          1770:        /* set the entity and return axl_true */
        !          1771:        axl_list_add (dtd->entities, entity);
        !          1772: 
        !          1773:        /* check for parameter entity definition */
        !          1774:        if (axl_stream_inspect (stream, "%", 1) > 0) {
        !          1775:                /* set the entity type */
        !          1776:                entity->type = PARAMETER_ENTITY;
        !          1777:                
        !          1778:                /* consume previous white spaces */
        !          1779:                AXL_CONSUME_SPACES (stream);
        !          1780: 
        !          1781:        } else
        !          1782:                entity->type = GENERAL_ENTITY;
        !          1783: 
        !          1784:        /* get the element name */
        !          1785:        string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_false, 1, " ");
        !          1786:        if (string_aux == NULL) {
        !          1787:                axl_error_new (-1, "Expected to receive a DTD entity name for <!ENTITY declaration, but not found", stream, error);
        !          1788:                axl_stream_free (stream);
        !          1789:                return axl_false;
        !          1790:        }
        !          1791: 
        !          1792:        /* set the name */
        !          1793:        axl_stream_nullify (stream, LAST_CHUNK);
        !          1794:        entity->name = string_aux;
        !          1795: 
        !          1796:        /* consume previous white spaces */
        !          1797:        AXL_CONSUME_SPACES (stream);
        !          1798: 
        !          1799:        /* now check if we have an external reference */
        !          1800:        if (axl_stream_inspect (stream, "PUBLIC", 6) > 0) {
        !          1801:                /* we have a public external resource definition */
        !          1802:                
        !          1803:        }else if (axl_stream_inspect (stream, "SYSTEM", 6) > 0) {
        !          1804:                /* we have a system definition */
        !          1805:                
        !          1806:        }else {
        !          1807:                /* we have a plain value get the content remove next "
        !          1808:                   and ' if defined */
        !          1809:                if (! ((axl_stream_inspect (stream, "\"", 1) > 0))) {
        !          1810:                        if (! (axl_stream_inspect (stream, "\'", 1) > 0)) {
        !          1811:                                axl_error_new (-2, "Expected to find entity value initiator (\") or ('), every entity value must start with them", 
        !          1812:                                               stream, error);
        !          1813:                                axl_stream_free (stream);
        !          1814:                                return axl_false;
        !          1815:                        }
        !          1816:                        /* knowing that ' was matched, now get the attribute value */
        !          1817:                        string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_true, 1, "'");
        !          1818:                }else {
        !          1819:                        /* knowhing that " was matched, now get the attribute value */
        !          1820:                        string_aux = axl_stream_get_until (stream, NULL, &matched_chunk, axl_true, 1, "\"");
        !          1821:                }
        !          1822: 
        !          1823:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "entity value found: [%s]", string_aux);
        !          1824:                
        !          1825:                /* nullify internal reference so we have the
        !          1826:                 * only one reference to entity content value
        !          1827:                 * inside string_aux */
        !          1828:                axl_stream_nullify (stream, LAST_CHUNK);
        !          1829: 
        !          1830:                /* set the value */
        !          1831:                entity->content = string_aux;
        !          1832:        }
        !          1833: 
        !          1834:        /* consume previous white spaces */
        !          1835:        AXL_CONSUME_SPACES (stream);
        !          1836: 
        !          1837:        /* check last item to parse */
        !          1838:        if (! (axl_stream_inspect (stream, ">", 1) > 0)) {
        !          1839:                axl_error_new (-2, "Expected to find entity definition terminator (>), but it wasn't found", 
        !          1840:                               stream, error);
        !          1841:                axl_stream_free (stream);
        !          1842:                return axl_false;
        !          1843:        }
        !          1844: 
        !          1845:        return axl_true;
        !          1846: }
        !          1847: 
        !          1848: 
        !          1849: /** 
        !          1850:  * @internal
        !          1851:  * 
        !          1852:  * Implements DTD parsing, reading it from a direct buffer, or a file
        !          1853:  * path or a file handle.
        !          1854:  */
        !          1855: axlDtd * __axl_dtd_parse_common (const char * entity, int entity_size, 
        !          1856:                                 const char * file_path, int fd_handle, 
        !          1857:                                 axlError ** error)
        !          1858: {
        !          1859:        axlStream * stream;
        !          1860:        axlDtd    * dtd;
        !          1861:        int         iterator;
        !          1862:        
        !          1863:        /* create the stream associated */
        !          1864:        stream = axl_stream_new (entity, entity_size, file_path, fd_handle, error);
        !          1865:        axl_return_val_if_fail (stream, NULL);
        !          1866: 
        !          1867:        dtd    = __axl_dtd_new ();
        !          1868:        axl_stream_link (stream, dtd, (axlDestroyFunc) axl_dtd_free);
        !          1869: 
        !          1870:        iterator = 0;
        !          1871:        while (axl_stream_remains (stream)) {
        !          1872:                /* get rid from comments found */
        !          1873:                if (! axl_doc_consume_comments (NULL, stream, error))
        !          1874:                        return NULL;
        !          1875:                
        !          1876:                /* check for element declaration */
        !          1877:                if (axl_stream_peek (stream, "<!ELEMENT", 9) > 0) {
        !          1878:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found DTD element declaration");
        !          1879:                        /* found element declaration */
        !          1880:                        if (! __axl_dtd_parse_element (dtd, stream, error))
        !          1881:                                return NULL;
        !          1882:                        
        !          1883:                        continue;
        !          1884: 
        !          1885:                }
        !          1886: 
        !          1887:                /* check for attribute list declarations */
        !          1888:                if (axl_stream_inspect (stream, "<!ATTLIST", 9) > 0) {
        !          1889:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found DTD attribute list declaration");
        !          1890: 
        !          1891:                        /* parse it */
        !          1892:                        if (! __axl_dtd_parse_attlist (dtd, stream, error))
        !          1893:                                return NULL;
        !          1894:                        
        !          1895:                        continue;
        !          1896:                }
        !          1897: 
        !          1898:                /* check for the entity declaration */
        !          1899:                if (axl_stream_peek (stream, "<!ENTITY", 8) > 0) {
        !          1900:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found DTD entity declaration");
        !          1901: 
        !          1902:                        /* parse the entity definition */
        !          1903:                        if (! __axl_dtd_parse_entity (dtd, stream, error))
        !          1904:                                return NULL;
        !          1905: 
        !          1906:                        continue;
        !          1907:                }
        !          1908: 
        !          1909:                /* stop the loop */
        !          1910:                if (iterator == 3) {
        !          1911:                        axl_error_new (-1, "unable to process DTD content, unable to find expected information (no <!ELEMENT, <!ATTLIST or <!ENTITY declaration)", stream, error);
        !          1912:                        axl_stream_free (stream);
        !          1913:                        return NULL;
        !          1914:                }
        !          1915:                iterator++;
        !          1916:        }
        !          1917: 
        !          1918: 
        !          1919:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "DTD elements totally loaded, building references..");
        !          1920: 
        !          1921:        /* update current root reference, the DTD root for the DTD
        !          1922:         * document already parsed */
        !          1923:        if (dtd->elements != NULL) 
        !          1924:                dtd->root = __axl_dtd_get_new_root (dtd);
        !          1925: 
        !          1926:        /* check if the DTD has ID declarations if found IDREF
        !          1927:         * declarations */
        !          1928:        if (! dtd->haveIdDecl && dtd->haveIdRefDecl) {
        !          1929:                axl_error_new (-1, "DTD semantic error, found IDREF attribute declaration but no attribute ID declaration was found.", stream, error);
        !          1930:                axl_stream_free (stream);
        !          1931:                return NULL;
        !          1932:        }
        !          1933:        
        !          1934:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "DTD load COMPLETE");
        !          1935: 
        !          1936:        axl_stream_unlink (stream);
        !          1937:        axl_stream_free (stream);
        !          1938:        return dtd;
        !          1939: }
        !          1940: 
        !          1941: /** 
        !          1942:  * @brief Allows to parse the provided entity, which is expected to
        !          1943:  * contain a DTD (Document Type Definition).
        !          1944:  * 
        !          1945:  * @param entity The document type definition to parse.
        !          1946:  *
        !          1947:  * @param entity_size The document size, or -1 to make the function to
        !          1948:  * figure out current size.
        !          1949:  *
        !          1950:  * @param error An optional \ref axlError where errors will be reported.
        !          1951:  * 
        !          1952:  * @return A newly allocated \ref axlDtd that must be deallocated when
        !          1953:  * no longer need with \ref axl_dtd_free. The function could return
        !          1954:  * NULL on failure detected. On that case, it is requred to check \ref
        !          1955:  * axlError variable, if defined.
        !          1956:  */
        !          1957: axlDtd   * axl_dtd_parse (const char * entity, 
        !          1958:                          int          entity_size,
        !          1959:                          axlError ** error)
        !          1960: {
        !          1961: 
        !          1962:        return __axl_dtd_parse_common (entity, entity_size, NULL, -1, error);
        !          1963: }
        !          1964: 
        !          1965: /** 
        !          1966:  * @brief Allows to parse the provided DTD definition, which is found
        !          1967:  * on the provided file path.
        !          1968:  * 
        !          1969:  * @param file_path The file path where it is expected to receive a
        !          1970:  * DTD file.
        !          1971:  *
        !          1972:  * @param error An optional \ref axlError reference where all errors found will be reported.
        !          1973:  * 
        !          1974:  * @return A newly allocated \ref axlDtd instance or NULL if it fails.
        !          1975:  *
        !          1976:  * <b>Making a DTD to be inline loaded: </b><br>
        !          1977:  * 
        !          1978:  * It may be helpful to make the DTD definition available at your
        !          1979:  * binary, inline compiled, to avoid distributing DTD files along with
        !          1980:  * libraries, etc. This also solves installation problems like
        !          1981:  * provisioning a default location to make your application to find
        !          1982:  * such files.
        !          1983:  *
        !          1984:  * With the following command you can create an inline representation
        !          1985:  * from your DTD file:
        !          1986:  * \code
        !          1987:  * >> axl-knife --input your-file.dtd --dtd-to-c --output your-file.dtd.h --ifnewer
        !          1988:  * \endcode
        !          1989:  *
        !          1990:  * This will create a header with an C-macro style definition of your
        !          1991:  * DTD. Now, you can include it using:
        !          1992:  *
        !          1993:  * \code
        !          1994:  * #include <your-file.dtd.h>
        !          1995:  * \endcode
        !          1996:  *
        !          1997:  * In the case you are developing a library, it is recommended to do
        !          1998:  * such include at the body implementation (usually .c or .cpp files,
        !          1999:  * to avoid requiring your API consumers to also include your DTD
        !          2000:  * inline definition). 
        !          2001:  *
        !          2002:  * Now, to load your DTD file, use the following:
        !          2003:  *
        !          2004:  * \code
        !          2005:  * axlError * err = NULL;
        !          2006:  * axlDtd   * dtd = axl_dtd_parse (YOUR_FILE_DTD, -1, &err);
        !          2007:  * if (dtd == NULL) {
        !          2008:  *    // This won't happen unless axl-runtime error found, since axl-knife 
        !          2009:  *    // checks your dtd file before producing the in-line definition.
        !          2010:  *    // However, bug happens! check this.
        !          2011:  * }
        !          2012:  * \endcode
        !          2013:  */
        !          2014: axlDtd   * axl_dtd_parse_from_file (const char * file_path,
        !          2015:                                    axlError ** error)
        !          2016: {
        !          2017:        return __axl_dtd_parse_common (NULL, -1, file_path, -1, error);
        !          2018: }
        !          2019: 
        !          2020: 
        !          2021: /** 
        !          2022:  * @internal
        !          2023:  * 
        !          2024:  * Support function for axl_dtd_validate which checks if the provided
        !          2025:  * parent have its childs configuration according to the values
        !          2026:  * expresed on the sequenced represented by the itemList.
        !          2027:  *
        !          2028:  * The function return axl_true if the validation was ok, or axl_false
        !          2029:  * if something have failed. It also creates an error, using the
        !          2030:  * optional axlError reference received.
        !          2031:  */
        !          2032: axl_bool     __axl_dtd_validate_sequence (axlNode            * parent, 
        !          2033:                                          int                * child_position,
        !          2034:                                          axlDtdElementList  * itemList, 
        !          2035:                                          axlError          ** error,
        !          2036:                                          axl_bool             try_match,
        !          2037:                                          axl_bool             top_level)
        !          2038: {
        !          2039:        int                      iterator        = 0;
        !          2040:        int                      child_pos       = *child_position;
        !          2041:        axlNode                * node;
        !          2042:        axlDtdElementListNode  * itemNode;
        !          2043:        axl_bool                 status          = axl_false;
        !          2044:        axl_bool                 one_matched;
        !          2045:        AxlDtdTimes              times;
        !          2046:        
        !          2047: 
        !          2048:        axl_return_val_if_fail (parent, axl_false);
        !          2049:        axl_return_val_if_fail (itemList, axl_false);
        !          2050: 
        !          2051: 
        !          2052:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "validating a sequence list: iterator=%d, item list count=%d, at child position=%d",
        !          2053:                 iterator, axl_dtd_item_list_count (itemList), child_pos);
        !          2054: 
        !          2055:        /* iterate over the sequence, checking its order */
        !          2056:        while (iterator < axl_dtd_item_list_count (itemList)) {
        !          2057:                
        !          2058:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "getting next item node from the DTD item list at: %d",
        !          2059:                         iterator);
        !          2060:                
        !          2061:                /* get the item node specification */
        !          2062:                itemNode    = axl_dtd_item_list_get_node (itemList, iterator);
        !          2063:                one_matched = axl_false;
        !          2064:                times       = axl_dtd_item_node_get_repeat (itemNode);
        !          2065: 
        !          2066:                do {
        !          2067: 
        !          2068:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "getting node at child position: %d",
        !          2069:                                   child_pos);
        !          2070: 
        !          2071:                        /* get the node that is located at the same position
        !          2072:                         * than the sequence */
        !          2073:                        if (child_pos < axl_node_get_child_num (parent)) {
        !          2074:                                node     = axl_node_get_child_nth (parent, child_pos);
        !          2075:                        } else
        !          2076:                                node     = NULL;
        !          2077: 
        !          2078:                        /* the node child list have ended, check if
        !          2079:                         * this situation was expected */
        !          2080:                        if (node == NULL) {
        !          2081:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "no more child nodes to validate at %d, for parent: %s, times: %d, iterator: %d, item count: %d",
        !          2082:                                           child_pos, axl_node_get_name (parent), times,
        !          2083:                                           iterator, axl_dtd_item_list_count (itemList));
        !          2084:                                /* check if we were working with a
        !          2085:                                 * list, which have matched at least
        !          2086:                                 * one item */
        !          2087:                                if (times == ONE_OR_MANY && one_matched && status) {
        !          2088:                                        if ((iterator + 1) == axl_dtd_item_list_count (itemList)) {
        !          2089:                                                *child_position = child_pos;
        !          2090:                                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sequence validated with child position (III): %d", child_pos);
        !          2091:                                                return axl_true;
        !          2092:                                        } 
        !          2093: 
        !          2094:                                        /* reached this point we have
        !          2095:                                           matched a one to many with
        !          2096:                                           at least one match */
        !          2097:                                        break;
        !          2098:                                }
        !          2099:                                
        !          2100:                                /* check that the rest of the
        !          2101:                                 * specification item is optional,
        !          2102:                                 * including the one used */
        !          2103:                                status = axl_true;
        !          2104:                                do {
        !          2105:                                        if (times != ZERO_OR_MANY &&
        !          2106:                                            times != ZERO_OR_ONE) {
        !          2107: 
        !          2108:                                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found item, inside the DTD item list, that is not optional: %d (repeat value: %d)", 
        !          2109:                                                           iterator, times);
        !          2110:                                                status = axl_false;
        !          2111:                                                break;
        !          2112:                                        }
        !          2113: 
        !          2114:                                        /* update index and get the next item */
        !          2115:                                        iterator++;
        !          2116:                                        if (iterator < axl_dtd_item_list_count (itemList))
        !          2117:                                                itemNode = axl_dtd_item_list_get_node (itemList, iterator);
        !          2118:                                }while (status && (iterator < axl_dtd_item_list_count (itemList)));
        !          2119: 
        !          2120:                                /* check status before checking the rest of the item spec */
        !          2121:                                if (status) {
        !          2122:                                        *child_position = child_pos;
        !          2123: 
        !          2124:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sequence validated with child position (II): %d", child_pos);
        !          2125: 
        !          2126:                                        return axl_true;
        !          2127:                                }
        !          2128:                                
        !          2129:                                /* check if a try match is being runned */
        !          2130:                                if (! try_match) {
        !          2131:                                        axl_error_report (error, -1 , 
        !          2132:                                                       "Found that DTD specifies more nodes to be hold by the parent (<%s>), but no more childs were found",
        !          2133:                                                       axl_node_get_name (parent));
        !          2134:                                }
        !          2135: 
        !          2136:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found that no nodes left to satisfy DTD validation operation");
        !          2137:                                *child_position = child_pos;
        !          2138:                                return axl_false;
        !          2139:                        }
        !          2140: 
        !          2141:                        /* check node type */
        !          2142:                        if (axl_dtd_item_node_get_type (itemNode) == AXL_ELEMENT_LIST) {
        !          2143: 
        !          2144:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "the item node is an item list, dtd item list position: %d, child position: %d=<%s>",
        !          2145:                                         iterator, child_pos, axl_node_get_name (node));
        !          2146: 
        !          2147:                                /* element list found, validate its content */
        !          2148:                                if (! __axl_dtd_validate_item_list (axl_dtd_item_node_get_list (itemNode),
        !          2149:                                                                    parent, &child_pos, error, axl_false)) {
        !          2150:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sub item list validation have failed (not critical)");
        !          2151:                                        /* check if we are the top
        !          2152:                                         * level list and the itemNode
        !          2153:                                         * checked is the last one
        !          2154:                                         * item on the item list */
        !          2155:                                        if (top_level && ((iterator + 1) == axl_node_get_child_num (parent))) {
        !          2156:                                                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "found that the last item list wasn't matched");
        !          2157:                                                
        !          2158:                                        }
        !          2159: 
        !          2160:                                        *child_position = child_pos;
        !          2161:                                        return axl_false;
        !          2162:                                }
        !          2163: 
        !          2164:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "validated item list, child position after: %d",
        !          2165:                                           child_pos);
        !          2166:                                /* because child position updating and
        !          2167:                                 * repeat matching is already handled
        !          2168:                                 * by dtd_validate_item_list function
        !          2169:                                 * we just continue with the next
        !          2170:                                 * iteration */
        !          2171:                                break;
        !          2172: 
        !          2173:                        } else if (axl_dtd_item_node_get_type (itemNode) == AXL_ELEMENT_NODE) {
        !          2174:                                /* check the name against the spec */
        !          2175: 
        !          2176:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, 
        !          2177:                                           "the item node is a final content particule definition: %s",
        !          2178:                                           axl_dtd_item_node_get_value (itemNode));
        !          2179: 
        !          2180:                                status = NODE_CMP_NAME (node, axl_dtd_item_node_get_value (itemNode));
        !          2181:                        }
        !          2182: 
        !          2183:                        /* check previous status */
        !          2184:                        if ((times == ONE_AND_ONLY_ONE) || 
        !          2185:                            (times == ONE_OR_MANY && one_matched == axl_false)) {
        !          2186:                                if (! status) {
        !          2187:                                        /* only report an upper level
        !          2188:                                         * error if we are not running
        !          2189:                                         * a try match */
        !          2190:                                        if (! try_match) {
        !          2191: 
        !          2192:                                                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, 
        !          2193:                                                           "Found different node (<%s>) for a sequence expected (<%s>), at child position: %d, item list pos: %d",
        !          2194:                                                           axl_node_get_name (node), 
        !          2195:                                                           axl_dtd_item_node_get_value (itemNode),
        !          2196:                                                           child_pos, iterator);
        !          2197:                                                axl_error_report (error, -1, 
        !          2198:                                                                  "Found different node (<%s>) for a sequence expected (<%s>), at child position: %d, item list pos: %d",
        !          2199:                                                                  axl_node_get_name (node), 
        !          2200:                                                                  axl_dtd_item_node_get_value (itemNode),
        !          2201:                                                                  child_pos, iterator);
        !          2202:                                        }
        !          2203:                                        /* return that a match wasn't possible */
        !          2204:                                        *child_position = child_pos;
        !          2205:                                        return axl_false;                       
        !          2206:                                }
        !          2207:                        }
        !          2208: 
        !          2209:                        /* according to the repetition pattern, update loop indexes */
        !          2210:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "updating child nodes references: %d, repeat type: %d, status=%d",
        !          2211:                                   child_pos, times, status);
        !          2212: 
        !          2213: 
        !          2214:                        /* one only item to match and exactly one */
        !          2215:                        if (times == ONE_AND_ONLY_ONE) {
        !          2216:                                child_pos++;
        !          2217:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "updated child position to: %d, repeat type: %d, status=%d",
        !          2218:                                           child_pos, times, status);
        !          2219:                                break;
        !          2220:                        }
        !          2221: 
        !          2222:                        /* one or many items to match */
        !          2223:                        if (times == ONE_OR_MANY) { 
        !          2224: 
        !          2225:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "matched one to many item node: status=%d one_matched=%d",
        !          2226:                                           status, one_matched);
        !          2227: 
        !          2228:                                /* if the match have failed and
        !          2229:                                 * previous matches was ok, it seems
        !          2230:                                 * we have reached the next
        !          2231:                                 * items. Just break the loop */
        !          2232:                                if (status == axl_false && one_matched == axl_true) 
        !          2233:                                        break;
        !          2234: 
        !          2235:                                child_pos++;
        !          2236:                                one_matched = axl_true;
        !          2237:                                continue; /* don't break the loop */
        !          2238:                        }
        !          2239: 
        !          2240:                        /* zero or optionally one item to match */                      
        !          2241:                        if (times == ZERO_OR_ONE) {
        !          2242:                                /* if previous status was ok, it seems
        !          2243:                                 * that we have matched the optional
        !          2244:                                 * character. In that case, move the
        !          2245:                                 * index to the following value. If
        !          2246:                                 * not, just break the loop. */
        !          2247:                                if (status == axl_true)
        !          2248:                                        child_pos++;
        !          2249:                                break;
        !          2250:                        }
        !          2251: 
        !          2252:                        /* zero or many items to match */
        !          2253:                        if (times == ZERO_OR_MANY) {
        !          2254:                                if (status == axl_true) {
        !          2255:                                        one_matched = axl_true;
        !          2256:                                        child_pos++;
        !          2257:                                        continue;
        !          2258:                                }
        !          2259:                                break;
        !          2260:                        }
        !          2261: 
        !          2262: 
        !          2263:                        /* until break the loop */
        !          2264:                }while (axl_true);
        !          2265: 
        !          2266:                /* update iterator index */
        !          2267:                iterator++;
        !          2268:        }
        !          2269: 
        !          2270:        /* check if more nodes where specified than the DTD spec */
        !          2271:        times = axl_dtd_item_list_repeat (itemList);
        !          2272:        if ((times == ONE_OR_MANY || times == ONE_AND_ONLY_ONE) && 
        !          2273:            top_level && (child_pos  < axl_node_get_child_num (parent))) {
        !          2274: 
        !          2275:                /* drop a log */
        !          2276:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "parent node <%s> have more childs=%d than the childs iterated=%d, top_level=%d",
        !          2277:                           axl_node_get_name (parent),
        !          2278:                           axl_node_get_child_num (parent),
        !          2279:                           child_pos, top_level);
        !          2280: 
        !          2281:                /* do not report an error found if a try match is
        !          2282:                 * being run */
        !          2283:                if (! try_match) {
        !          2284:                        axl_error_new (-1, "More childs, than the ones especified in the DTD, were found",
        !          2285:                                       NULL, error);
        !          2286:                }
        !          2287:                /* return that the match wasn't possible */
        !          2288:                *child_position = child_pos;
        !          2289:                return axl_false;
        !          2290:        }
        !          2291: 
        !          2292:        /* return that the sequence has been validated */
        !          2293:        *child_position = child_pos;
        !          2294: 
        !          2295:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sequence validated with child position (I): %d", child_pos);
        !          2296: 
        !          2297:        return axl_true;
        !          2298: }
        !          2299: 
        !          2300: /** 
        !          2301:  * @internal
        !          2302:  * 
        !          2303:  * Internal support function to validate the choice list.
        !          2304:  */
        !          2305: axl_bool     __axl_dtd_validate_choice (axlNode             * parent, 
        !          2306:                                        int                 * child_position, 
        !          2307:                                        axlDtdElementList   * itemList, 
        !          2308:                                        axlError           ** error,
        !          2309:                                        axl_bool              try_match, 
        !          2310:                                        axl_bool              top_level)
        !          2311: {
        !          2312:        axlNode               * node;
        !          2313:        axlDtdElementListNode * itemNode;
        !          2314:        int                     iterator;
        !          2315:        axl_bool                status;
        !          2316:        AxlDtdTimes             times;
        !          2317:        axl_bool                one_match;
        !          2318: 
        !          2319:        
        !          2320:        if (*child_position < axl_node_get_child_num (parent)) {
        !          2321:                /* get a reference to be matched by the choice list */
        !          2322:                node = axl_node_get_child_nth (parent, *child_position);
        !          2323:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "validated choice list at position: %d=<%s>", *child_position, axl_node_get_name (node));
        !          2324:        } else {
        !          2325:                /* tried to match a choice list with a child index
        !          2326:                 * outside the maximum number of childs */
        !          2327:                if (! try_match) {
        !          2328:                        axl_error_new (-1, "Unable to match choice list, it seems that the are not enough childs to validate the choice list",
        !          2329:                                       NULL, error);
        !          2330:                }
        !          2331:                return axl_false;
        !          2332:        }
        !          2333: 
        !          2334:        iterator = 0; 
        !          2335:        while (iterator < axl_dtd_item_list_count (itemList)) {
        !          2336:                /* get the DTD item list to match */
        !          2337:                itemNode = axl_dtd_item_list_get_node   (itemList, iterator);
        !          2338:                times    = axl_dtd_item_node_get_repeat (itemNode);
        !          2339: 
        !          2340:                if (axl_dtd_item_node_get_type (itemNode) == AXL_ELEMENT_NODE) {
        !          2341:                        /* reset match configuration */
        !          2342:                        one_match = axl_false;
        !          2343:                repeat_for_node:
        !          2344:                        /* a node was found */
        !          2345:                        status    = NODE_CMP_NAME (node, axl_dtd_item_node_get_value (itemNode));
        !          2346: 
        !          2347:                        /* know, if the node was matched check it
        !          2348:                         * repetition configuration */
        !          2349:                        if (status) {
        !          2350:                                /* update child position */
        !          2351:                                (*child_position)++;
        !          2352: 
        !          2353:                                if (times == ONE_AND_ONLY_ONE || times == ZERO_OR_ONE) {
        !          2354:                                        /* the node was matched and
        !          2355:                                         * the itemNode has a one and
        !          2356:                                         * only one configuration,
        !          2357:                                         * just return that the choice
        !          2358:                                         * list was matched */
        !          2359:                                        return axl_true;
        !          2360:                                }
        !          2361:                                if (times == ONE_OR_MANY || times == ZERO_OR_MANY) {
        !          2362:                                        /* because the node was matched, but the repetition
        !          2363:                                         * pattern allows to match more nodes we have to
        !          2364:                                         * iterate a bit more */
        !          2365:                                        node = axl_node_get_child_nth (parent, *child_position);
        !          2366:                                        if (node == NULL) {
        !          2367:                                                /* because we already matched at least one item, 
        !          2368:                                                 * we can assume that the itemNode was successfully 
        !          2369:                                                 * matched for both cases (*) and (+). */
        !          2370:                                                return axl_true;
        !          2371:                                        }
        !          2372:                                        /* flag the one match */
        !          2373:                                        one_match = axl_true;
        !          2374:                                        
        !          2375:                                        /* if the node reference is
        !          2376:                                         * not NULL, try to match the
        !          2377:                                         * next item */
        !          2378:                                        goto repeat_for_node;
        !          2379:                                }
        !          2380:                        } /* end if */
        !          2381:                        
        !          2382:                        /* before returning, that that we have matched
        !          2383:                         * previously, at least, one node for
        !          2384:                         * one-to-many and zero-to-many pattern */
        !          2385:                        if ((times == ONE_OR_MANY || times == ZERO_OR_MANY) && one_match) {
        !          2386:                                return axl_true;
        !          2387:                        }
        !          2388: 
        !          2389:                } else if (axl_dtd_item_node_get_type (itemNode) == AXL_ELEMENT_LIST) {
        !          2390:                        /* an element list was found, call to validate it */
        !          2391:                        /* element list found, validate its content */
        !          2392:                        if (__axl_dtd_validate_item_list (axl_dtd_item_node_get_list (itemNode),
        !          2393:                                                          parent, child_position, error, axl_false)) {
        !          2394:                                /* item list matched */
        !          2395:                                return axl_true;
        !          2396:                        }
        !          2397:                }
        !          2398: 
        !          2399:                /* no item was matched, update iterator indexes */
        !          2400:                iterator++;
        !          2401:        }
        !          2402: 
        !          2403:        /* seems that the choice list wasn't matched */
        !          2404:        if (! try_match) {
        !          2405:                axl_error_new (-1, "Unable to match choice list, after checking all posibilities, choice list wasn't validated", 
        !          2406:                               NULL, error);
        !          2407:        }
        !          2408:        return axl_false;
        !          2409: }
        !          2410: 
        !          2411: /** 
        !          2412:  * @internal 
        !          2413:  *
        !          2414:  * Tries to perform a validation, based on the item list received and
        !          2415:  * the repetition configuration.
        !          2416:  * 
        !          2417:  * @param itemList The item list containing DTD content spec
        !          2418:  * information used to validate.
        !          2419:  *
        !          2420:  * @param parent The parent node where the validation process is being
        !          2421:  * applied. The content spec refers to the childs the parent has.
        !          2422:  *
        !          2423:  * @param stack An stack used by the overall process to store the
        !          2424:  * subsequent parents to be validated. This stack must be released if
        !          2425:  * a error is found.
        !          2426:  *
        !          2427:  * @param error An optional axlError reference containing the error
        !          2428:  * textual diagnostic if found.
        !          2429:  * 
        !          2430:  * @return axl_true if the validation was ok, otherwise axl_false is
        !          2431:  * returned.
        !          2432:  */
        !          2433: axl_bool     __axl_dtd_validate_item_list (axlDtdElementList  * itemList,
        !          2434:                                           axlNode            * parent, 
        !          2435:                                           int                * child_position,
        !          2436:                                           axlError          ** error,
        !          2437:                                           axl_bool             top_level)
        !          2438: {
        !          2439:        int          temp_child_pos;
        !          2440:        int          caller_child_pos;
        !          2441:        axl_bool     status;
        !          2442:        axl_bool     already_matched;
        !          2443: 
        !          2444: 
        !          2445:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "validating an item list with repeat pattern: %d, at %d, top level=%d",
        !          2446:                   axl_dtd_item_list_repeat (itemList), *child_position, top_level);
        !          2447: 
        !          2448:        /* store current caller child position value to check it before */
        !          2449:        caller_child_pos = *child_position;
        !          2450: 
        !          2451:        /* now check repetition type */
        !          2452:        switch (axl_dtd_item_list_repeat (itemList)) {
        !          2453:        case ONE_AND_ONLY_ONE:
        !          2454:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a (one and only one) spec..");
        !          2455:                if (axl_dtd_item_list_type (itemList) == SEQUENCE) {
        !          2456: 
        !          2457:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "using a SEQUENCE form");
        !          2458:                        /* it is a choice, so the item list specifies
        !          2459:                         * the nodes that could appear */
        !          2460:                        if (!__axl_dtd_validate_sequence (parent, child_position, itemList, error, 
        !          2461:                                                          axl_false, top_level)) {
        !          2462:                                return axl_false;
        !          2463:                        }
        !          2464:                }else {
        !          2465:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "using a CHOICE form");
        !          2466:                        /* it is a sequence, so, item list
        !          2467:                         * specification represents the nodes, in the
        !          2468:                         * order they must appear */
        !          2469:                        if (!__axl_dtd_validate_choice (parent, child_position, itemList, error,
        !          2470:                                                        axl_false, top_level)) {
        !          2471:                                return axl_false;
        !          2472:                        }
        !          2473:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "choice list was properly validated");
        !          2474:                }
        !          2475:                break;
        !          2476:        case ZERO_OR_ONE:
        !          2477: 
        !          2478:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a (zero or one) spec..");
        !          2479:                if (axl_dtd_item_list_type (itemList) == SEQUENCE) {
        !          2480: 
        !          2481:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "using a SEQUENCE form, parent: <%s>",
        !          2482:                                   axl_node_get_name (parent));
        !          2483:                        /* because we are running a zero or one item
        !          2484:                         * list matching, we don't care if it doesn't
        !          2485:                         * match. In the case it match, the child
        !          2486:                         * position is updated and next calls will be
        !          2487:                         * properly aligned. In the match doesn't
        !          2488:                         * happens, it also don't matter because the
        !          2489:                         * pattern allow to not match */
        !          2490:                        temp_child_pos = *child_position;
        !          2491:                        if (!__axl_dtd_validate_sequence (parent, child_position, itemList, error, 
        !          2492:                                                          axl_true, top_level)) {
        !          2493:                                /* check that the match wasn't
        !          2494:                                 * produced, at any level */
        !          2495:                                if (temp_child_pos != *child_position) {
        !          2496:                                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "item list mismatch (%d != %d)", 
        !          2497:                                                   temp_child_pos, *child_position);
        !          2498:                                        axl_error_new (-1, "Found an DTD item list definition, that should be matched entirely or not, zero or one time, but it was matched partially",
        !          2499:                                                       NULL, error);
        !          2500:                                        return axl_false;
        !          2501:                                }
        !          2502: 
        !          2503:                                return axl_false;
        !          2504:                        }
        !          2505:                        
        !          2506:                }else {
        !          2507:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "    using a CHOICE form");
        !          2508: 
        !          2509:                        /* it is a sequence, so, item list
        !          2510:                         * specification represents the nodes, in the
        !          2511:                         * order they must appear */
        !          2512:                        __axl_dtd_validate_choice (parent, child_position, itemList, error,
        !          2513:                                                   axl_true, top_level);
        !          2514:                }
        !          2515:                break;
        !          2516:        case ZERO_OR_MANY:
        !          2517: 
        !          2518:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a (zero or many) spec..");
        !          2519:                if (axl_dtd_item_list_type (itemList) == SEQUENCE) {
        !          2520: 
        !          2521:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "    using a SEQUENCE (size: %d) form ",
        !          2522:                                   axl_dtd_item_list_count (itemList));
        !          2523:                        /* one this case, several matches must be
        !          2524:                         * tried, until the validation fails */
        !          2525:                        do {
        !          2526:                                temp_child_pos = *child_position;
        !          2527:                                status         = __axl_dtd_validate_sequence (parent, child_position, itemList, error, 
        !          2528:                                                                              axl_true, top_level);
        !          2529: 
        !          2530:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sequence match status=%d", status);
        !          2531:                                if (! status) {
        !          2532:                                        /* check that the match wasn't
        !          2533:                                         * produced, at any level */
        !          2534:                                        if ((temp_child_pos != *child_position)) {
        !          2535: 
        !          2536:                                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "item list mismatch (%d != %d)", 
        !          2537:                                                           temp_child_pos, *child_position);
        !          2538:                                                axl_error_new (-1, "Found an DTD item list definition, that should be matched entirely or not, zero or many times, but it was matched partially",
        !          2539:                                                               NULL, error);
        !          2540:                                                return axl_false;
        !          2541:                                        }
        !          2542:                                }
        !          2543:                        }while (status);
        !          2544:                }else {
        !          2545: 
        !          2546:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "    using a CHOICE form");
        !          2547:                        /* it is a sequence, so, item list
        !          2548:                         * specification represents the nodes, in the
        !          2549:                         * order they must appear */
        !          2550:                        do {
        !          2551:                                status = __axl_dtd_validate_choice (parent, child_position, itemList, error,
        !          2552:                                                                    axl_true, top_level);
        !          2553:                        }while (status);
        !          2554:                }
        !          2555:                break;
        !          2556:        case ONE_OR_MANY:
        !          2557:                /* one or many sequence spec (+) */
        !          2558:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found a (zero or many) spec..");
        !          2559:                if (axl_dtd_item_list_type (itemList) == SEQUENCE) {
        !          2560: 
        !          2561:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "    using a SEQUENCE (size: %d) form ",
        !          2562:                                   axl_dtd_item_list_count (itemList));
        !          2563: 
        !          2564:                        /* one this case, several matches must be
        !          2565:                         * tried, until the validation fails */
        !          2566:                        already_matched = axl_false;
        !          2567:                        do {
        !          2568:                                temp_child_pos = *child_position;
        !          2569:                                /* try to match the one or many
        !          2570:                                   sequence according to the value
        !          2571:                                   stored inside already matched */
        !          2572:                                status         = __axl_dtd_validate_sequence (parent, child_position, itemList, error, 
        !          2573:                                                                              already_matched, top_level);
        !          2574: 
        !          2575:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "sequence match status=%d", status);
        !          2576:                                if (! status) {
        !          2577:                                        /* check that the match wasn't
        !          2578:                                         * produced, at any level */
        !          2579:                                        if ((temp_child_pos != *child_position)) {
        !          2580: 
        !          2581:                                                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "item list mismatch, matched partially (%d != %d)", 
        !          2582:                                                           temp_child_pos, *child_position);
        !          2583:                                                axl_error_new (-1, 
        !          2584:                                                               "Found an DTD item list definition, that should be matched entirely or not, one or many times, but it was matched partially",
        !          2585:                                                               NULL, error);
        !          2586:                                                return axl_false;
        !          2587:                                        }
        !          2588:                                }else {
        !          2589:                                        /* set that we have matched, at least, one item */
        !          2590:                                        already_matched = axl_true;
        !          2591:                                }
        !          2592: 
        !          2593:                                
        !          2594: 
        !          2595:                        }while (status);
        !          2596:                }else {
        !          2597: 
        !          2598:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "    using a CHOICE form");
        !          2599:                        /* it is a sequence, so, item list
        !          2600:                         * specification represents the nodes, in the
        !          2601:                         * order they must appear */
        !          2602:                        already_matched = axl_false;
        !          2603:                        do {
        !          2604:                                /* the next choice matching is done
        !          2605:                                 * according to the value stored in
        !          2606:                                 * already matched */
        !          2607:                                status = __axl_dtd_validate_choice (parent, child_position, itemList, error,
        !          2608:                                                                    already_matched, top_level);
        !          2609:                                /* if the validation successed, set
        !          2610:                                 * that next matched are not required
        !          2611:                                 * to be successful ones */
        !          2612:                                if (status)
        !          2613:                                        already_matched = axl_true;
        !          2614:                        }while (status);
        !          2615:                }
        !          2616:                break;
        !          2617:        default:
        !          2618:                /* this case will never be reached */
        !          2619: #define INTERNAL_ERROR_01 "critical error reached a place that shows the dtd parser is not properly defining the repetition pattern for the current itemList."
        !          2620:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, INTERNAL_ERROR_01);
        !          2621:                axl_error_new (-1, INTERNAL_ERROR_01, NULL, error);
        !          2622:                return axl_false;
        !          2623:        }
        !          2624: 
        !          2625: 
        !          2626:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "validate item list terminated, now check post-conditions, top_level=%d, item list type=%d, child pos=%d, childs num=%d",
        !          2627:                   top_level, axl_dtd_item_list_type (itemList), *child_position, axl_node_get_child_num (parent));
        !          2628: 
        !          2629:        /* check that, in the case that the choice item list is being
        !          2630:         * validated, ensure it has validated all nodes, especially if
        !          2631:         * we are the top level definition */
        !          2632:        if (top_level && (axl_dtd_item_list_type (itemList) == CHOICE)) {
        !          2633:                if (((*child_position) + 1) < axl_node_get_child_num (parent)) {
        !          2634:                    
        !          2635: 
        !          2636:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "found that the choice list didn't cover all childs (%d), while parent=<%s> has: (%d)",
        !          2637:                                   (*child_position), axl_node_get_name (parent), axl_node_get_child_num (parent));
        !          2638:                        axl_error_new (-1, "Found that the validation process didn't cover all nodes, while using a choice list. This means that the xml document have more content than the DTD spec",
        !          2639:                                       NULL, error);
        !          2640:                        return axl_false;
        !          2641:                }
        !          2642:        }
        !          2643:        
        !          2644:        /* element type children validated */
        !          2645:        return axl_true;       
        !          2646: }
        !          2647: 
        !          2648: /** 
        !          2649:  * @internal
        !          2650:  *
        !          2651:  * Support function validate parent nodes which are element type
        !          2652:  * children ones.
        !          2653:  */
        !          2654: axl_bool     __axl_dtd_validate_element_type_children (axlDtdElement  * element, 
        !          2655:                                                       axlNode        * parent, 
        !          2656:                                                       axl_bool         top_level,
        !          2657:                                                       axlError      ** error)
        !          2658: {
        !          2659:        axlDtdElementList * itemList;
        !          2660:        int                 child_pos = 0;
        !          2661:        char              * err_msg;
        !          2662: 
        !          2663:        /* get a reference to the item list */
        !          2664:        itemList = axl_dtd_get_item_list (element);
        !          2665: 
        !          2666:        /* check for xml nodes with fewer content than the initially
        !          2667:         * expected. */
        !          2668:        if (axl_node_get_child_num (parent) < element->minimum_match) {
        !          2669:                err_msg = axl_strdup_printf ("Found that the parent node (<%s>) received doesn't contains enough xml nodes inside to get a proper validation (childs found (%d) != childs that should be found (%d)). This means that the xml document have fewer content than the DTD spec.",
        !          2670:                                             axl_node_get_name (parent), 
        !          2671:                                             axl_node_get_child_num (parent), 
        !          2672:                                             element->minimum_match);
        !          2673:                axl_error_new (-1, err_msg, NULL, error);
        !          2674:                axl_free (err_msg);
        !          2675:                return axl_false;
        !          2676:        }
        !          2677: 
        !          2678:        /* validate the item list, starting from the child 0 */
        !          2679:        if (__axl_dtd_validate_item_list (itemList, parent, &child_pos, error, top_level)) {
        !          2680:                /* check if, at least, all minimum elements was
        !          2681:                 * matched */
        !          2682:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking minimum node match: (%d < min: %d) (%d < childs: %d) node=<%s>", 
        !          2683:                           child_pos, element->minimum_match,
        !          2684:                           child_pos, axl_node_get_child_num (parent),
        !          2685:                           axl_node_get_name (parent));
        !          2686:                        
        !          2687:                if (child_pos < axl_node_get_child_num (parent)) {
        !          2688:                        axl_error_report (error, -1,
        !          2689:                                          "Found that the validation process didn't cover all nodes (%d < min:%d) (%d < childs:%d). All xml child nodes inside the parent=<%s> wasn't covered. This means that the xml document have more content than the DTD spec defines.",
        !          2690:                                          child_pos, element->minimum_match, child_pos, axl_node_get_child_num (parent), 
        !          2691:                                          axl_node_get_name (parent));
        !          2692:                        return axl_false;
        !          2693:                }
        !          2694:                /* seems that the minimum match */
        !          2695:                return axl_true;
        !          2696:        }
        !          2697: 
        !          2698:        return axl_false;
        !          2699: }
        !          2700: 
        !          2701: /** 
        !          2702:  * @internal
        !          2703:  * Internal support function to validate #PCDATA nodes.
        !          2704:  */
        !          2705: axl_bool     __axl_dtd_validate_element_type_pcdata (axlDtdElement  * element, 
        !          2706:                                                     axlNode        * parent, 
        !          2707:                                                     axlStack       * stack, 
        !          2708:                                                     axlError      ** error)
        !          2709: {
        !          2710:        /* check for childs */
        !          2711:        if (axl_node_have_childs (parent)) {
        !          2712:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "node <%s> should be #PCDATA and it contains childs",
        !          2713:                           axl_node_get_name (parent));
        !          2714:                axl_error_new (-1, 
        !          2715:                               "Found a node for which its espeficiation makes it to be a node with only data and no childs, and it currently contains childs",
        !          2716:                               NULL, error);
        !          2717:                return axl_false;
        !          2718:        }
        !          2719:        
        !          2720:        /* return that the validation was ok */
        !          2721:        return axl_true;
        !          2722: }
        !          2723: 
        !          2724: /** 
        !          2725:  * @internal
        !          2726:  * 
        !          2727:  * Support function to validate empty nodes.
        !          2728:  */
        !          2729: axl_bool     __axl_dtd_validate_element_type_empty (axlDtdElement  * element,
        !          2730:                                                    axlNode        * parent,
        !          2731:                                                    axlStack       * stack,
        !          2732:                                                    axlError      ** error)
        !          2733: {
        !          2734:        char * err_msg;
        !          2735: 
        !          2736:        /* check the node is indeed, empty */
        !          2737:        if (! axl_node_is_empty (parent)) {
        !          2738:                err_msg = axl_strdup_printf (
        !          2739:                        "Found a node <%s> that it is especified that must be empty, but it isn't",
        !          2740:                        axl_node_get_name (parent));
        !          2741:                axl_error_new (-1, err_msg, NULL, error);
        !          2742:                axl_free (err_msg);
        !          2743:                return axl_false;
        !          2744:        }
        !          2745: 
        !          2746:        /* check the node doesn't have childs */
        !          2747:        if (axl_node_have_childs (parent)) {
        !          2748:                err_msg = axl_strdup_printf (
        !          2749:                        "Found a node <%s> that it is especified that must be empty, but it has childs",
        !          2750:                        axl_node_get_name (parent));
        !          2751:                axl_error_new (-1, err_msg, NULL, error);
        !          2752:                axl_free (err_msg);
        !          2753:                return axl_false;
        !          2754:        }
        !          2755:        
        !          2756:        /* return that the validation was ok */
        !          2757:        return axl_true;
        !          2758: }
        !          2759: 
        !          2760: axl_bool __axl_dtd_attr_validate_foreach (const char * key, const char * value, axlPointer data, axlPointer data2)
        !          2761: {
        !          2762:        axlDtdAttribute     * attribute = data;
        !          2763:        axlError           ** error     = data2;
        !          2764:        axlDtdAttributeDecl * decl;
        !          2765:        char                * err_msg;
        !          2766: 
        !          2767:        /* get declaration associated */
        !          2768:        decl = axl_list_lookup (attribute->list, __find_attr_decl, (axlPointer) key);
        !          2769:        
        !          2770:        if (decl == NULL) {
        !          2771:                /* found an error */
        !          2772:                err_msg = axl_strdup_printf ("Found an attribute (%s) which is not specified by the attribute declaration for <%s>",
        !          2773:                                             key, attribute->name);
        !          2774:                axl_error_new (-1, err_msg, NULL, error);
        !          2775:                
        !          2776:                /* free the cursor and the error message */
        !          2777:                axl_free (err_msg);
        !          2778: 
        !          2779:                /* return axl_true here because we want to stop the process */
        !          2780:                return axl_true;
        !          2781:                
        !          2782:        } /* end if */
        !          2783: 
        !          2784:        /* if the declaration is found, now check its
        !          2785:         * contraints */
        !          2786:        axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking contraint for attribute: %s=%s", decl->name, value);
        !          2787:        if (decl->type == CDATA_ATTRIBUTE) {
        !          2788:                /* found free attribute declaration, go ahed */
        !          2789:        } else if (decl->type == ENUMERATION_TYPE) {
        !          2790:                /* found an enumeration type, check and return */
        !          2791:                if (axl_list_lookup (decl->enumvalues, axl_list_find_string, (char *) value) == NULL) {
        !          2792:                        /* found an error */
        !          2793:                        err_msg = axl_strdup_printf ("Found an attribute (%s) with a value not allowed by the enum declaration (%s) for the node <%s>",
        !          2794:                                                     key, value, attribute->name);
        !          2795:                        axl_error_new (-1, err_msg, NULL, error);
        !          2796:                        
        !          2797:                        /* free the cursor and the error message */
        !          2798:                        axl_free (err_msg);
        !          2799:                        return axl_true;
        !          2800:                }
        !          2801:        } else {
        !          2802:                /* not supported yet */
        !          2803:        }
        !          2804: 
        !          2805:        /* return axl_false to continue with the process */
        !          2806:        return axl_false;
        !          2807: }
        !          2808: 
        !          2809: axl_bool __axl_dtd_attr_validate_required (axlPointer element, axlPointer data)
        !          2810: {
        !          2811:        axlNode             * node = data;
        !          2812:        axlDtdAttributeDecl * decl = element;
        !          2813: 
        !          2814:        switch (decl->defaults) {
        !          2815:        case ATT_REQUIRED:
        !          2816:                /* attribute required */
        !          2817:                return !HAS_ATTR (node, decl->name);
        !          2818:        case ATT_FIXED:
        !          2819:                return !HAS_ATTR_VALUE (node, decl->name, decl->default_value);
        !          2820:        default:
        !          2821:                break;
        !          2822:        } /* end switch */
        !          2823: 
        !          2824:        /* return axl_false for this because it is not obligatory
        !          2825:         * to have the attribute defined. */
        !          2826:        return axl_false;
        !          2827: }
        !          2828: 
        !          2829: /** 
        !          2830:  * @internal Functions which validates the attribute declaration for
        !          2831:  * the node provided, using attribute declarations found.
        !          2832:  * 
        !          2833:  * @param node The node to check for its attributes.
        !          2834:  *
        !          2835:  * @param dtd The dtd used to validate the node provided.
        !          2836:  *
        !          2837:  * @param error A reference to the axlError where the textual
        !          2838:  * diagnostic error will be reported.
        !          2839:  * 
        !          2840:  * @return axl_true if the node is validated, axl_false if not.
        !          2841:  */
        !          2842: axl_bool axl_dtd_attr_validate (axlNode * node, axlDtd * dtd, axlError ** error, axlHash * id_validation, axlList * idref_validation)
        !          2843: {
        !          2844:        axlDtdAttribute     * attribute;
        !          2845:        axlDtdAttributeDecl * decl;
        !          2846:        char                * err_msg;
        !          2847:        int                   iterator;
        !          2848:        axlError            * _error = NULL;
        !          2849: 
        !          2850:        /* find attribute contraints for the node */
        !          2851:        attribute = axl_dtd_get_attr (dtd, axl_node_get_name (node));
        !          2852:        if (attribute == NULL)
        !          2853:                return axl_true;
        !          2854: 
        !          2855:        /* we have an especification, run it */
        !          2856: 
        !          2857:        /* for each attribute found, check against the spec */
        !          2858:        axl_node_attr_foreach (node, __axl_dtd_attr_validate_foreach, attribute, &_error);
        !          2859: 
        !          2860:        /* check the error */
        !          2861:        if (! axl_error_was_ok (_error)) {
        !          2862:                /* reconfigure error returned */
        !          2863:                if (error != NULL)
        !          2864:                        *error = _error;
        !          2865:                return axl_false;
        !          2866:        } /* end if */
        !          2867:                
        !          2868:        
        !          2869:        /* now, for each contraint, check that all required nodes
        !          2870:         * exists */
        !          2871:        decl = axl_list_lookup (attribute->list, __axl_dtd_attr_validate_required, node);
        !          2872:        if (decl != NULL) {
        !          2873:                if (decl->defaults == ATT_FIXED)
        !          2874:                        err_msg = axl_strdup_printf ("attribute required '%s' (or its value), due to #FIXED declaration, not found for node <%s>", 
        !          2875:                                                     decl->name, attribute->name);
        !          2876:                else 
        !          2877:                        err_msg = axl_strdup_printf ("attribute required '%s', due to #REQUIRED declaration, not found for node <%s>", 
        !          2878:                                                     decl->name, attribute->name);
        !          2879:                axl_error_new (-1, err_msg, NULL, error);
        !          2880:                axl_free (err_msg);
        !          2881:                return axl_false;
        !          2882:        } /* end if */
        !          2883: 
        !          2884:        /* check declarations */
        !          2885:        if (dtd->haveIdDecl) {
        !          2886: 
        !          2887:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found DTD has ID unique attribute declaration..");
        !          2888:                
        !          2889:                /* check if the node have TOKENIZED_TYPE_ID */
        !          2890:                decl = axl_list_lookup (attribute->list, __find_id_decl, NULL);
        !          2891:                
        !          2892:                /* if we have a tokenized */
        !          2893:                if (decl != NULL) {
        !          2894: 
        !          2895:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "found ID unique attribute declaration %s=\"%s\"..",
        !          2896:                                   decl->name, ATTR_VALUE (node, decl->name));
        !          2897: 
        !          2898:                        /* check if the attribute value for the decl that is
        !          2899:                         * flagged as ID is already found at the
        !          2900:                         * id_validation */
        !          2901:                        if (axl_hash_exists (id_validation, (axlPointer) ATTR_VALUE (node, decl->name))) {
        !          2902:                                err_msg = axl_strdup_printf ("DTD declared the attribute '%s' as unique (ID) for the node %s, but was found used several times",
        !          2903:                                                             decl->name, attribute->name);
        !          2904:                                axl_error_new (-1, err_msg, NULL, error);
        !          2905:                                axl_free (err_msg);
        !          2906:                                return axl_false;
        !          2907:                        } /* end if */
        !          2908:                        
        !          2909:                        /* seems the attribute was not used, nice!, store it */
        !          2910:                        axl_hash_insert (id_validation, (axlPointer) ATTR_VALUE (node, decl->name), (axlPointer) ATTR_VALUE (node, decl->name));
        !          2911:                } /* end if */
        !          2912:        } /* end if */
        !          2913: 
        !          2914:        if (dtd->haveIdRefDecl) {
        !          2915:                /* find the id ref declaration */
        !          2916:                
        !          2917:                iterator = 0;
        !          2918:                while (iterator < axl_list_length (attribute->list)) {
        !          2919:                        
        !          2920:                        /* get the attribute declaration at the
        !          2921:                         * particular position */
        !          2922:                        decl = axl_list_get_nth (attribute->list, iterator);
        !          2923:                        if (decl->type == TOKENIZED_TYPE_IDREF) {
        !          2924:                                /* found a reference, but do not check
        !          2925:                                 * it at this place becase the
        !          2926:                                 * reference could be placed at any
        !          2927:                                 * part in the document event after
        !          2928:                                 * the reference pointed is
        !          2929:                                 * defined. store and check later */
        !          2930:                                if (ATTR_VALUE (node, decl->name)) {
        !          2931:                                        /* store the id ref reference
        !          2932:                                         * if defined */
        !          2933:                                        axl_list_add (idref_validation, (axlPointer) ATTR_VALUE (node, decl->name));
        !          2934:                                }
        !          2935:                        } /* end if */
        !          2936: 
        !          2937:                        /* get the next */
        !          2938:                        iterator++;
        !          2939:                        
        !          2940:                } /* end if */
        !          2941:                
        !          2942:        } /* end if */
        !          2943: 
        !          2944:        axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "attributes validated for node=<%s>", attribute->name);
        !          2945:        
        !          2946:        return axl_true;
        !          2947: }
        !          2948: 
        !          2949: /** 
        !          2950:  * @internal Function used by axl_dtd_validate_references to ensure
        !          2951:  * that all references found point to a valid reference defined.
        !          2952:  */
        !          2953: axl_bool __axl_dtd_reference_check (axlPointer _element, axlPointer data)
        !          2954: {
        !          2955: #if defined(SHOW_DEBUG_LOG)
        !          2956:        const char * value = _element;
        !          2957: 
        !          2958:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "checking id ref: %s", value);
        !          2959: #endif
        !          2960: 
        !          2961:        return ! axl_hash_exists ((axlHash *) data, _element);
        !          2962: }
        !          2963: 
        !          2964: /** 
        !          2965:  * @internal Function that validates all references found (from IDREF
        !          2966:  * attribute) to unique references (defined by ID attributes).
        !          2967:  *
        !          2968:  */
        !          2969: axl_bool axl_dtd_validate_references (axlHash * id_validation, axlList * idref_validation, axlError ** error)
        !          2970: {
        !          2971:        char * reference;
        !          2972:        char * err_msg;
        !          2973:        
        !          2974:        /* if no empty at the valiadtion reference list, means not
        !          2975:         * reference was done, so there is no room for errors */
        !          2976:        if (idref_validation == NULL) 
        !          2977:                return axl_true;
        !          2978:        
        !          2979:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "id_validation reference: 0x%x", id_validation);
        !          2980: 
        !          2981:        /* find first reference not found */
        !          2982:        reference = axl_list_lookup (idref_validation, __axl_dtd_reference_check, id_validation);
        !          2983:        
        !          2984:        if (reference != NULL) {
        !          2985:                /* found a reference not defined, report it to the
        !          2986:                 * application level */
        !          2987:                err_msg = axl_strdup_printf ("Found a reference defined ('%s') which is not found in any ID attribute in the document",
        !          2988:                                             reference);
        !          2989:                axl_error_new (-1, err_msg, NULL, error);
        !          2990:                axl_free (err_msg);
        !          2991: 
        !          2992:                return axl_false;
        !          2993:        } /* end if */
        !          2994:        
        !          2995:        /* validation ok */
        !          2996:        return axl_true;
        !          2997: }
        !          2998: 
        !          2999: /** 
        !          3000:  * @brief Allows to validate the given XML document (\ref axlDoc)
        !          3001:  * against the given document type definition (DTD, \ref axlDtd).
        !          3002:  *
        !          3003:  * This function allows to validate your XML documents providing the
        !          3004:  * document type definition, that was read using \ref axl_dtd_parse or
        !          3005:  * \ref axl_dtd_parse_from_file.
        !          3006:  *
        !          3007:  * Keep in mind that a document could be well-formed and valid. The
        !          3008:  * only difference is that valid XML document are those that, meet all
        !          3009:  * XML rules, but also are clasified and recognized as XML documents
        !          3010:  * with some particular structure, that is represented (or
        !          3011:  * constrained) with providing a DTD definition.
        !          3012:  *
        !          3013:  * @param doc The \ref axlDoc containing the XML document to be
        !          3014:  * validated.
        !          3015:  *
        !          3016:  * @param dtd The \ref axlDtd containing the DTD definition used to
        !          3017:  * validate the document.
        !          3018:  *
        !          3019:  * @param error An optional reference to a \ref axlError object where
        !          3020:  * validation errors are reported.
        !          3021:  *
        !          3022:  * @return axl_true if the document is valid, axl_false if not.
        !          3023:  */
        !          3024: axl_bool           axl_dtd_validate        (axlDoc * doc, axlDtd * dtd,
        !          3025:                                            axlError ** error)
        !          3026: {
        !          3027:        axlNode            * parent;
        !          3028:        axlStack           * stack;
        !          3029:        axlHash            * id_validation = NULL;
        !          3030:        axlList            * idref_validation = NULL;
        !          3031:        
        !          3032:        axlDtdElement      * element;
        !          3033:        axl_bool             top_level;
        !          3034:        char               * err_msg;
        !          3035:        axl_bool             result;
        !          3036:        
        !          3037:        /* perform some checkings */
        !          3038:        axl_return_val_if_fail (doc, axl_false);
        !          3039:        axl_return_val_if_fail (dtd, axl_false);
        !          3040: 
        !          3041:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "starting DTD validation");
        !          3042: 
        !          3043:        /* validate the very first root node */
        !          3044:        parent  = axl_doc_get_root (doc);
        !          3045:        element = axl_dtd_get_root (dtd);
        !          3046:        if ((element != NULL) && ! NODE_CMP_NAME (parent, axl_dtd_get_element_name (element))) {
        !          3047: 
        !          3048:                /* because a DTD document could have several top level
        !          3049:                 * elements, ensure this is not the case */
        !          3050:                element = axl_dtd_get_element (dtd, axl_node_get_name (parent));
        !          3051:                if (element == NULL) { /*  || ! axl_dtd_element_is_toplevel (dtd, element)) { */
        !          3052:                        /* root node doesn't match */
        !          3053:                        err_msg = axl_strdup_printf ("Found that root node doesn't match (%s != %s!",
        !          3054:                                                     axl_node_get_name (parent), 
        !          3055:                                                     axl_dtd_get_element_name (element));
        !          3056:                        axl_error_new (-1, err_msg, NULL, error);
        !          3057:                        axl_free (err_msg);
        !          3058:                        return axl_false;
        !          3059: 
        !          3060:                } /* end if */
        !          3061:        } /* end if */
        !          3062: 
        !          3063:        /* check if the node has DTD element declaration */
        !          3064:        if (element == NULL) {
        !          3065:                err_msg = axl_strdup_printf ("There is not DTD element declaration to validate the node <%s>", 
        !          3066:                                             axl_node_get_name (parent));
        !          3067:                axl_error_new (-1, err_msg, NULL, error);
        !          3068:                axl_free (err_msg);
        !          3069:                return axl_false;
        !          3070:        } /* end if */
        !          3071: 
        !          3072:        /* check if the dtd contains a Id declaration */
        !          3073:        if (dtd->haveIdDecl) {
        !          3074:                /* seems the user have declarted ID attributes init the hash */
        !          3075:                id_validation = axl_hash_new (axl_hash_string, axl_hash_equal_string);
        !          3076:        } /* end if */
        !          3077: 
        !          3078:        /* check if the dtd contains Id ref declarations */
        !          3079:        if (dtd->haveIdRefDecl) {
        !          3080:                /* create a list that could contain all references done */
        !          3081:                idref_validation = axl_list_new (axl_list_always_return_1, NULL);
        !          3082:        } /* end if */
        !          3083: 
        !          3084:        /* check empty content spec */
        !          3085:        if (axl_dtd_get_element_type (element) == ELEMENT_TYPE_EMPTY) {
        !          3086:                /* check if the document provided have only one node */
        !          3087:                result = axl_node_is_empty (parent) && !axl_node_have_childs (parent) && axl_dtd_attr_validate (parent, dtd, error, id_validation, idref_validation);
        !          3088: 
        !          3089:                /* check references */
        !          3090:                if (result)
        !          3091:                        result = axl_dtd_validate_references (id_validation, idref_validation, error);
        !          3092:                
        !          3093:                /* free and return */
        !          3094:                axl_hash_free (id_validation);
        !          3095: 
        !          3096:                /* free the list */
        !          3097:                axl_list_free (idref_validation);
        !          3098:                return result;
        !          3099:        } /* end if */
        !          3100: 
        !          3101:        /* queue initial nodes to validate */
        !          3102:        stack     = axl_stack_new (NULL);
        !          3103:        
        !          3104: 
        !          3105:        /* set that the only top level node is the first one */
        !          3106:        top_level = axl_true;
        !          3107: 
        !          3108:        do {
        !          3109:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "doing a DTD iteration: <%s>...",
        !          3110:                           axl_node_get_name (parent));
        !          3111: 
        !          3112:                /* validate attributes */
        !          3113:                if (! axl_dtd_attr_validate (parent, dtd, error, id_validation, idref_validation)) {
        !          3114:                        /* free the stack */
        !          3115:                        axl_stack_free (stack);
        !          3116: 
        !          3117:                        /* free id_validation */
        !          3118:                        axl_hash_free (id_validation);
        !          3119: 
        !          3120:                        /* free the list */
        !          3121:                        axl_list_free (idref_validation);
        !          3122:                        return axl_false;
        !          3123:                }
        !          3124: 
        !          3125:                /* reach this position, the <parent> reference contains
        !          3126:                 * a reference to the parent node, which will be used
        !          3127:                 * to validate current child content against current
        !          3128:                 * configuration for dtd element constraining it.
        !          3129:                 * 
        !          3130:                 * equally, the <element> reference contains a dtd
        !          3131:                 * reference to the already checked DTD element which
        !          3132:                 * configure this parent node. */
        !          3133:                switch (axl_dtd_get_element_type (element)) {
        !          3134:                case ELEMENT_TYPE_PCDATA:
        !          3135:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  find  PCDATA dtd element=%s: parent=<%s>, ",
        !          3136:                                   axl_dtd_get_element_name (element), 
        !          3137:                                   axl_node_get_name (parent));
        !          3138: 
        !          3139:                        /* ok, a leaf node was found, know it is
        !          3140:                         * required to check that the node doesn't
        !          3141:                         * have more childs and only have content,
        !          3142:                         * that is, it is not empty  */
        !          3143:                        if (!__axl_dtd_validate_element_type_pcdata (element, parent, stack, error)) {
        !          3144:                                /* free id_validation */
        !          3145:                                axl_hash_free (id_validation);
        !          3146: 
        !          3147:                                /* free the stack */
        !          3148:                                axl_stack_free (stack);
        !          3149:                                
        !          3150:                                /* free the list */
        !          3151:                                axl_list_free (idref_validation);
        !          3152:                                return axl_false;
        !          3153:                        }
        !          3154:                        break;
        !          3155:                case ELEMENT_TYPE_CHILDREN:
        !          3156: 
        !          3157:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  find  CHILDREN dtd element");
        !          3158:                        /* ok, a parent node that have childs */
        !          3159:                        if (!__axl_dtd_validate_element_type_children (element, parent, top_level, error)) {
        !          3160:                                /* free id_validation */
        !          3161:                                axl_hash_free (id_validation);
        !          3162: 
        !          3163:                                /* free the stack */
        !          3164:                                axl_stack_free (stack);
        !          3165: 
        !          3166:                                /* free the list */
        !          3167:                                axl_list_free (idref_validation);
        !          3168:                                
        !          3169:                                return axl_false;
        !          3170:                        }
        !          3171:                        break;
        !          3172:                case ELEMENT_TYPE_EMPTY:
        !          3173:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  find  EMPTY dtd element");
        !          3174:                        /* the element especification is empty, the
        !          3175:                         * node being validated must also be the
        !          3176:                         * same */
        !          3177:                        if (!__axl_dtd_validate_element_type_empty (element, parent, stack, error)) {
        !          3178:                                /* free id_validation */
        !          3179:                                axl_hash_free (id_validation);
        !          3180: 
        !          3181:                                /* free the stack */
        !          3182:                                axl_stack_free (stack);
        !          3183: 
        !          3184:                                /* free the list */
        !          3185:                                axl_list_free (idref_validation);
        !          3186: 
        !          3187:                                return axl_false;
        !          3188:                        }
        !          3189:                        break;
        !          3190:                case ELEMENT_TYPE_ANY:
        !          3191:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  find  ANY dtd element");
        !          3192:                        /* the anything is allowed cased from this
        !          3193:                         * parent node. */
        !          3194:                        goto continue_with_validation;
        !          3195:                case ELEMENT_TYPE_MIXED:
        !          3196:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "  find  MIXED dtd element");
        !          3197: 
        !          3198:                        /* the mixed case, where nodes and PC data
        !          3199:                         * could be mixed */
        !          3200:                        break;
        !          3201:                default:
        !          3202:                        /* do not do any thing on this case */
        !          3203:                        break;
        !          3204:                }
        !          3205:                        
        !          3206:                /* queue more childs, as future parents to be
        !          3207:                 * validated on the provided queue, only in the case
        !          3208:                 * the parent node have childs */
        !          3209:                if (axl_node_have_childs (parent)) {
        !          3210: 
        !          3211:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "parent node <%s> have childs, adding its childs (stack size: %d)",
        !          3212:                                   axl_node_get_name (parent),
        !          3213:                                   axl_stack_size (stack));
        !          3214: 
        !          3215:                        /* queue childs to be processed */
        !          3216:                        __axl_dtd_queue_childs (stack, parent);
        !          3217: 
        !          3218:                        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "parent node <%s> childs: %d, (stack size: %d)",
        !          3219:                                   axl_node_get_name (parent), axl_node_get_child_num (parent),
        !          3220:                                   axl_stack_size (stack));
        !          3221:                }
        !          3222:                
        !          3223:                /* set the parent reference to NULL */
        !          3224:                parent = NULL;
        !          3225:                        
        !          3226:                /* update the reference to the new parent node, only
        !          3227:                 * if there are new parents on the stack */
        !          3228:        continue_with_validation:
        !          3229:                if (! axl_stack_is_empty (stack)) {
        !          3230: 
        !          3231: 
        !          3232:                        /* get a new reference */
        !          3233:                        parent  = axl_stack_pop (stack);
        !          3234:                        
        !          3235:                        /* get a reference to the DTD element to used */
        !          3236:                        element = axl_dtd_get_element (dtd, axl_node_get_name (parent));
        !          3237:                        if (element == NULL) {
        !          3238:                                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "found that the node <%s> doesn't have DTD especification", 
        !          3239:                                           axl_node_get_name (parent));
        !          3240:                                /* prepare the error message */
        !          3241:                                err_msg = axl_strdup_printf ("Found a node <%s> that doesn't have a DTD element espefication to validate it, DTD validation failed",
        !          3242:                                                             axl_node_get_name (parent));
        !          3243:                                axl_error_new (-1, err_msg, NULL, error);
        !          3244:                                axl_free (err_msg);
        !          3245: 
        !          3246:                                /* free id_validation */
        !          3247:                                axl_hash_free (id_validation);
        !          3248: 
        !          3249:                                /* free the list */
        !          3250:                                axl_list_free (idref_validation);
        !          3251: 
        !          3252:                                /* free the stack */
        !          3253:                                axl_stack_free (stack);
        !          3254:                                return axl_false;
        !          3255:                        } /* end if */
        !          3256:                } /* end if */
        !          3257: 
        !          3258:                /* set the top level status */
        !          3259:                top_level = axl_false;
        !          3260:                
        !          3261:                /* until the stack is empty */
        !          3262:        }while (parent != NULL);
        !          3263: 
        !          3264:        /* check references */
        !          3265:        result = axl_dtd_validate_references (id_validation, idref_validation, error);
        !          3266: 
        !          3267:        /* deallocate stack used */
        !          3268:        axl_stack_free (stack);
        !          3269: 
        !          3270:        /* free id_validation */
        !          3271:        axl_hash_free (id_validation);
        !          3272: 
        !          3273:        /* free the list */
        !          3274:        axl_list_free (idref_validation);
        !          3275: 
        !          3276:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "DTD validation, %s", result ? "ok" : "failed");
        !          3277: 
        !          3278:        /* the document is valid */
        !          3279:        return result;
        !          3280: }
        !          3281: 
        !          3282: /** 
        !          3283:  * @brief Allows to check if the provided two references represents
        !          3284:  * DTD documents with the same rules. 
        !          3285:  * 
        !          3286:  * @param dtd First reference to compare.
        !          3287:  * @param dtd2 Second reference to compare.
        !          3288:  *
        !          3289:  * @return axl_true if both references represent the same document. If
        !          3290:  * some of the references received are NULL the function returns
        !          3291:  * axl_false.
        !          3292:  *
        !          3293:  * NOTE: The function does not have the ability to perform a smart
        !          3294:  * equal operation like detecting DTD that are semantically
        !          3295:  * equivalent. It only checks internal structure. 
        !          3296:  */
        !          3297: axl_bool                 axl_dtd_are_equal        (axlDtd * dtd,
        !          3298:                                                   axlDtd * dtd2)
        !          3299: {
        !          3300:        int iterator;
        !          3301:        int iterator2;
        !          3302:        int iterator3;
        !          3303:        axlDtdEntity          * entity,      * entity2;
        !          3304:        axlDtdElement         * element,     * element2;
        !          3305:        axlDtdElementListNode * node,        * node2;
        !          3306:        axlDtdAttribute       * attribute,   * attribute2;
        !          3307:        axlDtdAttributeDecl   * attr_decl,   * attr_decl2;
        !          3308: 
        !          3309:        /* check references received */
        !          3310:        if (dtd == NULL)
        !          3311:                return axl_false;
        !          3312:        if (dtd2 == NULL)
        !          3313:                return axl_false;
        !          3314: 
        !          3315:        /* check each rule inside both documents */
        !          3316:        if (axl_list_length (dtd->entities) != axl_list_length (dtd2->entities))
        !          3317:                return axl_false;
        !          3318:        if (axl_list_length (dtd->elements) != axl_list_length (dtd2->elements))
        !          3319:                return axl_false;
        !          3320:        if (axl_list_length (dtd->attributes) != axl_list_length (dtd2->attributes))
        !          3321:                return axl_false;
        !          3322:        if (dtd->haveIdRefDecl != dtd2->haveIdRefDecl)
        !          3323:                return axl_false;
        !          3324:        if (dtd->haveIdDecl != dtd2->haveIdDecl)
        !          3325:                return axl_false;
        !          3326: 
        !          3327:        /* now check inner elements (ENTITIES) */
        !          3328:        iterator = 0;
        !          3329:        while (iterator < axl_list_length (dtd->entities)) {
        !          3330:                /* get referneces */
        !          3331:                entity  = axl_list_get_nth (dtd->entities, iterator);
        !          3332:                entity2 = axl_list_get_nth (dtd2->entities, iterator);
        !          3333: 
        !          3334:                /* check types */
        !          3335:                if (entity->type != entity2->type)
        !          3336:                        return axl_false;
        !          3337: 
        !          3338:                /* check names */
        !          3339:                if (! axl_cmp (entity->name, entity2->name)) 
        !          3340:                        return axl_false;
        !          3341: 
        !          3342:                /* check content */
        !          3343:                if (! axl_cmp (entity->content, entity2->content))
        !          3344:                        return axl_false;
        !          3345: 
        !          3346:                /* check external data */
        !          3347:                if (entity->data == NULL && entity2->data != NULL)
        !          3348:                        return axl_false;
        !          3349:                if (entity->data != NULL && entity2->data == NULL)
        !          3350:                        return axl_false;
        !          3351:                if (entity->data != NULL && entity2->data != NULL) {
        !          3352:                        if (! axl_cmp (entity->data->system_literal, entity2->data->system_literal))
        !          3353:                                return axl_false;
        !          3354:                        if (! axl_cmp (entity->data->public_literal, entity2->data->public_literal))
        !          3355:                                return axl_false;
        !          3356:                        if (! axl_cmp (entity->data->ndata, entity2->data->ndata))
        !          3357:                                return axl_false;
        !          3358:                } /* end if */
        !          3359: 
        !          3360:                /* next iterator */
        !          3361:                iterator++;
        !          3362:        } /* end while */
        !          3363: 
        !          3364:        /* now check inner elements (ELEMENTS) */
        !          3365:        iterator = 0;
        !          3366:        while (iterator < axl_list_length (dtd->elements)) {
        !          3367:                /* get referneces */
        !          3368:                element  = axl_list_get_nth (dtd->elements, iterator);
        !          3369:                element2 = axl_list_get_nth (dtd2->elements, iterator);
        !          3370: 
        !          3371:                /* check types */
        !          3372:                if (element->type != element2->type)
        !          3373:                        return axl_false;
        !          3374: 
        !          3375:                /* minimum match */
        !          3376:                if (element->minimum_match != element2->minimum_match)
        !          3377:                        return axl_false;
        !          3378: 
        !          3379:                /* check names */
        !          3380:                if (! axl_cmp (element->name, element2->name)) 
        !          3381:                        return axl_false;
        !          3382: 
        !          3383:                /* check element list */
        !          3384:                if (element->list == NULL && element2->list != NULL)
        !          3385:                        return axl_false;
        !          3386:                if (element->list != NULL && element2->list == NULL)
        !          3387:                        return axl_false;
        !          3388:                if (element->list != NULL && element2->list != NULL) {
        !          3389: 
        !          3390:                        /* check internal values */
        !          3391:                        if (element->list->type != element2->list->type)
        !          3392:                                return axl_false;
        !          3393:                        if (element->list->times != element2->list->times)
        !          3394:                                return axl_false;
        !          3395: 
        !          3396:                        iterator2 = 0;
        !          3397:                        while (iterator2 < axl_list_length (element->list->itemList)) {
        !          3398:                                
        !          3399:                                /* get references */
        !          3400:                                node  = axl_list_get_nth (element->list->itemList, iterator2);
        !          3401:                                node2 = axl_list_get_nth (element2->list->itemList, iterator2);
        !          3402: 
        !          3403:                                if (node->type != node->type)
        !          3404:                                        return axl_false;
        !          3405:                                if (node->times != node2->times)
        !          3406:                                        return axl_false;
        !          3407:                                
        !          3408:                                /* next value */
        !          3409:                                iterator2++;
        !          3410: 
        !          3411:                        } /* end while */
        !          3412:                        
        !          3413:                } /* end if */
        !          3414: 
        !          3415:                /* next iterator */
        !          3416:                iterator++;
        !          3417:        } /* end while */
        !          3418: 
        !          3419:        /* now check inner elements (ATTRIBUTES) */
        !          3420:        iterator = 0;
        !          3421:        while (iterator < axl_list_length (dtd->attributes)) {
        !          3422:                /* get referneces */
        !          3423:                attribute  = axl_list_get_nth (dtd->attributes, iterator);
        !          3424:                attribute2 = axl_list_get_nth (dtd2->attributes, iterator);
        !          3425: 
        !          3426:                /* check names */
        !          3427:                if (! axl_cmp (attribute->name, attribute2->name)) 
        !          3428:                        return axl_false;
        !          3429: 
        !          3430:                /* check values */
        !          3431:                if (attribute->list == NULL && attribute2->list != NULL)
        !          3432:                        return axl_false;
        !          3433:                if (attribute->list != NULL && attribute2->list == NULL)
        !          3434:                        return axl_false;
        !          3435:                if (attribute->list != NULL && attribute2->list != NULL) {
        !          3436: 
        !          3437:                        /* check list length */
        !          3438:                        if (axl_list_length (attribute->list) != axl_list_length (attribute2->list))
        !          3439:                                return axl_false;
        !          3440: 
        !          3441:                        /* check internal values */
        !          3442:                        iterator2 = 0;
        !          3443:                        while (iterator2 < axl_list_length (attribute->list)) {
        !          3444:                                
        !          3445:                                /* get references */
        !          3446:                                attr_decl   = axl_list_get_nth (attribute->list,  iterator2);
        !          3447:                                attr_decl2  = axl_list_get_nth (attribute2->list, iterator2);
        !          3448: 
        !          3449:                                if (attr_decl->type != attr_decl2->type)
        !          3450:                                        return axl_false;
        !          3451:                                if (attr_decl->defaults != attr_decl2->defaults)
        !          3452:                                        return axl_false;
        !          3453:                                if (! axl_cmp (attr_decl->name, attr_decl2->name))
        !          3454:                                        return axl_false;
        !          3455:                                
        !          3456:                                if (attr_decl->enumvalues == NULL && attr_decl2->enumvalues != NULL)
        !          3457:                                        return axl_false;
        !          3458:                                if (attr_decl->enumvalues != NULL && attr_decl2->enumvalues == NULL)
        !          3459:                                        return axl_false;
        !          3460:                                if (attr_decl->enumvalues != NULL && attr_decl2->enumvalues != NULL) {
        !          3461:                                        if (axl_list_length (attr_decl->enumvalues) != axl_list_length (attr_decl2->enumvalues))
        !          3462:                                                return axl_false;
        !          3463:                                        iterator3 = 0;
        !          3464:                                        while (iterator3 < axl_list_length (attr_decl->enumvalues)) {
        !          3465:                                                /* check values */
        !          3466:                                                if (! axl_cmp (axl_list_get_nth (attr_decl->enumvalues, iterator3),
        !          3467:                                                               axl_list_get_nth (attr_decl2->enumvalues, iterator3)))
        !          3468:                                                        return axl_false;
        !          3469: 
        !          3470:                                                /* next value */
        !          3471:                                                iterator3++;
        !          3472:                                        } /* end while */
        !          3473:                                } /* end if */
        !          3474:                                
        !          3475:                                /* next value */
        !          3476:                                iterator2++;
        !          3477: 
        !          3478:                        } /* end while */
        !          3479:                        
        !          3480:                } /* end if */
        !          3481: 
        !          3482:                /* next iterator */
        !          3483:                iterator++;
        !          3484:        } /* end while */
        !          3485: 
        !          3486:        return axl_true;
        !          3487:        
        !          3488: }
        !          3489: 
        !          3490: /** 
        !          3491:  * @brief Allows to get the root node for the provided DTD.
        !          3492:  *
        !          3493:  * Every DTD have a root node defined, which is the root node accepted
        !          3494:  * for the set of XML document considered to be valid under the
        !          3495:  * definition of the DTD provided.
        !          3496:  *
        !          3497:  * The value returned is the name of the root node that must have the
        !          3498:  * XML document being validated.
        !          3499:  * 
        !          3500:  * @param dtd The \ref axlDtd where the root node name will be
        !          3501:  * returned.
        !          3502:  * 
        !          3503:  * @return A reference to the internal representation of the root node
        !          3504:  * Value must not be deallocated.
        !          3505:  */
        !          3506: axlDtdElement  * axl_dtd_get_root        (axlDtd * dtd)
        !          3507: {
        !          3508:        axl_return_val_if_fail (dtd, NULL);
        !          3509:        
        !          3510:        /* return current status for the root node */
        !          3511:        if (dtd->root == NULL) {
        !          3512:                __axl_log (LOG_DOMAIN, AXL_LEVEL_CRITICAL, "dtd root element not defined");
        !          3513:                return NULL;
        !          3514:        }
        !          3515:        return dtd->root;
        !          3516: }
        !          3517: 
        !          3518: /** 
        !          3519:  * @internal function used by \ref axl_dtd_get_element to perform node
        !          3520:  * lookups.
        !          3521:  */
        !          3522: axl_bool __find_dtd_element (axlPointer _element, axlPointer data)
        !          3523: {
        !          3524:        axlDtdElement * element = _element;
        !          3525:        char          * name    = data;
        !          3526: 
        !          3527:        /* check the name */
        !          3528:        if (axl_cmp (element->name, name))
        !          3529:                return axl_true;
        !          3530: 
        !          3531:        /* it is not the element */
        !          3532:        return axl_false;
        !          3533: }
        !          3534: 
        !          3535: /** 
        !          3536:  * @brief Allows to get the DTD element (\ref axlDtdElement), inside
        !          3537:  * the provided DTD (\ref axlDtd), that represent the spefication for
        !          3538:  * the node called by the provided name.
        !          3539:  * 
        !          3540:  * @param dtd The DTD (\ref axlDtd) where the lookup will be
        !          3541:  * performed.
        !          3542:  *
        !          3543:  * @param name The element name to lookup.
        !          3544:  * 
        !          3545:  * @return A reference to the \ref axlDtdElement searched or NULL if
        !          3546:  * fails. The function also returns NULL if values received are NULL.
        !          3547:  */
        !          3548: axlDtdElement      * axl_dtd_get_element      (axlDtd * dtd, const char * name)
        !          3549: {
        !          3550: 
        !          3551:        axl_return_val_if_fail (dtd, NULL);
        !          3552:        axl_return_val_if_fail (name, NULL);
        !          3553: 
        !          3554:        /* perform the lookup */
        !          3555:        return axl_list_lookup (dtd->elements, __find_dtd_element, (axlPointer) name);
        !          3556: }
        !          3557: 
        !          3558: /** 
        !          3559:  * @internal function used by \ref axl_dtd_get_attr to perform node
        !          3560:  * lookups.
        !          3561:  */
        !          3562: axl_bool __find_dtd_attr (axlPointer _element, axlPointer data)
        !          3563: {
        !          3564:        axlDtdAttribute * attr = _element;
        !          3565:        char            * name = data;
        !          3566: 
        !          3567:        /* check the name */
        !          3568:        if (axl_cmp (attr->name, name))
        !          3569:                return axl_true;
        !          3570: 
        !          3571:        /* it is not the element */
        !          3572:        return axl_false;
        !          3573: }
        !          3574: 
        !          3575: /** 
        !          3576:  * @brief Allows to get the set of attribute declerations for a
        !          3577:  * particular node. 
        !          3578:  *
        !          3579:  * The \ref axlDtdAttribute declaration contains all constraints
        !          3580:  * configured for attributes found for the particular xml node
        !          3581:  * (identified by <b>name</b>).
        !          3582:  * 
        !          3583:  * @param dtd A reference to the DTD document.
        !          3584:  *
        !          3585:  * @param nodeName The xml node that is requested to return all attribute
        !          3586:  * declarations.
        !          3587:  * 
        !          3588:  * @return A reference to the \ref axlDtdAttribute or NULL if it
        !          3589:  * fails.
        !          3590:  */
        !          3591: axlDtdAttribute    * axl_dtd_get_attr         (axlDtd * dtd,
        !          3592:                                               const char * nodeName)
        !          3593: {
        !          3594:        axl_return_val_if_fail (dtd, NULL);
        !          3595:        axl_return_val_if_fail (nodeName, NULL);
        !          3596: 
        !          3597:        /* perform the lookup */
        !          3598:        return axl_list_lookup (dtd->attributes, __find_dtd_attr, (axlPointer) nodeName);
        !          3599: }
        !          3600: 
        !          3601: /** 
        !          3602:  * @brief Allows to get the number of constraints that have been
        !          3603:  * configured for the particular node.
        !          3604:  * 
        !          3605:  * @param dtd The reference to the DTD document.
        !          3606:  *
        !          3607:  * @param nodeName The name of the node that is being asked for its
        !          3608:  * constraints.
        !          3609:  * 
        !          3610:  * @return 0 or the number of contraints. The function return -1 if
        !          3611:  * any of the parameter received is null.
        !          3612:  */
        !          3613: int                  axl_dtd_get_attr_contraints (axlDtd * dtd,
        !          3614:                                                  const char * nodeName)
        !          3615: {
        !          3616:        axlDtdAttribute * attr;
        !          3617: 
        !          3618:        axl_return_val_if_fail (dtd, -1);
        !          3619:        axl_return_val_if_fail (nodeName, -1);
        !          3620: 
        !          3621:        /* get the attribute specification for the node */
        !          3622:        attr = axl_dtd_get_attr (dtd, nodeName);
        !          3623: 
        !          3624:        /* return the number of items */
        !          3625:        return axl_list_length (attr->list);
        !          3626: }
        !          3627: 
        !          3628: /** 
        !          3629:  * @brief Returns the name of the provided \ref axlDtdElement.
        !          3630:  * 
        !          3631:  * @param element A reference to a \ref axlDtdElement where the name
        !          3632:  * will be returned.
        !          3633:  * 
        !          3634:  * @return A reference to the internal DTD element name. Returned
        !          3635:  * value mustn't be deallocated.
        !          3636:  */
        !          3637: char           * axl_dtd_get_element_name (axlDtdElement * element)
        !          3638: {
        !          3639:        axl_return_val_if_fail (element,  NULL);
        !          3640: 
        !          3641:        return element->name;
        !          3642: }
        !          3643: 
        !          3644: /** 
        !          3645:  * @brief Returns current element type for the provided \ref axlDtdElement.
        !          3646:  * 
        !          3647:  * @param element The axlDtdElement where its type will be returned.
        !          3648:  * 
        !          3649:  * @return Current element type for the provided node.
        !          3650:  */
        !          3651: AxlDtdElementType    axl_dtd_get_element_type (axlDtdElement * element)
        !          3652: {
        !          3653:        axl_return_val_if_fail (element, ELEMENT_TYPE_UNKNOWN);
        !          3654:        
        !          3655:        return element->type;
        !          3656: }
        !          3657: 
        !          3658: /** 
        !          3659:  * @brief Returns current DTD content specification, represented by the Item list.
        !          3660:  * 
        !          3661:  * @param element The DTD element (\ref axlDtdElement) which is being
        !          3662:  * requested to return its \ref axlDtdElementList.
        !          3663:  * 
        !          3664:  * @return The \ref axlDtdElementList reference. The value returned
        !          3665:  * must not be deallocated. The function returns NULL if the reference received is NULL.
        !          3666:  */
        !          3667: axlDtdElementList  * axl_dtd_get_item_list    (axlDtdElement * element)
        !          3668: {
        !          3669:        axl_return_val_if_fail (element, NULL);
        !          3670: 
        !          3671:        return element->list; 
        !          3672: }
        !          3673: 
        !          3674: /** 
        !          3675:  * @brief Allows to check if the provided DTD ELEMENT representation
        !          3676:  * is a top level definition.
        !          3677:  * 
        !          3678:  * @param dtd The DTD document where the operation will be performed.
        !          3679:  * @param element The \ref axlDtdElement to check.
        !          3680:  * 
        !          3681:  * @return \ref axl_true if the dtd element is a top level element or
        !          3682:  * \ref axl_false if not. The function returns \ref axl_false if the
        !          3683:  * provided reference is NULL.
        !          3684:  */
        !          3685: axl_bool                    axl_dtd_element_is_toplevel (axlDtd * dtd, axlDtdElement * element)
        !          3686: {
        !          3687:        /* support several top level definitions */
        !          3688:        int             iterator;
        !          3689:        axlDtdElement * dtd_element_aux;
        !          3690: 
        !          3691:        axl_return_val_if_fail (dtd,     axl_false);
        !          3692:        axl_return_val_if_fail (element, axl_false);
        !          3693: 
        !          3694:        /* check which is the top */
        !          3695:        iterator        = 0;
        !          3696:        while (iterator < axl_list_length (dtd->elements)) {
        !          3697:                        
        !          3698:                /* get the next reference */
        !          3699:                dtd_element_aux = axl_list_get_nth (dtd->elements, iterator);
        !          3700:                        
        !          3701:                /* check which is the top */
        !          3702:                if (__axl_dtd_get_is_parent (dtd_element_aux, element)) {
        !          3703:                        /* the element provided have a parent */
        !          3704:                        return axl_false;
        !          3705:                }
        !          3706:                        
        !          3707:                /* update inner loop iterator */
        !          3708:                iterator ++;
        !          3709:        } /* while end */
        !          3710: 
        !          3711:        /* return that the provided node doesn't have a parent node */
        !          3712:        return axl_true;
        !          3713: }
        !          3714: 
        !          3715: /** 
        !          3716:  * @brief Returns the number of item nodes (\ref
        !          3717:  * axlDtdElementListNode) inside the item list received (\ref axlDtdElementList).
        !          3718:  * 
        !          3719:  * @param itemList The \ref axlDtdElementList where the count
        !          3720:  * operation is being requested.
        !          3721:  * 
        !          3722:  * @return The number of item list the provided \ref axlDtdElementList
        !          3723:  * reference has. The function return -1 if the provided reference is
        !          3724:  * NULL.
        !          3725:  */
        !          3726: int                  axl_dtd_item_list_count  (axlDtdElementList * itemList)
        !          3727: {
        !          3728:        axl_return_val_if_fail (itemList, -1);
        !          3729: 
        !          3730:        if (itemList->itemList == NULL)
        !          3731:                return 0;
        !          3732: 
        !          3733:        return axl_list_length (itemList->itemList);
        !          3734: }
        !          3735: 
        !          3736: /** 
        !          3737:  * @brief Allows to get current configuration for the provided item
        !          3738:  * list, which is the content specification for a DTD element.
        !          3739:  * 
        !          3740:  * @param itemList The item list where the operation will be
        !          3741:  * performed.
        !          3742:  * 
        !          3743:  * @return Current configuration (\ref SEQUENCE or a \ref CHOICE).
        !          3744:  */
        !          3745: AxlDtdNestedType     axl_dtd_item_list_type   (axlDtdElementList * itemList)
        !          3746: {
        !          3747:        axl_return_val_if_fail (itemList, -1);
        !          3748: 
        !          3749:        return itemList->type;
        !          3750: }
        !          3751: 
        !          3752: /** 
        !          3753:  * @brief Allows to get current configuration for DTD content spec
        !          3754:  * repetition.
        !          3755:  * 
        !          3756:  * @param itemList The content spec where the query will be performed.
        !          3757:  * 
        !          3758:  * @return Current configuration for times to be repeated DTD element
        !          3759:  * content specification.
        !          3760:  */
        !          3761: AxlDtdTimes          axl_dtd_item_list_repeat (axlDtdElementList * itemList)
        !          3762: {
        !          3763:        axl_return_val_if_fail (itemList, DTD_TIMES_UNKNOWN);
        !          3764: 
        !          3765:        /* returns current times configuration */
        !          3766:        return itemList->times;
        !          3767: }
        !          3768: 
        !          3769: /** 
        !          3770:  * @brief Allows to get the provided item node reference (\ref
        !          3771:  * axlDtdElementListNode) from the provided item list (\ref
        !          3772:  * axlDtdElementList).
        !          3773:  *
        !          3774:  * Provided position ranges from 0 up to \ref axl_dtd_item_list_count.
        !          3775:  * 
        !          3776:  * @param itemList The itemList where the operation will be performed.
        !          3777:  * @param position The position where the item node will be looked up.
        !          3778:  * 
        !          3779:  * @return A reference to the \ref axlDtdElementListNode, or NULL if
        !          3780:  * there is no item node at the selected index.  The function return
        !          3781:  * NULL if the provided position is a non positive value or it is
        !          3782:  * greater than the current item list count (\ref
        !          3783:  * axl_dtd_item_list_count) or the provided item list reference is
        !          3784:  * NULL.
        !          3785:  */
        !          3786: axlDtdElementListNode * axl_dtd_item_list_get_node (axlDtdElementList * itemList, 
        !          3787:                                                    int position)
        !          3788: {
        !          3789:        axl_return_val_if_fail (itemList, NULL);
        !          3790:        axl_return_val_if_fail (position >= 0, NULL);
        !          3791:        axl_return_val_if_fail (position < axl_dtd_item_list_count (itemList), NULL);
        !          3792:        
        !          3793:        return axl_list_get_nth (itemList->itemList, position);
        !          3794: }
        !          3795: 
        !          3796: /** 
        !          3797:  * @brief Allows to get current node type for the provided DTD element
        !          3798:  * type content particule or item node (\ref axlDtdElementListNode).
        !          3799:  *
        !          3800:  * @param node The node where the type is being requested.
        !          3801:  * 
        !          3802:  * @return It returns if the item node contains a final leaf node,
        !          3803:  * making a reference to an explicit node naming that is allowed to be
        !          3804:  * used in the context where is found the provided \ref
        !          3805:  * axlDtdElementListNode or a \ref axlDtdElementList containing more
        !          3806:  * nodes or lists. 
        !          3807:  */
        !          3808: NodeType             axl_dtd_item_node_get_type (axlDtdElementListNode * node)
        !          3809: {
        !          3810:        axl_return_val_if_fail (node, AXL_ELEMENT_NOT_DEFINED);
        !          3811:        return node->type;
        !          3812: }
        !          3813: 
        !          3814: /** 
        !          3815:  * @brief Returns the item list inside the provided node.
        !          3816:  *
        !          3817:  * The node is supported to contain an item list reference or NULL
        !          3818:  * will be returned. Check \ref axl_dtd_item_node_get_type.
        !          3819:  * 
        !          3820:  * @param node The node where the operation will be performed.
        !          3821:  * 
        !          3822:  * @return The item list inside the node or NULL if fails.
        !          3823:  */
        !          3824: axlDtdElementList   * axl_dtd_item_node_get_list (axlDtdElementListNode * node)
        !          3825: {
        !          3826:        axl_return_val_if_fail (node, NULL);
        !          3827:        axl_return_val_if_fail (node->type == AXL_ELEMENT_LIST, NULL);
        !          3828: 
        !          3829:        return node->data;
        !          3830: }
        !          3831: 
        !          3832: /** 
        !          3833:  * @brief Allows to get the dtd item list value, which represents the
        !          3834:  * node name that is being constrained/represented.
        !          3835:  * 
        !          3836:  * @param node The item node where the value is being requested.
        !          3837:  * 
        !          3838:  * @return The value inside the item node, supposing it contains an
        !          3839:  * leaf item node or NULL if fails. The value returned must not be
        !          3840:  * deallocated.
        !          3841:  */
        !          3842: char               * axl_dtd_item_node_get_value (axlDtdElementListNode * node)
        !          3843: {
        !          3844:        axl_return_val_if_fail (node, NULL);
        !          3845:        if (node->type != AXL_ELEMENT_NODE) 
        !          3846:                return "requested-value-on-a-list";
        !          3847: 
        !          3848:        return node->data;
        !          3849: }
        !          3850: 
        !          3851: /** 
        !          3852:  * @brief Allows to get current configuration for the provided content
        !          3853:  * particule for the times to be repeated.
        !          3854:  * 
        !          3855:  * @param node The content particule where the query will be
        !          3856:  * performed.
        !          3857:  * 
        !          3858:  * @return Return current repetition configuration. 
        !          3859:  */
        !          3860: AxlDtdTimes          axl_dtd_item_node_get_repeat (axlDtdElementListNode * node)
        !          3861: {
        !          3862:        axlDtdElementList * list;
        !          3863: 
        !          3864:        axl_return_val_if_fail (node, DTD_TIMES_UNKNOWN);
        !          3865: 
        !          3866: 
        !          3867:        if (node->type == AXL_ELEMENT_NODE) {
        !          3868:                /* return value requested */
        !          3869:                return node->times;
        !          3870:        }
        !          3871: 
        !          3872:        if (node->type == AXL_ELEMENT_LIST) {
        !          3873:                /* return the requested value for an item list */
        !          3874:                list = node->data;
        !          3875:                return list->times;
        !          3876:        }
        !          3877:        
        !          3878:        /* return that we don't know man */
        !          3879:        return DTD_TIMES_UNKNOWN;
        !          3880: }
        !          3881: 
        !          3882: 
        !          3883: /** 
        !          3884:  * @internal
        !          3885:  *
        !          3886:  * Internal function which allows to lookup the DTD entity reference
        !          3887:  * provided the name and the type.
        !          3888:  */
        !          3889: axlDtdEntity * __axl_dtd_entity_lookup (axlDtd            * dtd, 
        !          3890:                                        const char        * name,
        !          3891:                                        axlDtdEntityType    type)
        !          3892: {
        !          3893:        axlDtdEntity  * entity;
        !          3894:        int             iterator;
        !          3895:        int             length;
        !          3896: 
        !          3897:        /* check values received */
        !          3898:        axl_return_val_if_fail (dtd,  NULL);
        !          3899:        axl_return_val_if_fail (name, NULL);
        !          3900: 
        !          3901:        /* lookup for the item */
        !          3902:        iterator = 0;
        !          3903:        length   = axl_list_length (dtd->entities);
        !          3904:        while (iterator < length) {
        !          3905: 
        !          3906:                /* get the entity at the provided position */
        !          3907:                entity = axl_list_get_nth (dtd->entities, iterator);
        !          3908: 
        !          3909:                /* check the type and the name */
        !          3910:                if ((entity->type == type) && axl_cmp (entity->name, name))
        !          3911:                        return entity;
        !          3912:                
        !          3913:                /* update iterator */
        !          3914:                iterator++;
        !          3915:        } /* end while */
        !          3916: 
        !          3917:        return NULL;
        !          3918: }
        !          3919: 
        !          3920: /** 
        !          3921:  * @brief Allows to check if the provided entity name, with the
        !          3922:  * provided type is defined on the given DTD object.
        !          3923:  * 
        !          3924:  * @param dtd The \ref axlDtd instance where the entity lookup will be
        !          3925:  * performed.
        !          3926:  *
        !          3927:  * @param name The entity name to lookup.
        !          3928:  *
        !          3929:  * @param type The entity type to lookup.
        !          3930:  * 
        !          3931:  * @return axl_true if an entity is found named as provided with the type
        !          3932:  * provided. Othewise, axl_false is returned.
        !          3933:  */
        !          3934: axl_bool                 axl_dtd_entity_exists    (axlDtd            * dtd, 
        !          3935:                                                   const char        * name,
        !          3936:                                                   axlDtdEntityType    type)
        !          3937: {
        !          3938:        /* return if the entity exists */
        !          3939:        return (__axl_dtd_entity_lookup (dtd, name, type) != NULL);
        !          3940: }
        !          3941: 
        !          3942: /** 
        !          3943:  * @brief Allows to get the content configured inside the entity that
        !          3944:  * is identified by the provided name and the provided type.
        !          3945:  * 
        !          3946:  * @param dtd The DTD where the lookup will be performed.
        !          3947:  *
        !          3948:  * @param name The entity name to lookup for its content.
        !          3949:  *
        !          3950:  * @param type The entity type to match.
        !          3951:  * 
        !          3952:  * @return An internal reference to the content associated to the
        !          3953:  * entity found or NULL. In case the content is defined (as return
        !          3954:  * value) it must not be deallocated.
        !          3955:  */
        !          3956: char               * axl_dtd_entity_value     (axlDtd            * dtd, 
        !          3957:                                               const char        * name,
        !          3958:                                               axlDtdEntityType    type)
        !          3959: {
        !          3960:        axlDtdEntity * entity;
        !          3961: 
        !          3962:        /* get the entity reference */
        !          3963:        entity = __axl_dtd_entity_lookup (dtd, name, type);
        !          3964:        
        !          3965:        /* check the entity reference */
        !          3966:        axl_return_val_if_fail (entity, NULL);
        !          3967: 
        !          3968:        /* return the content */
        !          3969:        return entity->content;
        !          3970: }
        !          3971: 
        !          3972: /** 
        !          3973:  * @brief Allows to destroy the provided \ref axlDtd  document.
        !          3974:  * 
        !          3975:  * @param dtd The \ref axlDtd document to destroy.
        !          3976:  */
        !          3977: void       axl_dtd_free  (axlDtd * dtd)
        !          3978: {
        !          3979:        if (dtd == NULL) {
        !          3980:                __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "received a null DTD reference, doing nothing");
        !          3981:                return;
        !          3982:        }
        !          3983:        
        !          3984:        __axl_log (LOG_DOMAIN, AXL_LEVEL_DEBUG, "releasing the DTD reference");
        !          3985:        /* free dtd elements */
        !          3986:        if (dtd->elements)
        !          3987:                axl_list_free (dtd->elements);
        !          3988: 
        !          3989:        /* free entities */
        !          3990:        if (dtd->entities)
        !          3991:                axl_list_free (dtd->entities);
        !          3992: 
        !          3993:        /* free attributes */
        !          3994:        if (dtd->attributes)
        !          3995:                axl_list_free (dtd->attributes);
        !          3996: 
        !          3997:        /* free the node itself */
        !          3998:        axl_free (dtd);
        !          3999: 
        !          4000:        return;
        !          4001: }
        !          4002: 
        !          4003: 
        !          4004: /** 
        !          4005:  * @internal
        !          4006:  *
        !          4007:  * @brief Allows to release the memory hold by the given
        !          4008:  * axlDtdElement.
        !          4009:  * 
        !          4010:  * @param element The axlDtdElement to release.
        !          4011:  */
        !          4012: void       axl_dtd_element_free (axlDtdElement * element)
        !          4013: {
        !          4014:        if (element == NULL)
        !          4015:                return;
        !          4016: 
        !          4017:        /* free element name */
        !          4018:        if (element->name != NULL)
        !          4019:                axl_free (element->name);
        !          4020: 
        !          4021:        /* free element list definitions */
        !          4022:        axl_dtd_item_list_free (element->list);
        !          4023:        
        !          4024:        /* free element itself */
        !          4025:        axl_free (element);
        !          4026: 
        !          4027:        return;
        !          4028: }
        !          4029: 
        !          4030: /** 
        !          4031:  * @internal 
        !          4032:  *
        !          4033:  * @brief Deallocates memory used by the \ref axlDtdElementList
        !          4034:  * reference.
        !          4035:  * 
        !          4036:  * @param list The reference to deallocate.
        !          4037:  */
        !          4038: void axl_dtd_item_list_free (axlDtdElementList * list)
        !          4039: {
        !          4040:        if (list == NULL)
        !          4041:                return;
        !          4042:        
        !          4043:        /* check and deallocate the list provided */
        !          4044:        if (list->itemList != NULL)
        !          4045:                axl_list_free (list->itemList);
        !          4046:        
        !          4047:        /* deallocates the node itself */
        !          4048:        axl_free (list);
        !          4049:        return;
        !          4050: }
        !          4051: 
        !          4052: /* @} */
        !          4053: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>