Annotation of embedaddon/libxml2/debugXML.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * debugXML.c : This is a set of routines used for debugging the tree
                      3:  *              produced by the XML parser.
                      4:  *
                      5:  * See Copyright for the status of this software.
                      6:  *
                      7:  * Daniel Veillard <daniel@veillard.com>
                      8:  */
                      9: 
                     10: #define IN_LIBXML
                     11: #include "libxml.h"
                     12: #ifdef LIBXML_DEBUG_ENABLED
                     13: 
                     14: #include <string.h>
                     15: #ifdef HAVE_STDLIB_H
                     16: #include <stdlib.h>
                     17: #endif
                     18: #ifdef HAVE_STRING_H
                     19: #include <string.h>
                     20: #endif
                     21: #include <libxml/xmlmemory.h>
                     22: #include <libxml/tree.h>
                     23: #include <libxml/parser.h>
                     24: #include <libxml/parserInternals.h>
                     25: #include <libxml/valid.h>
                     26: #include <libxml/debugXML.h>
                     27: #include <libxml/HTMLtree.h>
                     28: #include <libxml/HTMLparser.h>
                     29: #include <libxml/xmlerror.h>
                     30: #include <libxml/globals.h>
                     31: #include <libxml/xpathInternals.h>
                     32: #include <libxml/uri.h>
                     33: #ifdef LIBXML_SCHEMAS_ENABLED
                     34: #include <libxml/relaxng.h>
                     35: #endif
                     36: 
                     37: #define DUMP_TEXT_TYPE 1
                     38: 
                     39: typedef struct _xmlDebugCtxt xmlDebugCtxt;
                     40: typedef xmlDebugCtxt *xmlDebugCtxtPtr;
                     41: struct _xmlDebugCtxt {
                     42:     FILE *output;               /* the output file */
                     43:     char shift[101];            /* used for indenting */
                     44:     int depth;                  /* current depth */
                     45:     xmlDocPtr doc;              /* current document */
                     46:     xmlNodePtr node;           /* current node */
                     47:     xmlDictPtr dict;           /* the doc dictionnary */
                     48:     int check;                  /* do just checkings */
                     49:     int errors;                 /* number of errors found */
                     50:     int nodict;                        /* if the document has no dictionnary */
                     51:     int options;               /* options */
                     52: };
                     53: 
                     54: static void xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node);
                     55: 
                     56: static void
                     57: xmlCtxtDumpInitCtxt(xmlDebugCtxtPtr ctxt)
                     58: {
                     59:     int i;
                     60: 
                     61:     ctxt->depth = 0;
                     62:     ctxt->check = 0;
                     63:     ctxt->errors = 0;
                     64:     ctxt->output = stdout;
                     65:     ctxt->doc = NULL;
                     66:     ctxt->node = NULL;
                     67:     ctxt->dict = NULL;
                     68:     ctxt->nodict = 0;
                     69:     ctxt->options = 0;
                     70:     for (i = 0; i < 100; i++)
                     71:         ctxt->shift[i] = ' ';
                     72:     ctxt->shift[100] = 0;
                     73: }
                     74: 
                     75: static void
                     76: xmlCtxtDumpCleanCtxt(xmlDebugCtxtPtr ctxt ATTRIBUTE_UNUSED)
                     77: {
                     78:  /* remove the ATTRIBUTE_UNUSED when this is added */
                     79: }
                     80: 
                     81: /**
                     82:  * xmlNsCheckScope:
                     83:  * @node: the node
                     84:  * @ns: the namespace node
                     85:  *
                     86:  * Check that a given namespace is in scope on a node.
                     87:  *
                     88:  * Returns 1 if in scope, -1 in case of argument error, 
                     89:  *         -2 if the namespace is not in scope, and -3 if not on
                     90:  *         an ancestor node.
                     91:  */
                     92: static int
                     93: xmlNsCheckScope(xmlNodePtr node, xmlNsPtr ns)
                     94: {
                     95:     xmlNsPtr cur;
                     96: 
                     97:     if ((node == NULL) || (ns == NULL))
                     98:         return(-1);
                     99: 
                    100:     if ((node->type != XML_ELEMENT_NODE) &&
                    101:        (node->type != XML_ATTRIBUTE_NODE) &&
                    102:        (node->type != XML_DOCUMENT_NODE) &&
                    103:        (node->type != XML_TEXT_NODE) &&
                    104:        (node->type != XML_HTML_DOCUMENT_NODE) &&
                    105:        (node->type != XML_XINCLUDE_START))
                    106:        return(-2);
                    107: 
                    108:     while ((node != NULL) &&
                    109:            ((node->type == XML_ELEMENT_NODE) ||
                    110:             (node->type == XML_ATTRIBUTE_NODE) ||
                    111:             (node->type == XML_TEXT_NODE) ||
                    112:            (node->type == XML_XINCLUDE_START))) {
                    113:        if ((node->type == XML_ELEMENT_NODE) ||
                    114:            (node->type == XML_XINCLUDE_START)) {
                    115:            cur = node->nsDef;
                    116:            while (cur != NULL) {
                    117:                if (cur == ns)
                    118:                    return(1);
                    119:                if (xmlStrEqual(cur->prefix, ns->prefix))
                    120:                    return(-2);
                    121:                cur = cur->next;
                    122:            }
                    123:        }
                    124:        node = node->parent;
                    125:     }
                    126:     /* the xml namespace may be declared on the document node */
                    127:     if ((node != NULL) &&
                    128:         ((node->type == XML_DOCUMENT_NODE) ||
                    129:         (node->type == XML_HTML_DOCUMENT_NODE))) {
                    130:         xmlNsPtr oldNs = ((xmlDocPtr) node)->oldNs;
                    131:         if (oldNs == ns)
                    132:             return(1);
                    133:     }
                    134:     return(-3);
                    135: }
                    136: 
                    137: static void
                    138: xmlCtxtDumpSpaces(xmlDebugCtxtPtr ctxt)
                    139: {
                    140:     if (ctxt->check)
                    141:         return;
                    142:     if ((ctxt->output != NULL) && (ctxt->depth > 0)) {
                    143:         if (ctxt->depth < 50)
                    144:             fprintf(ctxt->output, "%s", &ctxt->shift[100 - 2 * ctxt->depth]);
                    145:         else
                    146:             fprintf(ctxt->output, "%s", ctxt->shift);
                    147:     }
                    148: }
                    149: 
                    150: /**
                    151:  * xmlDebugErr:
                    152:  * @ctxt:  a debug context
                    153:  * @error:  the error code
                    154:  *
                    155:  * Handle a debug error.
                    156:  */
                    157: static void
                    158: xmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg)
                    159: {
                    160:     ctxt->errors++;
                    161:     __xmlRaiseError(NULL, NULL, NULL,
                    162:                    NULL, ctxt->node, XML_FROM_CHECK,
                    163:                    error, XML_ERR_ERROR, NULL, 0,
                    164:                    NULL, NULL, NULL, 0, 0,
                    165:                    "%s", msg);
                    166: }
                    167: static void
                    168: xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra)
                    169: {
                    170:     ctxt->errors++;
                    171:     __xmlRaiseError(NULL, NULL, NULL,
                    172:                    NULL, ctxt->node, XML_FROM_CHECK,
                    173:                    error, XML_ERR_ERROR, NULL, 0,
                    174:                    NULL, NULL, NULL, 0, 0,
                    175:                    msg, extra);
                    176: }
                    177: static void
                    178: xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra)
                    179: {
                    180:     ctxt->errors++;
                    181:     __xmlRaiseError(NULL, NULL, NULL,
                    182:                    NULL, ctxt->node, XML_FROM_CHECK,
                    183:                    error, XML_ERR_ERROR, NULL, 0,
                    184:                    NULL, NULL, NULL, 0, 0,
                    185:                    msg, extra);
                    186: }
                    187: 
                    188: /**
                    189:  * xmlCtxtNsCheckScope:
                    190:  * @ctxt: the debugging context
                    191:  * @node: the node
                    192:  * @ns: the namespace node
                    193:  *
                    194:  * Report if a given namespace is is not in scope.
                    195:  */
                    196: static void
                    197: xmlCtxtNsCheckScope(xmlDebugCtxtPtr ctxt, xmlNodePtr node, xmlNsPtr ns)
                    198: {
                    199:     int ret;
                    200: 
                    201:     ret = xmlNsCheckScope(node, ns);
                    202:     if (ret == -2) {
                    203:         if (ns->prefix == NULL)
                    204:            xmlDebugErr(ctxt, XML_CHECK_NS_SCOPE,
                    205:                        "Reference to default namespace not in scope\n");
                    206:        else
                    207:            xmlDebugErr3(ctxt, XML_CHECK_NS_SCOPE,
                    208:                         "Reference to namespace '%s' not in scope\n",
                    209:                         (char *) ns->prefix);
                    210:     }
                    211:     if (ret == -3) {
                    212:         if (ns->prefix == NULL)
                    213:            xmlDebugErr(ctxt, XML_CHECK_NS_ANCESTOR,
                    214:                        "Reference to default namespace not on ancestor\n");
                    215:        else
                    216:            xmlDebugErr3(ctxt, XML_CHECK_NS_ANCESTOR,
                    217:                         "Reference to namespace '%s' not on ancestor\n",
                    218:                         (char *) ns->prefix);
                    219:     }
                    220: }
                    221: 
                    222: /**
                    223:  * xmlCtxtCheckString:
                    224:  * @ctxt: the debug context
                    225:  * @str: the string
                    226:  *
                    227:  * Do debugging on the string, currently it just checks the UTF-8 content
                    228:  */
                    229: static void
                    230: xmlCtxtCheckString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
                    231: {
                    232:     if (str == NULL) return;
                    233:     if (ctxt->check) {
                    234:         if (!xmlCheckUTF8(str)) {
                    235:            xmlDebugErr3(ctxt, XML_CHECK_NOT_UTF8,
                    236:                         "String is not UTF-8 %s", (const char *) str);
                    237:        }
                    238:     }
                    239: }
                    240: 
                    241: /**
                    242:  * xmlCtxtCheckName:
                    243:  * @ctxt: the debug context
                    244:  * @name: the name
                    245:  *
                    246:  * Do debugging on the name, for example the dictionnary status and
                    247:  * conformance to the Name production.
                    248:  */
                    249: static void
                    250: xmlCtxtCheckName(xmlDebugCtxtPtr ctxt, const xmlChar * name)
                    251: {
                    252:     if (ctxt->check) {
                    253:        if (name == NULL) {
                    254:            xmlDebugErr(ctxt, XML_CHECK_NO_NAME, "Name is NULL");
                    255:            return;
                    256:        }
                    257:         if (xmlValidateName(name, 0)) {
                    258:            xmlDebugErr3(ctxt, XML_CHECK_NOT_NCNAME,
                    259:                         "Name is not an NCName '%s'", (const char *) name);
                    260:        }
                    261:        if ((ctxt->dict != NULL) &&
                    262:            (!xmlDictOwns(ctxt->dict, name)) &&
                    263:             ((ctxt->doc == NULL) ||
                    264:              ((ctxt->doc->parseFlags & (XML_PARSE_SAX1 | XML_PARSE_NODICT)) == 0))) {
                    265:            xmlDebugErr3(ctxt, XML_CHECK_OUTSIDE_DICT,
                    266:                         "Name is not from the document dictionnary '%s'",
                    267:                         (const char *) name);
                    268:        }
                    269:     }
                    270: }
                    271: 
                    272: static void
                    273: xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) {
                    274:     xmlDocPtr doc;
                    275:     xmlDictPtr dict;
                    276: 
                    277:     doc = node->doc;
                    278: 
                    279:     if (node->parent == NULL)
                    280:         xmlDebugErr(ctxt, XML_CHECK_NO_PARENT,
                    281:                    "Node has no parent\n");
                    282:     if (node->doc == NULL) {
                    283:         xmlDebugErr(ctxt, XML_CHECK_NO_DOC,
                    284:                    "Node has no doc\n");
                    285:         dict = NULL;
                    286:     } else {
                    287:        dict = doc->dict;
                    288:        if ((dict == NULL) && (ctxt->nodict == 0)) {
                    289: #if 0
                    290:             /* desactivated right now as it raises too many errors */
                    291:            if (doc->type == XML_DOCUMENT_NODE)
                    292:                xmlDebugErr(ctxt, XML_CHECK_NO_DICT,
                    293:                            "Document has no dictionnary\n");
                    294: #endif
                    295:            ctxt->nodict = 1;
                    296:        }
                    297:        if (ctxt->doc == NULL)
                    298:            ctxt->doc = doc;
                    299: 
                    300:        if (ctxt->dict == NULL) {
                    301:            ctxt->dict = dict;
                    302:        }
                    303:     }
                    304:     if ((node->parent != NULL) && (node->doc != node->parent->doc) &&
                    305:         (!xmlStrEqual(node->name, BAD_CAST "pseudoroot")))
                    306:         xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC,
                    307:                    "Node doc differs from parent's one\n");
                    308:     if (node->prev == NULL) {
                    309:         if (node->type == XML_ATTRIBUTE_NODE) {
                    310:            if ((node->parent != NULL) &&
                    311:                (node != (xmlNodePtr) node->parent->properties))
                    312:                xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
                    313:                     "Attr has no prev and not first of attr list\n");
                    314:                
                    315:         } else if ((node->parent != NULL) && (node->parent->children != node))
                    316:            xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
                    317:                     "Node has no prev and not first of parent list\n");
                    318:     } else {
                    319:         if (node->prev->next != node)
                    320:            xmlDebugErr(ctxt, XML_CHECK_WRONG_PREV,
                    321:                         "Node prev->next : back link wrong\n");
                    322:     }
                    323:     if (node->next == NULL) {
                    324:        if ((node->parent != NULL) && (node->type != XML_ATTRIBUTE_NODE) &&
                    325:            (node->parent->last != node) &&
                    326:            (node->parent->type == XML_ELEMENT_NODE))
                    327:            xmlDebugErr(ctxt, XML_CHECK_NO_NEXT,
                    328:                     "Node has no next and not last of parent list\n");
                    329:     } else {
                    330:         if (node->next->prev != node)
                    331:            xmlDebugErr(ctxt, XML_CHECK_WRONG_NEXT,
                    332:                     "Node next->prev : forward link wrong\n");
                    333:         if (node->next->parent != node->parent)
                    334:            xmlDebugErr(ctxt, XML_CHECK_WRONG_PARENT,
                    335:                     "Node next->prev : forward link wrong\n");
                    336:     }
                    337:     if (node->type == XML_ELEMENT_NODE) {
                    338:         xmlNsPtr ns;
                    339: 
                    340:        ns = node->nsDef;
                    341:        while (ns != NULL) {
                    342:            xmlCtxtNsCheckScope(ctxt, node, ns);
                    343:            ns = ns->next;
                    344:        }
                    345:        if (node->ns != NULL)
                    346:            xmlCtxtNsCheckScope(ctxt, node, node->ns);
                    347:     } else if (node->type == XML_ATTRIBUTE_NODE) {
                    348:        if (node->ns != NULL)
                    349:            xmlCtxtNsCheckScope(ctxt, node, node->ns);
                    350:     }
                    351: 
                    352:     if ((node->type != XML_ELEMENT_NODE) &&
                    353:        (node->type != XML_ATTRIBUTE_NODE) &&
                    354:        (node->type != XML_ELEMENT_DECL) &&
                    355:        (node->type != XML_ATTRIBUTE_DECL) &&
                    356:        (node->type != XML_DTD_NODE) &&
                    357:        (node->type != XML_ELEMENT_DECL) &&
                    358:        (node->type != XML_HTML_DOCUMENT_NODE) &&
                    359:        (node->type != XML_DOCUMENT_NODE)) {
                    360:        if (node->content != NULL)
                    361:            xmlCtxtCheckString(ctxt, (const xmlChar *) node->content);
                    362:     }
                    363:     switch (node->type) {
                    364:         case XML_ELEMENT_NODE:
                    365:         case XML_ATTRIBUTE_NODE:
                    366:            xmlCtxtCheckName(ctxt, node->name);
                    367:            break;
                    368:         case XML_TEXT_NODE:
                    369:            if ((node->name == xmlStringText) ||
                    370:                (node->name == xmlStringTextNoenc))
                    371:                break;
                    372:            /* some case of entity substitution can lead to this */
                    373:            if ((ctxt->dict != NULL) &&
                    374:                (node->name == xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
                    375:                                             7)))
                    376:                break;
                    377: 
                    378:            xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
                    379:                         "Text node has wrong name '%s'",
                    380:                         (const char *) node->name);
                    381:            break;
                    382:         case XML_COMMENT_NODE:
                    383:            if (node->name == xmlStringComment)
                    384:                break;
                    385:            xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
                    386:                         "Comment node has wrong name '%s'",
                    387:                         (const char *) node->name);
                    388:            break;
                    389:         case XML_PI_NODE:
                    390:            xmlCtxtCheckName(ctxt, node->name);
                    391:            break;
                    392:         case XML_CDATA_SECTION_NODE:
                    393:            if (node->name == NULL)
                    394:                break;
                    395:            xmlDebugErr3(ctxt, XML_CHECK_NAME_NOT_NULL,
                    396:                         "CData section has non NULL name '%s'",
                    397:                         (const char *) node->name);
                    398:            break;
                    399:         case XML_ENTITY_REF_NODE:
                    400:         case XML_ENTITY_NODE:
                    401:         case XML_DOCUMENT_TYPE_NODE:
                    402:         case XML_DOCUMENT_FRAG_NODE:
                    403:         case XML_NOTATION_NODE:
                    404:         case XML_DTD_NODE:
                    405:         case XML_ELEMENT_DECL:
                    406:         case XML_ATTRIBUTE_DECL:
                    407:         case XML_ENTITY_DECL:
                    408:         case XML_NAMESPACE_DECL:
                    409:         case XML_XINCLUDE_START:
                    410:         case XML_XINCLUDE_END:
                    411: #ifdef LIBXML_DOCB_ENABLED
                    412:         case XML_DOCB_DOCUMENT_NODE:
                    413: #endif
                    414:         case XML_DOCUMENT_NODE:
                    415:         case XML_HTML_DOCUMENT_NODE:
                    416:            break;
                    417:     }
                    418: }
                    419: 
                    420: static void
                    421: xmlCtxtDumpString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
                    422: {
                    423:     int i;
                    424: 
                    425:     if (ctxt->check) {
                    426:         return;
                    427:     }
                    428:     /* TODO: check UTF8 content of the string */
                    429:     if (str == NULL) {
                    430:         fprintf(ctxt->output, "(NULL)");
                    431:         return;
                    432:     }
                    433:     for (i = 0; i < 40; i++)
                    434:         if (str[i] == 0)
                    435:             return;
                    436:         else if (IS_BLANK_CH(str[i]))
                    437:             fputc(' ', ctxt->output);
                    438:         else if (str[i] >= 0x80)
                    439:             fprintf(ctxt->output, "#%X", str[i]);
                    440:         else
                    441:             fputc(str[i], ctxt->output);
                    442:     fprintf(ctxt->output, "...");
                    443: }
                    444: 
                    445: static void
                    446: xmlCtxtDumpDtdNode(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
                    447: {
                    448:     xmlCtxtDumpSpaces(ctxt);
                    449: 
                    450:     if (dtd == NULL) {
                    451:         if (!ctxt->check)
                    452:             fprintf(ctxt->output, "DTD node is NULL\n");
                    453:         return;
                    454:     }
                    455: 
                    456:     if (dtd->type != XML_DTD_NODE) {
                    457:        xmlDebugErr(ctxt, XML_CHECK_NOT_DTD,
                    458:                    "Node is not a DTD");
                    459:         return;
                    460:     }
                    461:     if (!ctxt->check) {
                    462:         if (dtd->name != NULL)
                    463:             fprintf(ctxt->output, "DTD(%s)", (char *) dtd->name);
                    464:         else
                    465:             fprintf(ctxt->output, "DTD");
                    466:         if (dtd->ExternalID != NULL)
                    467:             fprintf(ctxt->output, ", PUBLIC %s", (char *) dtd->ExternalID);
                    468:         if (dtd->SystemID != NULL)
                    469:             fprintf(ctxt->output, ", SYSTEM %s", (char *) dtd->SystemID);
                    470:         fprintf(ctxt->output, "\n");
                    471:     }
                    472:     /*
                    473:      * Do a bit of checking
                    474:      */
                    475:     xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) dtd);
                    476: }
                    477: 
                    478: static void
                    479: xmlCtxtDumpAttrDecl(xmlDebugCtxtPtr ctxt, xmlAttributePtr attr)
                    480: {
                    481:     xmlCtxtDumpSpaces(ctxt);
                    482: 
                    483:     if (attr == NULL) {
                    484:         if (!ctxt->check)
                    485:             fprintf(ctxt->output, "Attribute declaration is NULL\n");
                    486:         return;
                    487:     }
                    488:     if (attr->type != XML_ATTRIBUTE_DECL) {
                    489:        xmlDebugErr(ctxt, XML_CHECK_NOT_ATTR_DECL,
                    490:                    "Node is not an attribute declaration");
                    491:         return;
                    492:     }
                    493:     if (attr->name != NULL) {
                    494:         if (!ctxt->check)
                    495:             fprintf(ctxt->output, "ATTRDECL(%s)", (char *) attr->name);
                    496:     } else
                    497:        xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
                    498:                    "Node attribute declaration has no name");
                    499:     if (attr->elem != NULL) {
                    500:         if (!ctxt->check)
                    501:             fprintf(ctxt->output, " for %s", (char *) attr->elem);
                    502:     } else
                    503:        xmlDebugErr(ctxt, XML_CHECK_NO_ELEM,
                    504:                    "Node attribute declaration has no element name");
                    505:     if (!ctxt->check) {
                    506:         switch (attr->atype) {
                    507:             case XML_ATTRIBUTE_CDATA:
                    508:                 fprintf(ctxt->output, " CDATA");
                    509:                 break;
                    510:             case XML_ATTRIBUTE_ID:
                    511:                 fprintf(ctxt->output, " ID");
                    512:                 break;
                    513:             case XML_ATTRIBUTE_IDREF:
                    514:                 fprintf(ctxt->output, " IDREF");
                    515:                 break;
                    516:             case XML_ATTRIBUTE_IDREFS:
                    517:                 fprintf(ctxt->output, " IDREFS");
                    518:                 break;
                    519:             case XML_ATTRIBUTE_ENTITY:
                    520:                 fprintf(ctxt->output, " ENTITY");
                    521:                 break;
                    522:             case XML_ATTRIBUTE_ENTITIES:
                    523:                 fprintf(ctxt->output, " ENTITIES");
                    524:                 break;
                    525:             case XML_ATTRIBUTE_NMTOKEN:
                    526:                 fprintf(ctxt->output, " NMTOKEN");
                    527:                 break;
                    528:             case XML_ATTRIBUTE_NMTOKENS:
                    529:                 fprintf(ctxt->output, " NMTOKENS");
                    530:                 break;
                    531:             case XML_ATTRIBUTE_ENUMERATION:
                    532:                 fprintf(ctxt->output, " ENUMERATION");
                    533:                 break;
                    534:             case XML_ATTRIBUTE_NOTATION:
                    535:                 fprintf(ctxt->output, " NOTATION ");
                    536:                 break;
                    537:         }
                    538:         if (attr->tree != NULL) {
                    539:             int indx;
                    540:             xmlEnumerationPtr cur = attr->tree;
                    541: 
                    542:             for (indx = 0; indx < 5; indx++) {
                    543:                 if (indx != 0)
                    544:                     fprintf(ctxt->output, "|%s", (char *) cur->name);
                    545:                 else
                    546:                     fprintf(ctxt->output, " (%s", (char *) cur->name);
                    547:                 cur = cur->next;
                    548:                 if (cur == NULL)
                    549:                     break;
                    550:             }
                    551:             if (cur == NULL)
                    552:                 fprintf(ctxt->output, ")");
                    553:             else
                    554:                 fprintf(ctxt->output, "...)");
                    555:         }
                    556:         switch (attr->def) {
                    557:             case XML_ATTRIBUTE_NONE:
                    558:                 break;
                    559:             case XML_ATTRIBUTE_REQUIRED:
                    560:                 fprintf(ctxt->output, " REQUIRED");
                    561:                 break;
                    562:             case XML_ATTRIBUTE_IMPLIED:
                    563:                 fprintf(ctxt->output, " IMPLIED");
                    564:                 break;
                    565:             case XML_ATTRIBUTE_FIXED:
                    566:                 fprintf(ctxt->output, " FIXED");
                    567:                 break;
                    568:         }
                    569:         if (attr->defaultValue != NULL) {
                    570:             fprintf(ctxt->output, "\"");
                    571:             xmlCtxtDumpString(ctxt, attr->defaultValue);
                    572:             fprintf(ctxt->output, "\"");
                    573:         }
                    574:         fprintf(ctxt->output, "\n");
                    575:     }
                    576: 
                    577:     /*
                    578:      * Do a bit of checking
                    579:      */
                    580:     xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
                    581: }
                    582: 
                    583: static void
                    584: xmlCtxtDumpElemDecl(xmlDebugCtxtPtr ctxt, xmlElementPtr elem)
                    585: {
                    586:     xmlCtxtDumpSpaces(ctxt);
                    587: 
                    588:     if (elem == NULL) {
                    589:         if (!ctxt->check)
                    590:             fprintf(ctxt->output, "Element declaration is NULL\n");
                    591:         return;
                    592:     }
                    593:     if (elem->type != XML_ELEMENT_DECL) {
                    594:        xmlDebugErr(ctxt, XML_CHECK_NOT_ELEM_DECL,
                    595:                    "Node is not an element declaration");
                    596:         return;
                    597:     }
                    598:     if (elem->name != NULL) {
                    599:         if (!ctxt->check) {
                    600:             fprintf(ctxt->output, "ELEMDECL(");
                    601:             xmlCtxtDumpString(ctxt, elem->name);
                    602:             fprintf(ctxt->output, ")");
                    603:         }
                    604:     } else
                    605:        xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
                    606:                    "Element declaration has no name");
                    607:     if (!ctxt->check) {
                    608:         switch (elem->etype) {
                    609:             case XML_ELEMENT_TYPE_UNDEFINED:
                    610:                 fprintf(ctxt->output, ", UNDEFINED");
                    611:                 break;
                    612:             case XML_ELEMENT_TYPE_EMPTY:
                    613:                 fprintf(ctxt->output, ", EMPTY");
                    614:                 break;
                    615:             case XML_ELEMENT_TYPE_ANY:
                    616:                 fprintf(ctxt->output, ", ANY");
                    617:                 break;
                    618:             case XML_ELEMENT_TYPE_MIXED:
                    619:                 fprintf(ctxt->output, ", MIXED ");
                    620:                 break;
                    621:             case XML_ELEMENT_TYPE_ELEMENT:
                    622:                 fprintf(ctxt->output, ", MIXED ");
                    623:                 break;
                    624:         }
                    625:         if ((elem->type != XML_ELEMENT_NODE) && (elem->content != NULL)) {
                    626:             char buf[5001];
                    627: 
                    628:             buf[0] = 0;
                    629:             xmlSnprintfElementContent(buf, 5000, elem->content, 1);
                    630:             buf[5000] = 0;
                    631:             fprintf(ctxt->output, "%s", buf);
                    632:         }
                    633:         fprintf(ctxt->output, "\n");
                    634:     }
                    635: 
                    636:     /*
                    637:      * Do a bit of checking
                    638:      */
                    639:     xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) elem);
                    640: }
                    641: 
                    642: static void
                    643: xmlCtxtDumpEntityDecl(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
                    644: {
                    645:     xmlCtxtDumpSpaces(ctxt);
                    646: 
                    647:     if (ent == NULL) {
                    648:         if (!ctxt->check)
                    649:             fprintf(ctxt->output, "Entity declaration is NULL\n");
                    650:         return;
                    651:     }
                    652:     if (ent->type != XML_ENTITY_DECL) {
                    653:        xmlDebugErr(ctxt, XML_CHECK_NOT_ENTITY_DECL,
                    654:                    "Node is not an entity declaration");
                    655:         return;
                    656:     }
                    657:     if (ent->name != NULL) {
                    658:         if (!ctxt->check) {
                    659:             fprintf(ctxt->output, "ENTITYDECL(");
                    660:             xmlCtxtDumpString(ctxt, ent->name);
                    661:             fprintf(ctxt->output, ")");
                    662:         }
                    663:     } else
                    664:        xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
                    665:                    "Entity declaration has no name");
                    666:     if (!ctxt->check) {
                    667:         switch (ent->etype) {
                    668:             case XML_INTERNAL_GENERAL_ENTITY:
                    669:                 fprintf(ctxt->output, ", internal\n");
                    670:                 break;
                    671:             case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                    672:                 fprintf(ctxt->output, ", external parsed\n");
                    673:                 break;
                    674:             case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                    675:                 fprintf(ctxt->output, ", unparsed\n");
                    676:                 break;
                    677:             case XML_INTERNAL_PARAMETER_ENTITY:
                    678:                 fprintf(ctxt->output, ", parameter\n");
                    679:                 break;
                    680:             case XML_EXTERNAL_PARAMETER_ENTITY:
                    681:                 fprintf(ctxt->output, ", external parameter\n");
                    682:                 break;
                    683:             case XML_INTERNAL_PREDEFINED_ENTITY:
                    684:                 fprintf(ctxt->output, ", predefined\n");
                    685:                 break;
                    686:         }
                    687:         if (ent->ExternalID) {
                    688:             xmlCtxtDumpSpaces(ctxt);
                    689:             fprintf(ctxt->output, " ExternalID=%s\n",
                    690:                     (char *) ent->ExternalID);
                    691:         }
                    692:         if (ent->SystemID) {
                    693:             xmlCtxtDumpSpaces(ctxt);
                    694:             fprintf(ctxt->output, " SystemID=%s\n",
                    695:                     (char *) ent->SystemID);
                    696:         }
                    697:         if (ent->URI != NULL) {
                    698:             xmlCtxtDumpSpaces(ctxt);
                    699:             fprintf(ctxt->output, " URI=%s\n", (char *) ent->URI);
                    700:         }
                    701:         if (ent->content) {
                    702:             xmlCtxtDumpSpaces(ctxt);
                    703:             fprintf(ctxt->output, " content=");
                    704:             xmlCtxtDumpString(ctxt, ent->content);
                    705:             fprintf(ctxt->output, "\n");
                    706:         }
                    707:     }
                    708: 
                    709:     /*
                    710:      * Do a bit of checking
                    711:      */
                    712:     xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) ent);
                    713: }
                    714: 
                    715: static void
                    716: xmlCtxtDumpNamespace(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
                    717: {
                    718:     xmlCtxtDumpSpaces(ctxt);
                    719: 
                    720:     if (ns == NULL) {
                    721:         if (!ctxt->check)
                    722:             fprintf(ctxt->output, "namespace node is NULL\n");
                    723:         return;
                    724:     }
                    725:     if (ns->type != XML_NAMESPACE_DECL) {
                    726:        xmlDebugErr(ctxt, XML_CHECK_NOT_NS_DECL,
                    727:                    "Node is not a namespace declaration");
                    728:         return;
                    729:     }
                    730:     if (ns->href == NULL) {
                    731:         if (ns->prefix != NULL)
                    732:            xmlDebugErr3(ctxt, XML_CHECK_NO_HREF,
                    733:                     "Incomplete namespace %s href=NULL\n",
                    734:                     (char *) ns->prefix);
                    735:         else
                    736:            xmlDebugErr(ctxt, XML_CHECK_NO_HREF,
                    737:                     "Incomplete default namespace href=NULL\n");
                    738:     } else {
                    739:         if (!ctxt->check) {
                    740:             if (ns->prefix != NULL)
                    741:                 fprintf(ctxt->output, "namespace %s href=",
                    742:                         (char *) ns->prefix);
                    743:             else
                    744:                 fprintf(ctxt->output, "default namespace href=");
                    745: 
                    746:             xmlCtxtDumpString(ctxt, ns->href);
                    747:             fprintf(ctxt->output, "\n");
                    748:         }
                    749:     }
                    750: }
                    751: 
                    752: static void
                    753: xmlCtxtDumpNamespaceList(xmlDebugCtxtPtr ctxt, xmlNsPtr ns)
                    754: {
                    755:     while (ns != NULL) {
                    756:         xmlCtxtDumpNamespace(ctxt, ns);
                    757:         ns = ns->next;
                    758:     }
                    759: }
                    760: 
                    761: static void
                    762: xmlCtxtDumpEntity(xmlDebugCtxtPtr ctxt, xmlEntityPtr ent)
                    763: {
                    764:     xmlCtxtDumpSpaces(ctxt);
                    765: 
                    766:     if (ent == NULL) {
                    767:         if (!ctxt->check)
                    768:             fprintf(ctxt->output, "Entity is NULL\n");
                    769:         return;
                    770:     }
                    771:     if (!ctxt->check) {
                    772:         switch (ent->etype) {
                    773:             case XML_INTERNAL_GENERAL_ENTITY:
                    774:                 fprintf(ctxt->output, "INTERNAL_GENERAL_ENTITY ");
                    775:                 break;
                    776:             case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                    777:                 fprintf(ctxt->output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
                    778:                 break;
                    779:             case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                    780:                 fprintf(ctxt->output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
                    781:                 break;
                    782:             case XML_INTERNAL_PARAMETER_ENTITY:
                    783:                 fprintf(ctxt->output, "INTERNAL_PARAMETER_ENTITY ");
                    784:                 break;
                    785:             case XML_EXTERNAL_PARAMETER_ENTITY:
                    786:                 fprintf(ctxt->output, "EXTERNAL_PARAMETER_ENTITY ");
                    787:                 break;
                    788:             default:
                    789:                 fprintf(ctxt->output, "ENTITY_%d ! ", (int) ent->etype);
                    790:         }
                    791:         fprintf(ctxt->output, "%s\n", ent->name);
                    792:         if (ent->ExternalID) {
                    793:             xmlCtxtDumpSpaces(ctxt);
                    794:             fprintf(ctxt->output, "ExternalID=%s\n",
                    795:                     (char *) ent->ExternalID);
                    796:         }
                    797:         if (ent->SystemID) {
                    798:             xmlCtxtDumpSpaces(ctxt);
                    799:             fprintf(ctxt->output, "SystemID=%s\n", (char *) ent->SystemID);
                    800:         }
                    801:         if (ent->URI) {
                    802:             xmlCtxtDumpSpaces(ctxt);
                    803:             fprintf(ctxt->output, "URI=%s\n", (char *) ent->URI);
                    804:         }
                    805:         if (ent->content) {
                    806:             xmlCtxtDumpSpaces(ctxt);
                    807:             fprintf(ctxt->output, "content=");
                    808:             xmlCtxtDumpString(ctxt, ent->content);
                    809:             fprintf(ctxt->output, "\n");
                    810:         }
                    811:     }
                    812: }
                    813: 
                    814: /**
                    815:  * xmlCtxtDumpAttr:
                    816:  * @output:  the FILE * for the output
                    817:  * @attr:  the attribute
                    818:  * @depth:  the indentation level.
                    819:  *
                    820:  * Dumps debug information for the attribute
                    821:  */
                    822: static void
                    823: xmlCtxtDumpAttr(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
                    824: {
                    825:     xmlCtxtDumpSpaces(ctxt);
                    826: 
                    827:     if (attr == NULL) {
                    828:         if (!ctxt->check)
                    829:             fprintf(ctxt->output, "Attr is NULL");
                    830:         return;
                    831:     }
                    832:     if (!ctxt->check) {
                    833:         fprintf(ctxt->output, "ATTRIBUTE ");
                    834:        xmlCtxtDumpString(ctxt, attr->name);
                    835:         fprintf(ctxt->output, "\n");
                    836:         if (attr->children != NULL) {
                    837:             ctxt->depth++;
                    838:             xmlCtxtDumpNodeList(ctxt, attr->children);
                    839:             ctxt->depth--;
                    840:         }
                    841:     }
                    842:     if (attr->name == NULL)
                    843:        xmlDebugErr(ctxt, XML_CHECK_NO_NAME,
                    844:                    "Attribute has no name");
                    845: 
                    846:     /*
                    847:      * Do a bit of checking
                    848:      */
                    849:     xmlCtxtGenericNodeCheck(ctxt, (xmlNodePtr) attr);
                    850: }
                    851: 
                    852: /**
                    853:  * xmlCtxtDumpAttrList:
                    854:  * @output:  the FILE * for the output
                    855:  * @attr:  the attribute list
                    856:  * @depth:  the indentation level.
                    857:  *
                    858:  * Dumps debug information for the attribute list
                    859:  */
                    860: static void
                    861: xmlCtxtDumpAttrList(xmlDebugCtxtPtr ctxt, xmlAttrPtr attr)
                    862: {
                    863:     while (attr != NULL) {
                    864:         xmlCtxtDumpAttr(ctxt, attr);
                    865:         attr = attr->next;
                    866:     }
                    867: }
                    868: 
                    869: /**
                    870:  * xmlCtxtDumpOneNode:
                    871:  * @output:  the FILE * for the output
                    872:  * @node:  the node
                    873:  * @depth:  the indentation level.
                    874:  *
                    875:  * Dumps debug information for the element node, it is not recursive
                    876:  */
                    877: static void
                    878: xmlCtxtDumpOneNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
                    879: {
                    880:     if (node == NULL) {
                    881:         if (!ctxt->check) {
                    882:             xmlCtxtDumpSpaces(ctxt);
                    883:             fprintf(ctxt->output, "node is NULL\n");
                    884:         }
                    885:         return;
                    886:     }
                    887:     ctxt->node = node;
                    888: 
                    889:     switch (node->type) {
                    890:         case XML_ELEMENT_NODE:
                    891:             if (!ctxt->check) {
                    892:                 xmlCtxtDumpSpaces(ctxt);
                    893:                 fprintf(ctxt->output, "ELEMENT ");
                    894:                 if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
                    895:                     xmlCtxtDumpString(ctxt, node->ns->prefix);
                    896:                     fprintf(ctxt->output, ":");
                    897:                 }
                    898:                 xmlCtxtDumpString(ctxt, node->name);
                    899:                 fprintf(ctxt->output, "\n");
                    900:             }
                    901:             break;
                    902:         case XML_ATTRIBUTE_NODE:
                    903:             if (!ctxt->check)
                    904:                 xmlCtxtDumpSpaces(ctxt);
                    905:             fprintf(ctxt->output, "Error, ATTRIBUTE found here\n");
                    906:             xmlCtxtGenericNodeCheck(ctxt, node);
                    907:             return;
                    908:         case XML_TEXT_NODE:
                    909:             if (!ctxt->check) {
                    910:                 xmlCtxtDumpSpaces(ctxt);
                    911:                 if (node->name == (const xmlChar *) xmlStringTextNoenc)
                    912:                     fprintf(ctxt->output, "TEXT no enc");
                    913:                 else
                    914:                     fprintf(ctxt->output, "TEXT");
                    915:                if (ctxt->options & DUMP_TEXT_TYPE) {
                    916:                    if (node->content == (xmlChar *) &(node->properties))
                    917:                        fprintf(ctxt->output, " compact\n");
                    918:                    else if (xmlDictOwns(ctxt->dict, node->content) == 1)
                    919:                        fprintf(ctxt->output, " interned\n");
                    920:                    else
                    921:                        fprintf(ctxt->output, "\n");
                    922:                } else
                    923:                    fprintf(ctxt->output, "\n");
                    924:             }
                    925:             break;
                    926:         case XML_CDATA_SECTION_NODE:
                    927:             if (!ctxt->check) {
                    928:                 xmlCtxtDumpSpaces(ctxt);
                    929:                 fprintf(ctxt->output, "CDATA_SECTION\n");
                    930:             }
                    931:             break;
                    932:         case XML_ENTITY_REF_NODE:
                    933:             if (!ctxt->check) {
                    934:                 xmlCtxtDumpSpaces(ctxt);
                    935:                 fprintf(ctxt->output, "ENTITY_REF(%s)\n",
                    936:                         (char *) node->name);
                    937:             }
                    938:             break;
                    939:         case XML_ENTITY_NODE:
                    940:             if (!ctxt->check) {
                    941:                 xmlCtxtDumpSpaces(ctxt);
                    942:                 fprintf(ctxt->output, "ENTITY\n");
                    943:             }
                    944:             break;
                    945:         case XML_PI_NODE:
                    946:             if (!ctxt->check) {
                    947:                 xmlCtxtDumpSpaces(ctxt);
                    948:                 fprintf(ctxt->output, "PI %s\n", (char *) node->name);
                    949:             }
                    950:             break;
                    951:         case XML_COMMENT_NODE:
                    952:             if (!ctxt->check) {
                    953:                 xmlCtxtDumpSpaces(ctxt);
                    954:                 fprintf(ctxt->output, "COMMENT\n");
                    955:             }
                    956:             break;
                    957:         case XML_DOCUMENT_NODE:
                    958:         case XML_HTML_DOCUMENT_NODE:
                    959:             if (!ctxt->check) {
                    960:                 xmlCtxtDumpSpaces(ctxt);
                    961:             }
                    962:             fprintf(ctxt->output, "Error, DOCUMENT found here\n");
                    963:             xmlCtxtGenericNodeCheck(ctxt, node);
                    964:             return;
                    965:         case XML_DOCUMENT_TYPE_NODE:
                    966:             if (!ctxt->check) {
                    967:                 xmlCtxtDumpSpaces(ctxt);
                    968:                 fprintf(ctxt->output, "DOCUMENT_TYPE\n");
                    969:             }
                    970:             break;
                    971:         case XML_DOCUMENT_FRAG_NODE:
                    972:             if (!ctxt->check) {
                    973:                 xmlCtxtDumpSpaces(ctxt);
                    974:                 fprintf(ctxt->output, "DOCUMENT_FRAG\n");
                    975:             }
                    976:             break;
                    977:         case XML_NOTATION_NODE:
                    978:             if (!ctxt->check) {
                    979:                 xmlCtxtDumpSpaces(ctxt);
                    980:                 fprintf(ctxt->output, "NOTATION\n");
                    981:             }
                    982:             break;
                    983:         case XML_DTD_NODE:
                    984:             xmlCtxtDumpDtdNode(ctxt, (xmlDtdPtr) node);
                    985:             return;
                    986:         case XML_ELEMENT_DECL:
                    987:             xmlCtxtDumpElemDecl(ctxt, (xmlElementPtr) node);
                    988:             return;
                    989:         case XML_ATTRIBUTE_DECL:
                    990:             xmlCtxtDumpAttrDecl(ctxt, (xmlAttributePtr) node);
                    991:             return;
                    992:         case XML_ENTITY_DECL:
                    993:             xmlCtxtDumpEntityDecl(ctxt, (xmlEntityPtr) node);
                    994:             return;
                    995:         case XML_NAMESPACE_DECL:
                    996:             xmlCtxtDumpNamespace(ctxt, (xmlNsPtr) node);
                    997:             return;
                    998:         case XML_XINCLUDE_START:
                    999:             if (!ctxt->check) {
                   1000:                 xmlCtxtDumpSpaces(ctxt);
                   1001:                 fprintf(ctxt->output, "INCLUDE START\n");
                   1002:             }
                   1003:             return;
                   1004:         case XML_XINCLUDE_END:
                   1005:             if (!ctxt->check) {
                   1006:                 xmlCtxtDumpSpaces(ctxt);
                   1007:                 fprintf(ctxt->output, "INCLUDE END\n");
                   1008:             }
                   1009:             return;
                   1010:         default:
                   1011:             if (!ctxt->check)
                   1012:                 xmlCtxtDumpSpaces(ctxt);
                   1013:            xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
                   1014:                        "Unknown node type %d\n", node->type);
                   1015:             return;
                   1016:     }
                   1017:     if (node->doc == NULL) {
                   1018:         if (!ctxt->check) {
                   1019:             xmlCtxtDumpSpaces(ctxt);
                   1020:         }
                   1021:         fprintf(ctxt->output, "PBM: doc == NULL !!!\n");
                   1022:     }
                   1023:     ctxt->depth++;
                   1024:     if ((node->type == XML_ELEMENT_NODE) && (node->nsDef != NULL))
                   1025:         xmlCtxtDumpNamespaceList(ctxt, node->nsDef);
                   1026:     if ((node->type == XML_ELEMENT_NODE) && (node->properties != NULL))
                   1027:         xmlCtxtDumpAttrList(ctxt, node->properties);
                   1028:     if (node->type != XML_ENTITY_REF_NODE) {
                   1029:         if ((node->type != XML_ELEMENT_NODE) && (node->content != NULL)) {
                   1030:             if (!ctxt->check) {
                   1031:                 xmlCtxtDumpSpaces(ctxt);
                   1032:                 fprintf(ctxt->output, "content=");
                   1033:                 xmlCtxtDumpString(ctxt, node->content);
                   1034:                 fprintf(ctxt->output, "\n");
                   1035:             }
                   1036:         }
                   1037:     } else {
                   1038:         xmlEntityPtr ent;
                   1039: 
                   1040:         ent = xmlGetDocEntity(node->doc, node->name);
                   1041:         if (ent != NULL)
                   1042:             xmlCtxtDumpEntity(ctxt, ent);
                   1043:     }
                   1044:     ctxt->depth--;
                   1045: 
                   1046:     /*
                   1047:      * Do a bit of checking
                   1048:      */
                   1049:     xmlCtxtGenericNodeCheck(ctxt, node);
                   1050: }
                   1051: 
                   1052: /**
                   1053:  * xmlCtxtDumpNode:
                   1054:  * @output:  the FILE * for the output
                   1055:  * @node:  the node
                   1056:  * @depth:  the indentation level.
                   1057:  *
                   1058:  * Dumps debug information for the element node, it is recursive
                   1059:  */
                   1060: static void
                   1061: xmlCtxtDumpNode(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
                   1062: {
                   1063:     if (node == NULL) {
                   1064:         if (!ctxt->check) {
                   1065:             xmlCtxtDumpSpaces(ctxt);
                   1066:             fprintf(ctxt->output, "node is NULL\n");
                   1067:         }
                   1068:         return;
                   1069:     }
                   1070:     xmlCtxtDumpOneNode(ctxt, node);
                   1071:     if ((node->type != XML_NAMESPACE_DECL) && 
                   1072:         (node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
                   1073:         ctxt->depth++;
                   1074:         xmlCtxtDumpNodeList(ctxt, node->children);
                   1075:         ctxt->depth--;
                   1076:     }
                   1077: }
                   1078: 
                   1079: /**
                   1080:  * xmlCtxtDumpNodeList:
                   1081:  * @output:  the FILE * for the output
                   1082:  * @node:  the node list
                   1083:  * @depth:  the indentation level.
                   1084:  *
                   1085:  * Dumps debug information for the list of element node, it is recursive
                   1086:  */
                   1087: static void
                   1088: xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node)
                   1089: {
                   1090:     while (node != NULL) {
                   1091:         xmlCtxtDumpNode(ctxt, node);
                   1092:         node = node->next;
                   1093:     }
                   1094: }
                   1095: 
                   1096: static void
                   1097: xmlCtxtDumpDocHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
                   1098: {
                   1099:     if (doc == NULL) {
                   1100:         if (!ctxt->check)
                   1101:             fprintf(ctxt->output, "DOCUMENT == NULL !\n");
                   1102:         return;
                   1103:     }
                   1104:     ctxt->node = (xmlNodePtr) doc;
                   1105: 
                   1106:     switch (doc->type) {
                   1107:         case XML_ELEMENT_NODE:
                   1108:            xmlDebugErr(ctxt, XML_CHECK_FOUND_ELEMENT,
                   1109:                        "Misplaced ELEMENT node\n");
                   1110:             break;
                   1111:         case XML_ATTRIBUTE_NODE:
                   1112:            xmlDebugErr(ctxt, XML_CHECK_FOUND_ATTRIBUTE,
                   1113:                        "Misplaced ATTRIBUTE node\n");
                   1114:             break;
                   1115:         case XML_TEXT_NODE:
                   1116:            xmlDebugErr(ctxt, XML_CHECK_FOUND_TEXT,
                   1117:                        "Misplaced TEXT node\n");
                   1118:             break;
                   1119:         case XML_CDATA_SECTION_NODE:
                   1120:            xmlDebugErr(ctxt, XML_CHECK_FOUND_CDATA,
                   1121:                        "Misplaced CDATA node\n");
                   1122:             break;
                   1123:         case XML_ENTITY_REF_NODE:
                   1124:            xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITYREF,
                   1125:                        "Misplaced ENTITYREF node\n");
                   1126:             break;
                   1127:         case XML_ENTITY_NODE:
                   1128:            xmlDebugErr(ctxt, XML_CHECK_FOUND_ENTITY,
                   1129:                        "Misplaced ENTITY node\n");
                   1130:             break;
                   1131:         case XML_PI_NODE:
                   1132:            xmlDebugErr(ctxt, XML_CHECK_FOUND_PI,
                   1133:                        "Misplaced PI node\n");
                   1134:             break;
                   1135:         case XML_COMMENT_NODE:
                   1136:            xmlDebugErr(ctxt, XML_CHECK_FOUND_COMMENT,
                   1137:                        "Misplaced COMMENT node\n");
                   1138:             break;
                   1139:         case XML_DOCUMENT_NODE:
                   1140:            if (!ctxt->check)
                   1141:                fprintf(ctxt->output, "DOCUMENT\n");
                   1142:             break;
                   1143:         case XML_HTML_DOCUMENT_NODE:
                   1144:            if (!ctxt->check)
                   1145:                fprintf(ctxt->output, "HTML DOCUMENT\n");
                   1146:             break;
                   1147:         case XML_DOCUMENT_TYPE_NODE:
                   1148:            xmlDebugErr(ctxt, XML_CHECK_FOUND_DOCTYPE,
                   1149:                        "Misplaced DOCTYPE node\n");
                   1150:             break;
                   1151:         case XML_DOCUMENT_FRAG_NODE:
                   1152:            xmlDebugErr(ctxt, XML_CHECK_FOUND_FRAGMENT,
                   1153:                        "Misplaced FRAGMENT node\n");
                   1154:             break;
                   1155:         case XML_NOTATION_NODE:
                   1156:            xmlDebugErr(ctxt, XML_CHECK_FOUND_NOTATION,
                   1157:                        "Misplaced NOTATION node\n");
                   1158:             break;
                   1159:         default:
                   1160:            xmlDebugErr2(ctxt, XML_CHECK_UNKNOWN_NODE,
                   1161:                        "Unknown node type %d\n", doc->type);
                   1162:     }
                   1163: }
                   1164: 
                   1165: /**
                   1166:  * xmlCtxtDumpDocumentHead:
                   1167:  * @output:  the FILE * for the output
                   1168:  * @doc:  the document
                   1169:  *
                   1170:  * Dumps debug information cncerning the document, not recursive
                   1171:  */
                   1172: static void
                   1173: xmlCtxtDumpDocumentHead(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
                   1174: {
                   1175:     if (doc == NULL) return;
                   1176:     xmlCtxtDumpDocHead(ctxt, doc);
                   1177:     if (!ctxt->check) {
                   1178:         if (doc->name != NULL) {
                   1179:             fprintf(ctxt->output, "name=");
                   1180:             xmlCtxtDumpString(ctxt, BAD_CAST doc->name);
                   1181:             fprintf(ctxt->output, "\n");
                   1182:         }
                   1183:         if (doc->version != NULL) {
                   1184:             fprintf(ctxt->output, "version=");
                   1185:             xmlCtxtDumpString(ctxt, doc->version);
                   1186:             fprintf(ctxt->output, "\n");
                   1187:         }
                   1188:         if (doc->encoding != NULL) {
                   1189:             fprintf(ctxt->output, "encoding=");
                   1190:             xmlCtxtDumpString(ctxt, doc->encoding);
                   1191:             fprintf(ctxt->output, "\n");
                   1192:         }
                   1193:         if (doc->URL != NULL) {
                   1194:             fprintf(ctxt->output, "URL=");
                   1195:             xmlCtxtDumpString(ctxt, doc->URL);
                   1196:             fprintf(ctxt->output, "\n");
                   1197:         }
                   1198:         if (doc->standalone)
                   1199:             fprintf(ctxt->output, "standalone=true\n");
                   1200:     }
                   1201:     if (doc->oldNs != NULL)
                   1202:         xmlCtxtDumpNamespaceList(ctxt, doc->oldNs);
                   1203: }
                   1204: 
                   1205: /**
                   1206:  * xmlCtxtDumpDocument:
                   1207:  * @output:  the FILE * for the output
                   1208:  * @doc:  the document
                   1209:  *
                   1210:  * Dumps debug information for the document, it's recursive
                   1211:  */
                   1212: static void
                   1213: xmlCtxtDumpDocument(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
                   1214: {
                   1215:     if (doc == NULL) {
                   1216:         if (!ctxt->check)
                   1217:             fprintf(ctxt->output, "DOCUMENT == NULL !\n");
                   1218:         return;
                   1219:     }
                   1220:     xmlCtxtDumpDocumentHead(ctxt, doc);
                   1221:     if (((doc->type == XML_DOCUMENT_NODE) ||
                   1222:          (doc->type == XML_HTML_DOCUMENT_NODE))
                   1223:         && (doc->children != NULL)) {
                   1224:         ctxt->depth++;
                   1225:         xmlCtxtDumpNodeList(ctxt, doc->children);
                   1226:         ctxt->depth--;
                   1227:     }
                   1228: }
                   1229: 
                   1230: static void
                   1231: xmlCtxtDumpEntityCallback(xmlEntityPtr cur, xmlDebugCtxtPtr ctxt)
                   1232: {
                   1233:     if (cur == NULL) {
                   1234:         if (!ctxt->check)
                   1235:             fprintf(ctxt->output, "Entity is NULL");
                   1236:         return;
                   1237:     }
                   1238:     if (!ctxt->check) {
                   1239:         fprintf(ctxt->output, "%s : ", (char *) cur->name);
                   1240:         switch (cur->etype) {
                   1241:             case XML_INTERNAL_GENERAL_ENTITY:
                   1242:                 fprintf(ctxt->output, "INTERNAL GENERAL, ");
                   1243:                 break;
                   1244:             case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                   1245:                 fprintf(ctxt->output, "EXTERNAL PARSED, ");
                   1246:                 break;
                   1247:             case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                   1248:                 fprintf(ctxt->output, "EXTERNAL UNPARSED, ");
                   1249:                 break;
                   1250:             case XML_INTERNAL_PARAMETER_ENTITY:
                   1251:                 fprintf(ctxt->output, "INTERNAL PARAMETER, ");
                   1252:                 break;
                   1253:             case XML_EXTERNAL_PARAMETER_ENTITY:
                   1254:                 fprintf(ctxt->output, "EXTERNAL PARAMETER, ");
                   1255:                 break;
                   1256:             default:
                   1257:                xmlDebugErr2(ctxt, XML_CHECK_ENTITY_TYPE,
                   1258:                             "Unknown entity type %d\n", cur->etype);
                   1259:         }
                   1260:         if (cur->ExternalID != NULL)
                   1261:             fprintf(ctxt->output, "ID \"%s\"", (char *) cur->ExternalID);
                   1262:         if (cur->SystemID != NULL)
                   1263:             fprintf(ctxt->output, "SYSTEM \"%s\"", (char *) cur->SystemID);
                   1264:         if (cur->orig != NULL)
                   1265:             fprintf(ctxt->output, "\n orig \"%s\"", (char *) cur->orig);
                   1266:         if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL))
                   1267:             fprintf(ctxt->output, "\n content \"%s\"",
                   1268:                     (char *) cur->content);
                   1269:         fprintf(ctxt->output, "\n");
                   1270:     }
                   1271: }
                   1272: 
                   1273: /**
                   1274:  * xmlCtxtDumpEntities:
                   1275:  * @output:  the FILE * for the output
                   1276:  * @doc:  the document
                   1277:  *
                   1278:  * Dumps debug information for all the entities in use by the document
                   1279:  */
                   1280: static void
                   1281: xmlCtxtDumpEntities(xmlDebugCtxtPtr ctxt, xmlDocPtr doc)
                   1282: {
                   1283:     if (doc == NULL) return;
                   1284:     xmlCtxtDumpDocHead(ctxt, doc);
                   1285:     if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
                   1286:         xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
                   1287:             doc->intSubset->entities;
                   1288: 
                   1289:         if (!ctxt->check)
                   1290:             fprintf(ctxt->output, "Entities in internal subset\n");
                   1291:         xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback,
                   1292:                     ctxt);
                   1293:     } else
                   1294:         fprintf(ctxt->output, "No entities in internal subset\n");
                   1295:     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
                   1296:         xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
                   1297:             doc->extSubset->entities;
                   1298: 
                   1299:         if (!ctxt->check)
                   1300:             fprintf(ctxt->output, "Entities in external subset\n");
                   1301:         xmlHashScan(table, (xmlHashScanner) xmlCtxtDumpEntityCallback,
                   1302:                     ctxt);
                   1303:     } else if (!ctxt->check)
                   1304:         fprintf(ctxt->output, "No entities in external subset\n");
                   1305: }
                   1306: 
                   1307: /**
                   1308:  * xmlCtxtDumpDTD:
                   1309:  * @output:  the FILE * for the output
                   1310:  * @dtd:  the DTD
                   1311:  *
                   1312:  * Dumps debug information for the DTD
                   1313:  */
                   1314: static void
                   1315: xmlCtxtDumpDTD(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
                   1316: {
                   1317:     if (dtd == NULL) {
                   1318:         if (!ctxt->check)
                   1319:             fprintf(ctxt->output, "DTD is NULL\n");
                   1320:         return;
                   1321:     }
                   1322:     xmlCtxtDumpDtdNode(ctxt, dtd);
                   1323:     if (dtd->children == NULL)
                   1324:         fprintf(ctxt->output, "    DTD is empty\n");
                   1325:     else {
                   1326:         ctxt->depth++;
                   1327:         xmlCtxtDumpNodeList(ctxt, dtd->children);
                   1328:         ctxt->depth--;
                   1329:     }
                   1330: }
                   1331: 
                   1332: /************************************************************************
                   1333:  *                                                                     *
                   1334:  *                     Public entry points for dump                    *
                   1335:  *                                                                     *
                   1336:  ************************************************************************/
                   1337: 
                   1338: /**
                   1339:  * xmlDebugDumpString:
                   1340:  * @output:  the FILE * for the output
                   1341:  * @str:  the string
                   1342:  *
                   1343:  * Dumps informations about the string, shorten it if necessary
                   1344:  */
                   1345: void
                   1346: xmlDebugDumpString(FILE * output, const xmlChar * str)
                   1347: {
                   1348:     int i;
                   1349: 
                   1350:     if (output == NULL)
                   1351:        output = stdout;
                   1352:     if (str == NULL) {
                   1353:         fprintf(output, "(NULL)");
                   1354:         return;
                   1355:     }
                   1356:     for (i = 0; i < 40; i++)
                   1357:         if (str[i] == 0)
                   1358:             return;
                   1359:         else if (IS_BLANK_CH(str[i]))
                   1360:             fputc(' ', output);
                   1361:         else if (str[i] >= 0x80)
                   1362:             fprintf(output, "#%X", str[i]);
                   1363:         else
                   1364:             fputc(str[i], output);
                   1365:     fprintf(output, "...");
                   1366: }
                   1367: 
                   1368: /**
                   1369:  * xmlDebugDumpAttr:
                   1370:  * @output:  the FILE * for the output
                   1371:  * @attr:  the attribute
                   1372:  * @depth:  the indentation level.
                   1373:  *
                   1374:  * Dumps debug information for the attribute
                   1375:  */
                   1376: void
                   1377: xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
                   1378:     xmlDebugCtxt ctxt;
                   1379: 
                   1380:     if (output == NULL) return;
                   1381:     xmlCtxtDumpInitCtxt(&ctxt);
                   1382:     ctxt.output = output;
                   1383:     ctxt.depth = depth;
                   1384:     xmlCtxtDumpAttr(&ctxt, attr);
                   1385:     xmlCtxtDumpCleanCtxt(&ctxt);
                   1386: }
                   1387: 
                   1388: 
                   1389: /**
                   1390:  * xmlDebugDumpEntities:
                   1391:  * @output:  the FILE * for the output
                   1392:  * @doc:  the document
                   1393:  *
                   1394:  * Dumps debug information for all the entities in use by the document
                   1395:  */
                   1396: void
                   1397: xmlDebugDumpEntities(FILE * output, xmlDocPtr doc)
                   1398: {
                   1399:     xmlDebugCtxt ctxt;
                   1400: 
                   1401:     if (output == NULL) return;
                   1402:     xmlCtxtDumpInitCtxt(&ctxt);
                   1403:     ctxt.output = output;
                   1404:     xmlCtxtDumpEntities(&ctxt, doc);
                   1405:     xmlCtxtDumpCleanCtxt(&ctxt);
                   1406: }
                   1407: 
                   1408: /**
                   1409:  * xmlDebugDumpAttrList:
                   1410:  * @output:  the FILE * for the output
                   1411:  * @attr:  the attribute list
                   1412:  * @depth:  the indentation level.
                   1413:  *
                   1414:  * Dumps debug information for the attribute list
                   1415:  */
                   1416: void
                   1417: xmlDebugDumpAttrList(FILE * output, xmlAttrPtr attr, int depth)
                   1418: {
                   1419:     xmlDebugCtxt ctxt;
                   1420: 
                   1421:     if (output == NULL) return;
                   1422:     xmlCtxtDumpInitCtxt(&ctxt);
                   1423:     ctxt.output = output;
                   1424:     ctxt.depth = depth;
                   1425:     xmlCtxtDumpAttrList(&ctxt, attr);
                   1426:     xmlCtxtDumpCleanCtxt(&ctxt);
                   1427: }
                   1428: 
                   1429: /**
                   1430:  * xmlDebugDumpOneNode:
                   1431:  * @output:  the FILE * for the output
                   1432:  * @node:  the node
                   1433:  * @depth:  the indentation level.
                   1434:  *
                   1435:  * Dumps debug information for the element node, it is not recursive
                   1436:  */
                   1437: void
                   1438: xmlDebugDumpOneNode(FILE * output, xmlNodePtr node, int depth)
                   1439: {
                   1440:     xmlDebugCtxt ctxt;
                   1441: 
                   1442:     if (output == NULL) return;
                   1443:     xmlCtxtDumpInitCtxt(&ctxt);
                   1444:     ctxt.output = output;
                   1445:     ctxt.depth = depth;
                   1446:     xmlCtxtDumpOneNode(&ctxt, node);
                   1447:     xmlCtxtDumpCleanCtxt(&ctxt);
                   1448: }
                   1449: 
                   1450: /**
                   1451:  * xmlDebugDumpNode:
                   1452:  * @output:  the FILE * for the output
                   1453:  * @node:  the node
                   1454:  * @depth:  the indentation level.
                   1455:  *
                   1456:  * Dumps debug information for the element node, it is recursive
                   1457:  */
                   1458: void
                   1459: xmlDebugDumpNode(FILE * output, xmlNodePtr node, int depth)
                   1460: {
                   1461:     xmlDebugCtxt ctxt;
                   1462: 
                   1463:     if (output == NULL)
                   1464:        output = stdout;
                   1465:     xmlCtxtDumpInitCtxt(&ctxt);
                   1466:     ctxt.output = output;
                   1467:     ctxt.depth = depth;
                   1468:     xmlCtxtDumpNode(&ctxt, node);
                   1469:     xmlCtxtDumpCleanCtxt(&ctxt);
                   1470: }
                   1471: 
                   1472: /**
                   1473:  * xmlDebugDumpNodeList:
                   1474:  * @output:  the FILE * for the output
                   1475:  * @node:  the node list
                   1476:  * @depth:  the indentation level.
                   1477:  *
                   1478:  * Dumps debug information for the list of element node, it is recursive
                   1479:  */
                   1480: void
                   1481: xmlDebugDumpNodeList(FILE * output, xmlNodePtr node, int depth)
                   1482: {
                   1483:     xmlDebugCtxt ctxt;
                   1484: 
                   1485:     if (output == NULL)
                   1486:        output = stdout;
                   1487:     xmlCtxtDumpInitCtxt(&ctxt);
                   1488:     ctxt.output = output;
                   1489:     ctxt.depth = depth;
                   1490:     xmlCtxtDumpNodeList(&ctxt, node);
                   1491:     xmlCtxtDumpCleanCtxt(&ctxt);
                   1492: }
                   1493: 
                   1494: /**
                   1495:  * xmlDebugDumpDocumentHead:
                   1496:  * @output:  the FILE * for the output
                   1497:  * @doc:  the document
                   1498:  *
                   1499:  * Dumps debug information cncerning the document, not recursive
                   1500:  */
                   1501: void
                   1502: xmlDebugDumpDocumentHead(FILE * output, xmlDocPtr doc)
                   1503: {
                   1504:     xmlDebugCtxt ctxt;
                   1505: 
                   1506:     if (output == NULL)
                   1507:        output = stdout;
                   1508:     xmlCtxtDumpInitCtxt(&ctxt);
                   1509:     ctxt.options |= DUMP_TEXT_TYPE;
                   1510:     ctxt.output = output;
                   1511:     xmlCtxtDumpDocumentHead(&ctxt, doc);
                   1512:     xmlCtxtDumpCleanCtxt(&ctxt);
                   1513: }
                   1514: 
                   1515: /**
                   1516:  * xmlDebugDumpDocument:
                   1517:  * @output:  the FILE * for the output
                   1518:  * @doc:  the document
                   1519:  *
                   1520:  * Dumps debug information for the document, it's recursive
                   1521:  */
                   1522: void
                   1523: xmlDebugDumpDocument(FILE * output, xmlDocPtr doc)
                   1524: {
                   1525:     xmlDebugCtxt ctxt;
                   1526: 
                   1527:     if (output == NULL)
                   1528:        output = stdout;
                   1529:     xmlCtxtDumpInitCtxt(&ctxt);
                   1530:     ctxt.options |= DUMP_TEXT_TYPE;
                   1531:     ctxt.output = output;
                   1532:     xmlCtxtDumpDocument(&ctxt, doc);
                   1533:     xmlCtxtDumpCleanCtxt(&ctxt);
                   1534: }
                   1535: 
                   1536: /**
                   1537:  * xmlDebugDumpDTD:
                   1538:  * @output:  the FILE * for the output
                   1539:  * @dtd:  the DTD
                   1540:  *
                   1541:  * Dumps debug information for the DTD
                   1542:  */
                   1543: void
                   1544: xmlDebugDumpDTD(FILE * output, xmlDtdPtr dtd)
                   1545: {
                   1546:     xmlDebugCtxt ctxt;
                   1547: 
                   1548:     if (output == NULL)
                   1549:        output = stdout;
                   1550:     xmlCtxtDumpInitCtxt(&ctxt);
                   1551:     ctxt.options |= DUMP_TEXT_TYPE;
                   1552:     ctxt.output = output;
                   1553:     xmlCtxtDumpDTD(&ctxt, dtd);
                   1554:     xmlCtxtDumpCleanCtxt(&ctxt);
                   1555: }
                   1556: 
                   1557: /************************************************************************
                   1558:  *                                                                     *
                   1559:  *                     Public entry points for checkings               *
                   1560:  *                                                                     *
                   1561:  ************************************************************************/
                   1562: 
                   1563: /**
                   1564:  * xmlDebugCheckDocument:
                   1565:  * @output:  the FILE * for the output
                   1566:  * @doc:  the document
                   1567:  *
                   1568:  * Check the document for potential content problems, and output
                   1569:  * the errors to @output
                   1570:  *
                   1571:  * Returns the number of errors found
                   1572:  */
                   1573: int
                   1574: xmlDebugCheckDocument(FILE * output, xmlDocPtr doc)
                   1575: {
                   1576:     xmlDebugCtxt ctxt;
                   1577: 
                   1578:     if (output == NULL)
                   1579:        output = stdout;
                   1580:     xmlCtxtDumpInitCtxt(&ctxt);
                   1581:     ctxt.output = output;
                   1582:     ctxt.check = 1;
                   1583:     xmlCtxtDumpDocument(&ctxt, doc);
                   1584:     xmlCtxtDumpCleanCtxt(&ctxt);
                   1585:     return(ctxt.errors);
                   1586: }
                   1587: 
                   1588: /************************************************************************
                   1589:  *                                                                     *
                   1590:  *                     Helpers for Shell                               *
                   1591:  *                                                                     *
                   1592:  ************************************************************************/
                   1593: 
                   1594: /**
                   1595:  * xmlLsCountNode:
                   1596:  * @node:  the node to count
                   1597:  *
                   1598:  * Count the children of @node.
                   1599:  *
                   1600:  * Returns the number of children of @node.
                   1601:  */
                   1602: int
                   1603: xmlLsCountNode(xmlNodePtr node) {
                   1604:     int ret = 0;
                   1605:     xmlNodePtr list = NULL;
                   1606:     
                   1607:     if (node == NULL)
                   1608:        return(0);
                   1609: 
                   1610:     switch (node->type) {
                   1611:        case XML_ELEMENT_NODE:
                   1612:            list = node->children;
                   1613:            break;
                   1614:        case XML_DOCUMENT_NODE:
                   1615:        case XML_HTML_DOCUMENT_NODE:
                   1616: #ifdef LIBXML_DOCB_ENABLED
                   1617:        case XML_DOCB_DOCUMENT_NODE:
                   1618: #endif
                   1619:            list = ((xmlDocPtr) node)->children;
                   1620:            break;
                   1621:        case XML_ATTRIBUTE_NODE:
                   1622:            list = ((xmlAttrPtr) node)->children;
                   1623:            break;
                   1624:        case XML_TEXT_NODE:
                   1625:        case XML_CDATA_SECTION_NODE:
                   1626:        case XML_PI_NODE:
                   1627:        case XML_COMMENT_NODE:
                   1628:            if (node->content != NULL) {
                   1629:                ret = xmlStrlen(node->content);
                   1630:             }
                   1631:            break;
                   1632:        case XML_ENTITY_REF_NODE:
                   1633:        case XML_DOCUMENT_TYPE_NODE:
                   1634:        case XML_ENTITY_NODE:
                   1635:        case XML_DOCUMENT_FRAG_NODE:
                   1636:        case XML_NOTATION_NODE:
                   1637:        case XML_DTD_NODE:
                   1638:         case XML_ELEMENT_DECL:
                   1639:         case XML_ATTRIBUTE_DECL:
                   1640:         case XML_ENTITY_DECL:
                   1641:        case XML_NAMESPACE_DECL:
                   1642:        case XML_XINCLUDE_START:
                   1643:        case XML_XINCLUDE_END:
                   1644:            ret = 1;
                   1645:            break;
                   1646:     }
                   1647:     for (;list != NULL;ret++) 
                   1648:         list = list->next;
                   1649:     return(ret);
                   1650: }
                   1651: 
                   1652: /**
                   1653:  * xmlLsOneNode:
                   1654:  * @output:  the FILE * for the output
                   1655:  * @node:  the node to dump
                   1656:  *
                   1657:  * Dump to @output the type and name of @node.
                   1658:  */
                   1659: void
                   1660: xmlLsOneNode(FILE *output, xmlNodePtr node) {
                   1661:     if (output == NULL) return;
                   1662:     if (node == NULL) {
                   1663:        fprintf(output, "NULL\n");
                   1664:        return;
                   1665:     }
                   1666:     switch (node->type) {
                   1667:        case XML_ELEMENT_NODE:
                   1668:            fprintf(output, "-");
                   1669:            break;
                   1670:        case XML_ATTRIBUTE_NODE:
                   1671:            fprintf(output, "a");
                   1672:            break;
                   1673:        case XML_TEXT_NODE:
                   1674:            fprintf(output, "t");
                   1675:            break;
                   1676:        case XML_CDATA_SECTION_NODE:
                   1677:            fprintf(output, "C");
                   1678:            break;
                   1679:        case XML_ENTITY_REF_NODE:
                   1680:            fprintf(output, "e");
                   1681:            break;
                   1682:        case XML_ENTITY_NODE:
                   1683:            fprintf(output, "E");
                   1684:            break;
                   1685:        case XML_PI_NODE:
                   1686:            fprintf(output, "p");
                   1687:            break;
                   1688:        case XML_COMMENT_NODE:
                   1689:            fprintf(output, "c");
                   1690:            break;
                   1691:        case XML_DOCUMENT_NODE:
                   1692:            fprintf(output, "d");
                   1693:            break;
                   1694:        case XML_HTML_DOCUMENT_NODE:
                   1695:            fprintf(output, "h");
                   1696:            break;
                   1697:        case XML_DOCUMENT_TYPE_NODE:
                   1698:            fprintf(output, "T");
                   1699:            break;
                   1700:        case XML_DOCUMENT_FRAG_NODE:
                   1701:            fprintf(output, "F");
                   1702:            break;
                   1703:        case XML_NOTATION_NODE:
                   1704:            fprintf(output, "N");
                   1705:            break;
                   1706:        case XML_NAMESPACE_DECL:
                   1707:            fprintf(output, "n");
                   1708:            break;
                   1709:        default:
                   1710:            fprintf(output, "?");
                   1711:     }
                   1712:     if (node->type != XML_NAMESPACE_DECL) {
                   1713:        if (node->properties != NULL)
                   1714:            fprintf(output, "a");
                   1715:        else    
                   1716:            fprintf(output, "-");
                   1717:        if (node->nsDef != NULL) 
                   1718:            fprintf(output, "n");
                   1719:        else    
                   1720:            fprintf(output, "-");
                   1721:     }
                   1722: 
                   1723:     fprintf(output, " %8d ", xmlLsCountNode(node));
                   1724: 
                   1725:     switch (node->type) {
                   1726:        case XML_ELEMENT_NODE:
                   1727:            if (node->name != NULL)
                   1728:                fprintf(output, "%s", (const char *) node->name);
                   1729:            break;
                   1730:        case XML_ATTRIBUTE_NODE:
                   1731:            if (node->name != NULL)
                   1732:                fprintf(output, "%s", (const char *) node->name);
                   1733:            break;
                   1734:        case XML_TEXT_NODE:
                   1735:            if (node->content != NULL) {
                   1736:                xmlDebugDumpString(output, node->content);
                   1737:             }
                   1738:            break;
                   1739:        case XML_CDATA_SECTION_NODE:
                   1740:            break;
                   1741:        case XML_ENTITY_REF_NODE:
                   1742:            if (node->name != NULL)
                   1743:                fprintf(output, "%s", (const char *) node->name);
                   1744:            break;
                   1745:        case XML_ENTITY_NODE:
                   1746:            if (node->name != NULL)
                   1747:                fprintf(output, "%s", (const char *) node->name);
                   1748:            break;
                   1749:        case XML_PI_NODE:
                   1750:            if (node->name != NULL)
                   1751:                fprintf(output, "%s", (const char *) node->name);
                   1752:            break;
                   1753:        case XML_COMMENT_NODE:
                   1754:            break;
                   1755:        case XML_DOCUMENT_NODE:
                   1756:            break;
                   1757:        case XML_HTML_DOCUMENT_NODE:
                   1758:            break;
                   1759:        case XML_DOCUMENT_TYPE_NODE:
                   1760:            break;
                   1761:        case XML_DOCUMENT_FRAG_NODE:
                   1762:            break;
                   1763:        case XML_NOTATION_NODE:
                   1764:            break;
                   1765:        case XML_NAMESPACE_DECL: {
                   1766:            xmlNsPtr ns = (xmlNsPtr) node;
                   1767: 
                   1768:            if (ns->prefix == NULL)
                   1769:                fprintf(output, "default -> %s", (char *)ns->href);
                   1770:            else
                   1771:                fprintf(output, "%s -> %s", (char *)ns->prefix,
                   1772:                        (char *)ns->href);
                   1773:            break;
                   1774:        }
                   1775:        default:
                   1776:            if (node->name != NULL)
                   1777:                fprintf(output, "%s", (const char *) node->name);
                   1778:     }
                   1779:     fprintf(output, "\n");
                   1780: }
                   1781: 
                   1782: /**
                   1783:  * xmlBoolToText:
                   1784:  * @boolval: a bool to turn into text
                   1785:  *
                   1786:  * Convenient way to turn bool into text 
                   1787:  *
                   1788:  * Returns a pointer to either "True" or "False"
                   1789:  */
                   1790: const char *
                   1791: xmlBoolToText(int boolval)
                   1792: {
                   1793:     if (boolval)
                   1794:         return("True");
                   1795:     else
                   1796:         return("False");
                   1797: }
                   1798: 
                   1799: #ifdef LIBXML_XPATH_ENABLED
                   1800: /****************************************************************
                   1801:  *                                                             *
                   1802:  *             The XML shell related functions                 *
                   1803:  *                                                             *
                   1804:  ****************************************************************/
                   1805: 
                   1806: 
                   1807: 
                   1808: /*
                   1809:  * TODO: Improvement/cleanups for the XML shell
                   1810:  *     - allow to shell out an editor on a subpart
                   1811:  *     - cleanup function registrations (with help) and calling
                   1812:  *     - provide registration routines
                   1813:  */
                   1814: 
                   1815: /**
                   1816:  * xmlShellPrintXPathError:
                   1817:  * @errorType: valid xpath error id
                   1818:  * @arg: the argument that cause xpath to fail
                   1819:  *
                   1820:  * Print the xpath error to libxml default error channel
                   1821:  */
                   1822: void
                   1823: xmlShellPrintXPathError(int errorType, const char *arg)
                   1824: {
                   1825:     const char *default_arg = "Result";
                   1826: 
                   1827:     if (!arg)
                   1828:         arg = default_arg;
                   1829: 
                   1830:     switch (errorType) {
                   1831:         case XPATH_UNDEFINED:
                   1832:             xmlGenericError(xmlGenericErrorContext,
                   1833:                             "%s: no such node\n", arg);
                   1834:             break;
                   1835: 
                   1836:         case XPATH_BOOLEAN:
                   1837:             xmlGenericError(xmlGenericErrorContext,
                   1838:                             "%s is a Boolean\n", arg);
                   1839:             break;
                   1840:         case XPATH_NUMBER:
                   1841:             xmlGenericError(xmlGenericErrorContext,
                   1842:                             "%s is a number\n", arg);
                   1843:             break;
                   1844:         case XPATH_STRING:
                   1845:             xmlGenericError(xmlGenericErrorContext,
                   1846:                             "%s is a string\n", arg);
                   1847:             break;
                   1848:         case XPATH_POINT:
                   1849:             xmlGenericError(xmlGenericErrorContext,
                   1850:                             "%s is a point\n", arg);
                   1851:             break;
                   1852:         case XPATH_RANGE:
                   1853:             xmlGenericError(xmlGenericErrorContext,
                   1854:                             "%s is a range\n", arg);
                   1855:             break;
                   1856:         case XPATH_LOCATIONSET:
                   1857:             xmlGenericError(xmlGenericErrorContext,
                   1858:                             "%s is a range\n", arg);
                   1859:             break;
                   1860:         case XPATH_USERS:
                   1861:             xmlGenericError(xmlGenericErrorContext,
                   1862:                             "%s is user-defined\n", arg);
                   1863:             break;
                   1864:         case XPATH_XSLT_TREE:
                   1865:             xmlGenericError(xmlGenericErrorContext,
                   1866:                             "%s is an XSLT value tree\n", arg);
                   1867:             break;
                   1868:     }
                   1869: #if 0
                   1870:     xmlGenericError(xmlGenericErrorContext,
                   1871:                     "Try casting the result string function (xpath builtin)\n",
                   1872:                     arg);
                   1873: #endif
                   1874: }
                   1875: 
                   1876: 
                   1877: #ifdef LIBXML_OUTPUT_ENABLED
                   1878: /**
                   1879:  * xmlShellPrintNodeCtxt:
                   1880:  * @ctxt : a non-null shell context
                   1881:  * @node : a non-null node to print to the output FILE
                   1882:  *
                   1883:  * Print node to the output FILE
                   1884:  */
                   1885: static void
                   1886: xmlShellPrintNodeCtxt(xmlShellCtxtPtr ctxt,xmlNodePtr node)
                   1887: {
                   1888:     FILE *fp;
                   1889: 
                   1890:     if (!node)
                   1891:         return;
                   1892:     if (ctxt == NULL)
                   1893:        fp = stdout;
                   1894:     else
                   1895:        fp = ctxt->output;
                   1896: 
                   1897:     if (node->type == XML_DOCUMENT_NODE)
                   1898:         xmlDocDump(fp, (xmlDocPtr) node);
                   1899:     else if (node->type == XML_ATTRIBUTE_NODE)
                   1900:         xmlDebugDumpAttrList(fp, (xmlAttrPtr) node, 0);
                   1901:     else
                   1902:         xmlElemDump(fp, node->doc, node);
                   1903: 
                   1904:     fprintf(fp, "\n");
                   1905: }
                   1906: 
                   1907: /**
                   1908:  * xmlShellPrintNode:
                   1909:  * @node : a non-null node to print to the output FILE
                   1910:  *
                   1911:  * Print node to the output FILE
                   1912:  */
                   1913: void
                   1914: xmlShellPrintNode(xmlNodePtr node)
                   1915: {
                   1916:     xmlShellPrintNodeCtxt(NULL, node);
                   1917: }
                   1918: #endif /* LIBXML_OUTPUT_ENABLED */
                   1919: 
                   1920: /**
                   1921:  * xmlShellPrintXPathResultCtxt:
                   1922:  * @ctxt: a valid shell context
                   1923:  * @list: a valid result generated by an xpath evaluation
                   1924:  *
                   1925:  * Prints result to the output FILE
                   1926:  */
                   1927: static void
                   1928: xmlShellPrintXPathResultCtxt(xmlShellCtxtPtr ctxt,xmlXPathObjectPtr list)
                   1929: {
                   1930:     if (!ctxt)
                   1931:        return;
                   1932: 
                   1933:     if (list != NULL) {
                   1934:         switch (list->type) {
                   1935:             case XPATH_NODESET:{
                   1936: #ifdef LIBXML_OUTPUT_ENABLED
                   1937:                     int indx;
                   1938: 
                   1939:                     if (list->nodesetval) {
                   1940:                         for (indx = 0; indx < list->nodesetval->nodeNr;
                   1941:                              indx++) {
                   1942:                             xmlShellPrintNodeCtxt(ctxt,
                   1943:                                    list->nodesetval->nodeTab[indx]);
                   1944:                         }
                   1945:                     } else {
                   1946:                         xmlGenericError(xmlGenericErrorContext,
                   1947:                                         "Empty node set\n");
                   1948:                     }
                   1949:                     break;
                   1950: #else
                   1951:                    xmlGenericError(xmlGenericErrorContext,
                   1952:                                    "Node set\n");
                   1953: #endif /* LIBXML_OUTPUT_ENABLED */
                   1954:                 }
                   1955:             case XPATH_BOOLEAN:
                   1956:                 xmlGenericError(xmlGenericErrorContext,
                   1957:                                 "Is a Boolean:%s\n",
                   1958:                                 xmlBoolToText(list->boolval));
                   1959:                 break;
                   1960:             case XPATH_NUMBER:
                   1961:                 xmlGenericError(xmlGenericErrorContext,
                   1962:                                 "Is a number:%0g\n", list->floatval);
                   1963:                 break;
                   1964:             case XPATH_STRING:
                   1965:                 xmlGenericError(xmlGenericErrorContext,
                   1966:                                 "Is a string:%s\n", list->stringval);
                   1967:                 break;
                   1968: 
                   1969:             default:
                   1970:                 xmlShellPrintXPathError(list->type, NULL);
                   1971:         }
                   1972:     }
                   1973: }
                   1974: 
                   1975: /**
                   1976:  * xmlShellPrintXPathResult:
                   1977:  * @list: a valid result generated by an xpath evaluation
                   1978:  *
                   1979:  * Prints result to the output FILE
                   1980:  */
                   1981: void
                   1982: xmlShellPrintXPathResult(xmlXPathObjectPtr list)
                   1983: {
                   1984:     xmlShellPrintXPathResultCtxt(NULL, list);
                   1985: }
                   1986: 
                   1987: /**
                   1988:  * xmlShellList:
                   1989:  * @ctxt:  the shell context
                   1990:  * @arg:  unused
                   1991:  * @node:  a node
                   1992:  * @node2:  unused
                   1993:  *
                   1994:  * Implements the XML shell function "ls"
                   1995:  * Does an Unix like listing of the given node (like a directory)
                   1996:  *
                   1997:  * Returns 0
                   1998:  */
                   1999: int
                   2000: xmlShellList(xmlShellCtxtPtr ctxt,
                   2001:              char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
                   2002:              xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2003: {
                   2004:     xmlNodePtr cur;
                   2005:     if (!ctxt)
                   2006:         return (0);
                   2007:     if (node == NULL) {
                   2008:        fprintf(ctxt->output, "NULL\n");
                   2009:        return (0);
                   2010:     }
                   2011:     if ((node->type == XML_DOCUMENT_NODE) ||
                   2012:         (node->type == XML_HTML_DOCUMENT_NODE)) {
                   2013:         cur = ((xmlDocPtr) node)->children;
                   2014:     } else if (node->type == XML_NAMESPACE_DECL) {
                   2015:         xmlLsOneNode(ctxt->output, node);
                   2016:         return (0);
                   2017:     } else if (node->children != NULL) {
                   2018:         cur = node->children;
                   2019:     } else {
                   2020:         xmlLsOneNode(ctxt->output, node);
                   2021:         return (0);
                   2022:     }
                   2023:     while (cur != NULL) {
                   2024:         xmlLsOneNode(ctxt->output, cur);
                   2025:         cur = cur->next;
                   2026:     }
                   2027:     return (0);
                   2028: }
                   2029: 
                   2030: /**
                   2031:  * xmlShellBase:
                   2032:  * @ctxt:  the shell context
                   2033:  * @arg:  unused
                   2034:  * @node:  a node
                   2035:  * @node2:  unused
                   2036:  *
                   2037:  * Implements the XML shell function "base"
                   2038:  * dumps the current XML base of the node
                   2039:  *
                   2040:  * Returns 0
                   2041:  */
                   2042: int
                   2043: xmlShellBase(xmlShellCtxtPtr ctxt,
                   2044:              char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
                   2045:              xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2046: {
                   2047:     xmlChar *base;
                   2048:     if (!ctxt)
                   2049:         return 0;
                   2050:     if (node == NULL) {
                   2051:        fprintf(ctxt->output, "NULL\n");
                   2052:        return (0);
                   2053:     }    
                   2054: 
                   2055:     base = xmlNodeGetBase(node->doc, node);
                   2056: 
                   2057:     if (base == NULL) {
                   2058:         fprintf(ctxt->output, " No base found !!!\n");
                   2059:     } else {
                   2060:         fprintf(ctxt->output, "%s\n", base);
                   2061:         xmlFree(base);
                   2062:     }
                   2063:     return (0);
                   2064: }
                   2065: 
                   2066: #ifdef LIBXML_TREE_ENABLED
                   2067: /**
                   2068:  * xmlShellSetBase:
                   2069:  * @ctxt:  the shell context
                   2070:  * @arg:  the new base
                   2071:  * @node:  a node
                   2072:  * @node2:  unused
                   2073:  *
                   2074:  * Implements the XML shell function "setbase"
                   2075:  * change the current XML base of the node
                   2076:  *
                   2077:  * Returns 0
                   2078:  */
                   2079: static int
                   2080: xmlShellSetBase(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
                   2081:              char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
                   2082:              xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2083: {
                   2084:     xmlNodeSetBase(node, (xmlChar*) arg);
                   2085:     return (0);
                   2086: }
                   2087: #endif
                   2088: 
                   2089: #ifdef LIBXML_XPATH_ENABLED
                   2090: /**
                   2091:  * xmlShellRegisterNamespace:
                   2092:  * @ctxt:  the shell context
                   2093:  * @arg:  a string in prefix=nsuri format
                   2094:  * @node:  unused
                   2095:  * @node2:  unused
                   2096:  *
                   2097:  * Implements the XML shell function "setns"
                   2098:  * register/unregister a prefix=namespace pair
                   2099:  * on the XPath context
                   2100:  *
                   2101:  * Returns 0 on success and a negative value otherwise.
                   2102:  */
                   2103: static int
                   2104: xmlShellRegisterNamespace(xmlShellCtxtPtr ctxt, char *arg,
                   2105:       xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2106: {
                   2107:     xmlChar* nsListDup;
                   2108:     xmlChar* prefix;
                   2109:     xmlChar* href;
                   2110:     xmlChar* next;
                   2111: 
                   2112:     nsListDup = xmlStrdup((xmlChar *) arg);
                   2113:     next = nsListDup;
                   2114:     while(next != NULL) {
                   2115:        /* skip spaces */
                   2116:        /*while((*next) == ' ') next++;*/
                   2117:        if((*next) == '\0') break;
                   2118: 
                   2119:        /* find prefix */
                   2120:        prefix = next;
                   2121:        next = (xmlChar*)xmlStrchr(next, '=');
                   2122:        if(next == NULL) {
                   2123:            fprintf(ctxt->output, "setns: prefix=[nsuri] required\n");
                   2124:            xmlFree(nsListDup);
                   2125:            return(-1);
                   2126:        }
                   2127:        *(next++) = '\0';
                   2128: 
                   2129:        /* find href */
                   2130:        href = next;
                   2131:        next = (xmlChar*)xmlStrchr(next, ' ');
                   2132:        if(next != NULL) {
                   2133:            *(next++) = '\0';
                   2134:        }
                   2135: 
                   2136:        /* do register namespace */
                   2137:        if(xmlXPathRegisterNs(ctxt->pctxt, prefix, href) != 0) {
                   2138:            fprintf(ctxt->output,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href);
                   2139:            xmlFree(nsListDup);
                   2140:            return(-1);
                   2141:        }
                   2142:     }
                   2143: 
                   2144:     xmlFree(nsListDup);
                   2145:     return(0);
                   2146: }
                   2147: /**
                   2148:  * xmlShellRegisterRootNamespaces:
                   2149:  * @ctxt:  the shell context
                   2150:  * @arg:  unused
                   2151:  * @node:  the root element
                   2152:  * @node2:  unused
                   2153:  *
                   2154:  * Implements the XML shell function "setrootns"
                   2155:  * which registers all namespaces declarations found on the root element.
                   2156:  *
                   2157:  * Returns 0 on success and a negative value otherwise.
                   2158:  */
                   2159: static int
                   2160: xmlShellRegisterRootNamespaces(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
                   2161:       xmlNodePtr root, xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2162: {
                   2163:     xmlNsPtr ns;
                   2164: 
                   2165:     if ((root == NULL) || (root->type != XML_ELEMENT_NODE) ||
                   2166:         (root->nsDef == NULL) || (ctxt == NULL) || (ctxt->pctxt == NULL))
                   2167:        return(-1);
                   2168:     ns = root->nsDef;
                   2169:     while (ns != NULL) {
                   2170:         if (ns->prefix == NULL)
                   2171:            xmlXPathRegisterNs(ctxt->pctxt, BAD_CAST "defaultns", ns->href);
                   2172:        else
                   2173:            xmlXPathRegisterNs(ctxt->pctxt, ns->prefix, ns->href);
                   2174:         ns = ns->next;
                   2175:     }
                   2176:     return(0);
                   2177: }
                   2178: #endif
                   2179: 
                   2180: /**
                   2181:  * xmlShellGrep:
                   2182:  * @ctxt:  the shell context
                   2183:  * @arg:  the string or regular expression to find
                   2184:  * @node:  a node
                   2185:  * @node2:  unused
                   2186:  *
                   2187:  * Implements the XML shell function "grep"
                   2188:  * dumps informations about the node (namespace, attributes, content).
                   2189:  *
                   2190:  * Returns 0
                   2191:  */
                   2192: static int
                   2193: xmlShellGrep(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
                   2194:             char *arg, xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2195: {
                   2196:     if (!ctxt)
                   2197:         return (0);
                   2198:     if (node == NULL)
                   2199:        return (0);
                   2200:     if (arg == NULL)
                   2201:        return (0);
                   2202: #ifdef LIBXML_REGEXP_ENABLED
                   2203:     if ((xmlStrchr((xmlChar *) arg, '?')) ||
                   2204:        (xmlStrchr((xmlChar *) arg, '*')) ||
                   2205:        (xmlStrchr((xmlChar *) arg, '.')) ||
                   2206:        (xmlStrchr((xmlChar *) arg, '['))) {
                   2207:     }
                   2208: #endif
                   2209:     while (node != NULL) {
                   2210:         if (node->type == XML_COMMENT_NODE) {
                   2211:            if (xmlStrstr(node->content, (xmlChar *) arg)) {
                   2212: 
                   2213:                fprintf(ctxt->output, "%s : ", xmlGetNodePath(node));
                   2214:                 xmlShellList(ctxt, NULL, node, NULL);
                   2215:            }
                   2216:         } else if (node->type == XML_TEXT_NODE) {
                   2217:            if (xmlStrstr(node->content, (xmlChar *) arg)) {
                   2218: 
                   2219:                fprintf(ctxt->output, "%s : ", xmlGetNodePath(node->parent));
                   2220:                 xmlShellList(ctxt, NULL, node->parent, NULL);
                   2221:            }
                   2222:         }
                   2223: 
                   2224:         /*
                   2225:          * Browse the full subtree, deep first
                   2226:          */
                   2227: 
                   2228:         if ((node->type == XML_DOCUMENT_NODE) ||
                   2229:             (node->type == XML_HTML_DOCUMENT_NODE)) {
                   2230:             node = ((xmlDocPtr) node)->children;
                   2231:         } else if ((node->children != NULL)
                   2232:                    && (node->type != XML_ENTITY_REF_NODE)) {
                   2233:             /* deep first */
                   2234:             node = node->children;
                   2235:         } else if (node->next != NULL) {
                   2236:             /* then siblings */
                   2237:             node = node->next;
                   2238:         } else {
                   2239:             /* go up to parents->next if needed */
                   2240:             while (node != NULL) {
                   2241:                 if (node->parent != NULL) {
                   2242:                     node = node->parent;
                   2243:                 }
                   2244:                 if (node->next != NULL) {
                   2245:                     node = node->next;
                   2246:                     break;
                   2247:                 }
                   2248:                 if (node->parent == NULL) {
                   2249:                     node = NULL;
                   2250:                     break;
                   2251:                 }
                   2252:             }
                   2253:        }
                   2254:     }
                   2255:     return (0);
                   2256: }
                   2257: 
                   2258: /**
                   2259:  * xmlShellDir:
                   2260:  * @ctxt:  the shell context
                   2261:  * @arg:  unused
                   2262:  * @node:  a node
                   2263:  * @node2:  unused
                   2264:  *
                   2265:  * Implements the XML shell function "dir"
                   2266:  * dumps informations about the node (namespace, attributes, content).
                   2267:  *
                   2268:  * Returns 0
                   2269:  */
                   2270: int
                   2271: xmlShellDir(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
                   2272:             char *arg ATTRIBUTE_UNUSED, xmlNodePtr node,
                   2273:             xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2274: {
                   2275:     if (!ctxt)
                   2276:         return (0);
                   2277:     if (node == NULL) {
                   2278:        fprintf(ctxt->output, "NULL\n");
                   2279:        return (0);
                   2280:     }    
                   2281:     if ((node->type == XML_DOCUMENT_NODE) ||
                   2282:         (node->type == XML_HTML_DOCUMENT_NODE)) {
                   2283:         xmlDebugDumpDocumentHead(ctxt->output, (xmlDocPtr) node);
                   2284:     } else if (node->type == XML_ATTRIBUTE_NODE) {
                   2285:         xmlDebugDumpAttr(ctxt->output, (xmlAttrPtr) node, 0);
                   2286:     } else {
                   2287:         xmlDebugDumpOneNode(ctxt->output, node, 0);
                   2288:     }
                   2289:     return (0);
                   2290: }
                   2291: 
                   2292: /**
                   2293:  * xmlShellSetContent:
                   2294:  * @ctxt:  the shell context
                   2295:  * @value:  the content as a string
                   2296:  * @node:  a node
                   2297:  * @node2:  unused
                   2298:  *
                   2299:  * Implements the XML shell function "dir"
                   2300:  * dumps informations about the node (namespace, attributes, content).
                   2301:  *
                   2302:  * Returns 0
                   2303:  */
                   2304: static int
                   2305: xmlShellSetContent(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED,
                   2306:             char *value, xmlNodePtr node,
                   2307:             xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2308: {
                   2309:     xmlNodePtr results;
                   2310:     xmlParserErrors ret;
                   2311: 
                   2312:     if (!ctxt)
                   2313:         return (0);
                   2314:     if (node == NULL) {
                   2315:        fprintf(ctxt->output, "NULL\n");
                   2316:        return (0);
                   2317:     }
                   2318:     if (value == NULL) {
                   2319:         fprintf(ctxt->output, "NULL\n");
                   2320:        return (0);
                   2321:     }
                   2322: 
                   2323:     ret = xmlParseInNodeContext(node, value, strlen(value), 0, &results);
                   2324:     if (ret == XML_ERR_OK) {
                   2325:        if (node->children != NULL) {
                   2326:            xmlFreeNodeList(node->children);
                   2327:            node->children = NULL;
                   2328:            node->last = NULL;
                   2329:        }
                   2330:        xmlAddChildList(node, results);
                   2331:     } else {
                   2332:         fprintf(ctxt->output, "failed to parse content\n");
                   2333:     }
                   2334:     return (0);
                   2335: }
                   2336: 
                   2337: #ifdef LIBXML_SCHEMAS_ENABLED
                   2338: /**
                   2339:  * xmlShellRNGValidate:
                   2340:  * @ctxt:  the shell context
                   2341:  * @schemas:  the path to the Relax-NG schemas
                   2342:  * @node:  a node
                   2343:  * @node2:  unused
                   2344:  *
                   2345:  * Implements the XML shell function "relaxng"
                   2346:  * validating the instance against a Relax-NG schemas
                   2347:  *
                   2348:  * Returns 0
                   2349:  */
                   2350: static int
                   2351: xmlShellRNGValidate(xmlShellCtxtPtr sctxt, char *schemas,
                   2352:             xmlNodePtr node ATTRIBUTE_UNUSED,
                   2353:            xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2354: {
                   2355:     xmlRelaxNGPtr relaxngschemas;
                   2356:     xmlRelaxNGParserCtxtPtr ctxt;
                   2357:     xmlRelaxNGValidCtxtPtr vctxt;
                   2358:     int ret;
                   2359: 
                   2360:     ctxt = xmlRelaxNGNewParserCtxt(schemas);
                   2361:     xmlRelaxNGSetParserErrors(ctxt,
                   2362:            (xmlRelaxNGValidityErrorFunc) fprintf,
                   2363:            (xmlRelaxNGValidityWarningFunc) fprintf,
                   2364:            stderr);
                   2365:     relaxngschemas = xmlRelaxNGParse(ctxt);
                   2366:     xmlRelaxNGFreeParserCtxt(ctxt);
                   2367:     if (relaxngschemas == NULL) {
                   2368:        xmlGenericError(xmlGenericErrorContext,
                   2369:                "Relax-NG schema %s failed to compile\n", schemas);
                   2370:        return(-1);
                   2371:     }
                   2372:     vctxt = xmlRelaxNGNewValidCtxt(relaxngschemas);
                   2373:     xmlRelaxNGSetValidErrors(vctxt,
                   2374:            (xmlRelaxNGValidityErrorFunc) fprintf,
                   2375:            (xmlRelaxNGValidityWarningFunc) fprintf,
                   2376:            stderr);
                   2377:     ret = xmlRelaxNGValidateDoc(vctxt, sctxt->doc);
                   2378:     if (ret == 0) {
                   2379:        fprintf(stderr, "%s validates\n", sctxt->filename);
                   2380:     } else if (ret > 0) {
                   2381:        fprintf(stderr, "%s fails to validate\n", sctxt->filename);
                   2382:     } else {
                   2383:        fprintf(stderr, "%s validation generated an internal error\n",
                   2384:               sctxt->filename);
                   2385:     }
                   2386:     xmlRelaxNGFreeValidCtxt(vctxt);
                   2387:     if (relaxngschemas != NULL)
                   2388:        xmlRelaxNGFree(relaxngschemas);
                   2389:     return(0);
                   2390: }
                   2391: #endif
                   2392: 
                   2393: #ifdef LIBXML_OUTPUT_ENABLED
                   2394: /**
                   2395:  * xmlShellCat:
                   2396:  * @ctxt:  the shell context
                   2397:  * @arg:  unused
                   2398:  * @node:  a node
                   2399:  * @node2:  unused
                   2400:  *
                   2401:  * Implements the XML shell function "cat"
                   2402:  * dumps the serialization node content (XML or HTML).
                   2403:  *
                   2404:  * Returns 0
                   2405:  */
                   2406: int
                   2407: xmlShellCat(xmlShellCtxtPtr ctxt, char *arg ATTRIBUTE_UNUSED,
                   2408:             xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2409: {
                   2410:     if (!ctxt)
                   2411:         return (0);
                   2412:     if (node == NULL) {
                   2413:        fprintf(ctxt->output, "NULL\n");
                   2414:        return (0);
                   2415:     }    
                   2416:     if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
                   2417: #ifdef LIBXML_HTML_ENABLED
                   2418:         if (node->type == XML_HTML_DOCUMENT_NODE)
                   2419:             htmlDocDump(ctxt->output, (htmlDocPtr) node);
                   2420:         else
                   2421:             htmlNodeDumpFile(ctxt->output, ctxt->doc, node);
                   2422: #else
                   2423:         if (node->type == XML_DOCUMENT_NODE)
                   2424:             xmlDocDump(ctxt->output, (xmlDocPtr) node);
                   2425:         else
                   2426:             xmlElemDump(ctxt->output, ctxt->doc, node);
                   2427: #endif /* LIBXML_HTML_ENABLED */
                   2428:     } else {
                   2429:         if (node->type == XML_DOCUMENT_NODE)
                   2430:             xmlDocDump(ctxt->output, (xmlDocPtr) node);
                   2431:         else
                   2432:             xmlElemDump(ctxt->output, ctxt->doc, node);
                   2433:     }
                   2434:     fprintf(ctxt->output, "\n");
                   2435:     return (0);
                   2436: }
                   2437: #endif /* LIBXML_OUTPUT_ENABLED */
                   2438: 
                   2439: /**
                   2440:  * xmlShellLoad:
                   2441:  * @ctxt:  the shell context
                   2442:  * @filename:  the file name
                   2443:  * @node:  unused
                   2444:  * @node2:  unused
                   2445:  *
                   2446:  * Implements the XML shell function "load"
                   2447:  * loads a new document specified by the filename
                   2448:  *
                   2449:  * Returns 0 or -1 if loading failed
                   2450:  */
                   2451: int
                   2452: xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename,
                   2453:              xmlNodePtr node ATTRIBUTE_UNUSED,
                   2454:              xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2455: {
                   2456:     xmlDocPtr doc;
                   2457:     int html = 0;
                   2458: 
                   2459:     if ((ctxt == NULL) || (filename == NULL)) return(-1);
                   2460:     if (ctxt->doc != NULL)
                   2461:         html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
                   2462: 
                   2463:     if (html) {
                   2464: #ifdef LIBXML_HTML_ENABLED
                   2465:         doc = htmlParseFile(filename, NULL);
                   2466: #else
                   2467:         fprintf(ctxt->output, "HTML support not compiled in\n");
                   2468:         doc = NULL;
                   2469: #endif /* LIBXML_HTML_ENABLED */
                   2470:     } else {
                   2471:         doc = xmlReadFile(filename,NULL,0);
                   2472:     }
                   2473:     if (doc != NULL) {
                   2474:         if (ctxt->loaded == 1) {
                   2475:             xmlFreeDoc(ctxt->doc);
                   2476:         }
                   2477:         ctxt->loaded = 1;
                   2478: #ifdef LIBXML_XPATH_ENABLED
                   2479:         xmlXPathFreeContext(ctxt->pctxt);
                   2480: #endif /* LIBXML_XPATH_ENABLED */
                   2481:         xmlFree(ctxt->filename);
                   2482:         ctxt->doc = doc;
                   2483:         ctxt->node = (xmlNodePtr) doc;
                   2484: #ifdef LIBXML_XPATH_ENABLED
                   2485:         ctxt->pctxt = xmlXPathNewContext(doc);
                   2486: #endif /* LIBXML_XPATH_ENABLED */
                   2487:         ctxt->filename = (char *) xmlCanonicPath((xmlChar *) filename);
                   2488:     } else
                   2489:         return (-1);
                   2490:     return (0);
                   2491: }
                   2492: 
                   2493: #ifdef LIBXML_OUTPUT_ENABLED
                   2494: /**
                   2495:  * xmlShellWrite:
                   2496:  * @ctxt:  the shell context
                   2497:  * @filename:  the file name
                   2498:  * @node:  a node in the tree
                   2499:  * @node2:  unused
                   2500:  *
                   2501:  * Implements the XML shell function "write"
                   2502:  * Write the current node to the filename, it saves the serialization
                   2503:  * of the subtree under the @node specified
                   2504:  *
                   2505:  * Returns 0 or -1 in case of error
                   2506:  */
                   2507: int
                   2508: xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
                   2509:               xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2510: {
                   2511:     if (node == NULL)
                   2512:         return (-1);
                   2513:     if ((filename == NULL) || (filename[0] == 0)) {
                   2514:         return (-1);
                   2515:     }
                   2516: #ifdef W_OK
                   2517:     if (access((char *) filename, W_OK)) {
                   2518:         xmlGenericError(xmlGenericErrorContext,
                   2519:                         "Cannot write to %s\n", filename);
                   2520:         return (-1);
                   2521:     }
                   2522: #endif
                   2523:     switch (node->type) {
                   2524:         case XML_DOCUMENT_NODE:
                   2525:             if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
                   2526:                 xmlGenericError(xmlGenericErrorContext,
                   2527:                                 "Failed to write to %s\n", filename);
                   2528:                 return (-1);
                   2529:             }
                   2530:             break;
                   2531:         case XML_HTML_DOCUMENT_NODE:
                   2532: #ifdef LIBXML_HTML_ENABLED
                   2533:             if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   2534:                 xmlGenericError(xmlGenericErrorContext,
                   2535:                                 "Failed to write to %s\n", filename);
                   2536:                 return (-1);
                   2537:             }
                   2538: #else
                   2539:             if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
                   2540:                 xmlGenericError(xmlGenericErrorContext,
                   2541:                                 "Failed to write to %s\n", filename);
                   2542:                 return (-1);
                   2543:             }
                   2544: #endif /* LIBXML_HTML_ENABLED */
                   2545:             break;
                   2546:         default:{
                   2547:                 FILE *f;
                   2548: 
                   2549:                 f = fopen((char *) filename, "w");
                   2550:                 if (f == NULL) {
                   2551:                     xmlGenericError(xmlGenericErrorContext,
                   2552:                                     "Failed to write to %s\n", filename);
                   2553:                     return (-1);
                   2554:                 }
                   2555:                 xmlElemDump(f, ctxt->doc, node);
                   2556:                 fclose(f);
                   2557:             }
                   2558:     }
                   2559:     return (0);
                   2560: }
                   2561: 
                   2562: /**
                   2563:  * xmlShellSave:
                   2564:  * @ctxt:  the shell context
                   2565:  * @filename:  the file name (optional)
                   2566:  * @node:  unused
                   2567:  * @node2:  unused
                   2568:  *
                   2569:  * Implements the XML shell function "save"
                   2570:  * Write the current document to the filename, or it's original name
                   2571:  *
                   2572:  * Returns 0 or -1 in case of error
                   2573:  */
                   2574: int
                   2575: xmlShellSave(xmlShellCtxtPtr ctxt, char *filename,
                   2576:              xmlNodePtr node ATTRIBUTE_UNUSED,
                   2577:              xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2578: {
                   2579:     if ((ctxt == NULL) || (ctxt->doc == NULL))
                   2580:         return (-1);
                   2581:     if ((filename == NULL) || (filename[0] == 0))
                   2582:         filename = ctxt->filename;
                   2583:     if (filename == NULL)
                   2584:         return (-1);
                   2585: #ifdef W_OK
                   2586:     if (access((char *) filename, W_OK)) {
                   2587:         xmlGenericError(xmlGenericErrorContext,
                   2588:                         "Cannot save to %s\n", filename);
                   2589:         return (-1);
                   2590:     }
                   2591: #endif
                   2592:     switch (ctxt->doc->type) {
                   2593:         case XML_DOCUMENT_NODE:
                   2594:             if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   2595:                 xmlGenericError(xmlGenericErrorContext,
                   2596:                                 "Failed to save to %s\n", filename);
                   2597:             }
                   2598:             break;
                   2599:         case XML_HTML_DOCUMENT_NODE:
                   2600: #ifdef LIBXML_HTML_ENABLED
                   2601:             if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   2602:                 xmlGenericError(xmlGenericErrorContext,
                   2603:                                 "Failed to save to %s\n", filename);
                   2604:             }
                   2605: #else
                   2606:             if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   2607:                 xmlGenericError(xmlGenericErrorContext,
                   2608:                                 "Failed to save to %s\n", filename);
                   2609:             }
                   2610: #endif /* LIBXML_HTML_ENABLED */
                   2611:             break;
                   2612:         default:
                   2613:             xmlGenericError(xmlGenericErrorContext,
                   2614:            "To save to subparts of a document use the 'write' command\n");
                   2615:             return (-1);
                   2616: 
                   2617:     }
                   2618:     return (0);
                   2619: }
                   2620: #endif /* LIBXML_OUTPUT_ENABLED */
                   2621: 
                   2622: #ifdef LIBXML_VALID_ENABLED
                   2623: /**
                   2624:  * xmlShellValidate:
                   2625:  * @ctxt:  the shell context
                   2626:  * @dtd:  the DTD URI (optional)
                   2627:  * @node:  unused
                   2628:  * @node2:  unused
                   2629:  *
                   2630:  * Implements the XML shell function "validate"
                   2631:  * Validate the document, if a DTD path is provided, then the validation
                   2632:  * is done against the given DTD.
                   2633:  *
                   2634:  * Returns 0 or -1 in case of error
                   2635:  */
                   2636: int
                   2637: xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd,
                   2638:                  xmlNodePtr node ATTRIBUTE_UNUSED,
                   2639:                  xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2640: {
                   2641:     xmlValidCtxt vctxt;
                   2642:     int res = -1;
                   2643: 
                   2644:     if ((ctxt == NULL) || (ctxt->doc == NULL)) return(-1);
                   2645:     vctxt.userData = stderr;
                   2646:     vctxt.error = (xmlValidityErrorFunc) fprintf;
                   2647:     vctxt.warning = (xmlValidityWarningFunc) fprintf;
                   2648: 
                   2649:     if ((dtd == NULL) || (dtd[0] == 0)) {
                   2650:         res = xmlValidateDocument(&vctxt, ctxt->doc);
                   2651:     } else {
                   2652:         xmlDtdPtr subset;
                   2653: 
                   2654:         subset = xmlParseDTD(NULL, (xmlChar *) dtd);
                   2655:         if (subset != NULL) {
                   2656:             res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
                   2657: 
                   2658:             xmlFreeDtd(subset);
                   2659:         }
                   2660:     }
                   2661:     return (res);
                   2662: }
                   2663: #endif /* LIBXML_VALID_ENABLED */
                   2664: 
                   2665: /**
                   2666:  * xmlShellDu:
                   2667:  * @ctxt:  the shell context
                   2668:  * @arg:  unused
                   2669:  * @tree:  a node defining a subtree
                   2670:  * @node2:  unused
                   2671:  *
                   2672:  * Implements the XML shell function "du"
                   2673:  * show the structure of the subtree under node @tree
                   2674:  * If @tree is null, the command works on the current node.
                   2675:  *
                   2676:  * Returns 0 or -1 in case of error
                   2677:  */
                   2678: int
                   2679: xmlShellDu(xmlShellCtxtPtr ctxt,
                   2680:            char *arg ATTRIBUTE_UNUSED, xmlNodePtr tree,
                   2681:            xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2682: {
                   2683:     xmlNodePtr node;
                   2684:     int indent = 0, i;
                   2685: 
                   2686:     if (!ctxt)
                   2687:        return (-1);
                   2688: 
                   2689:     if (tree == NULL)
                   2690:         return (-1);
                   2691:     node = tree;
                   2692:     while (node != NULL) {
                   2693:         if ((node->type == XML_DOCUMENT_NODE) ||
                   2694:             (node->type == XML_HTML_DOCUMENT_NODE)) {
                   2695:             fprintf(ctxt->output, "/\n");
                   2696:         } else if (node->type == XML_ELEMENT_NODE) {
                   2697:             for (i = 0; i < indent; i++)
                   2698:                 fprintf(ctxt->output, "  ");
                   2699:             fprintf(ctxt->output, "%s\n", node->name);
                   2700:         } else {
                   2701:         }
                   2702: 
                   2703:         /*
                   2704:          * Browse the full subtree, deep first
                   2705:          */
                   2706: 
                   2707:         if ((node->type == XML_DOCUMENT_NODE) ||
                   2708:             (node->type == XML_HTML_DOCUMENT_NODE)) {
                   2709:             node = ((xmlDocPtr) node)->children;
                   2710:         } else if ((node->children != NULL)
                   2711:                    && (node->type != XML_ENTITY_REF_NODE)) {
                   2712:             /* deep first */
                   2713:             node = node->children;
                   2714:             indent++;
                   2715:         } else if ((node != tree) && (node->next != NULL)) {
                   2716:             /* then siblings */
                   2717:             node = node->next;
                   2718:         } else if (node != tree) {
                   2719:             /* go up to parents->next if needed */
                   2720:             while (node != tree) {
                   2721:                 if (node->parent != NULL) {
                   2722:                     node = node->parent;
                   2723:                     indent--;
                   2724:                 }
                   2725:                 if ((node != tree) && (node->next != NULL)) {
                   2726:                     node = node->next;
                   2727:                     break;
                   2728:                 }
                   2729:                 if (node->parent == NULL) {
                   2730:                     node = NULL;
                   2731:                     break;
                   2732:                 }
                   2733:                 if (node == tree) {
                   2734:                     node = NULL;
                   2735:                     break;
                   2736:                 }
                   2737:             }
                   2738:             /* exit condition */
                   2739:             if (node == tree)
                   2740:                 node = NULL;
                   2741:         } else
                   2742:             node = NULL;
                   2743:     }
                   2744:     return (0);
                   2745: }
                   2746: 
                   2747: /**
                   2748:  * xmlShellPwd:
                   2749:  * @ctxt:  the shell context
                   2750:  * @buffer:  the output buffer
                   2751:  * @node:  a node 
                   2752:  * @node2:  unused
                   2753:  *
                   2754:  * Implements the XML shell function "pwd"
                   2755:  * Show the full path from the root to the node, if needed building
                   2756:  * thumblers when similar elements exists at a given ancestor level.
                   2757:  * The output is compatible with XPath commands.
                   2758:  *
                   2759:  * Returns 0 or -1 in case of error
                   2760:  */
                   2761: int
                   2762: xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer,
                   2763:             xmlNodePtr node, xmlNodePtr node2 ATTRIBUTE_UNUSED)
                   2764: {
                   2765:     xmlChar *path;
                   2766: 
                   2767:     if ((node == NULL) || (buffer == NULL))
                   2768:         return (-1);
                   2769: 
                   2770:     path = xmlGetNodePath(node);
                   2771:     if (path == NULL)
                   2772:        return (-1);
                   2773: 
                   2774:     /*
                   2775:      * This test prevents buffer overflow, because this routine
                   2776:      * is only called by xmlShell, in which the second argument is
                   2777:      * 500 chars long.
                   2778:      * It is a dirty hack before a cleaner solution is found.
                   2779:      * Documentation should mention that the second argument must
                   2780:      * be at least 500 chars long, and could be stripped if too long.
                   2781:      */
                   2782:     snprintf(buffer, 499, "%s", path);
                   2783:     buffer[499] = '0';
                   2784:     xmlFree(path);
                   2785: 
                   2786:     return (0);
                   2787: }
                   2788: 
                   2789: /**
                   2790:  * xmlShell:
                   2791:  * @doc:  the initial document
                   2792:  * @filename:  the output buffer
                   2793:  * @input:  the line reading function
                   2794:  * @output:  the output FILE*, defaults to stdout if NULL
                   2795:  *
                   2796:  * Implements the XML shell 
                   2797:  * This allow to load, validate, view, modify and save a document
                   2798:  * using a environment similar to a UNIX commandline.
                   2799:  */
                   2800: void
                   2801: xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                   2802:          FILE * output)
                   2803: {
                   2804:     char prompt[500] = "/ > ";
                   2805:     char *cmdline = NULL, *cur;
                   2806:     char command[100];
                   2807:     char arg[400];
                   2808:     int i;
                   2809:     xmlShellCtxtPtr ctxt;
                   2810:     xmlXPathObjectPtr list;
                   2811: 
                   2812:     if (doc == NULL)
                   2813:         return;
                   2814:     if (filename == NULL)
                   2815:         return;
                   2816:     if (input == NULL)
                   2817:         return;
                   2818:     if (output == NULL)
                   2819:         output = stdout;
                   2820:     ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
                   2821:     if (ctxt == NULL)
                   2822:         return;
                   2823:     ctxt->loaded = 0;
                   2824:     ctxt->doc = doc;
                   2825:     ctxt->input = input;
                   2826:     ctxt->output = output;
                   2827:     ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
                   2828:     ctxt->node = (xmlNodePtr) ctxt->doc;
                   2829: 
                   2830: #ifdef LIBXML_XPATH_ENABLED
                   2831:     ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
                   2832:     if (ctxt->pctxt == NULL) {
                   2833:         xmlFree(ctxt);
                   2834:         return;
                   2835:     }
                   2836: #endif /* LIBXML_XPATH_ENABLED */
                   2837:     while (1) {
                   2838:         if (ctxt->node == (xmlNodePtr) ctxt->doc)
                   2839:             snprintf(prompt, sizeof(prompt), "%s > ", "/");
                   2840:         else if ((ctxt->node != NULL) && (ctxt->node->name))
                   2841:             snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
                   2842:         else
                   2843:             snprintf(prompt, sizeof(prompt), "? > ");
                   2844:         prompt[sizeof(prompt) - 1] = 0;
                   2845: 
                   2846:         /*
                   2847:          * Get a new command line
                   2848:          */
                   2849:         cmdline = ctxt->input(prompt);
                   2850:         if (cmdline == NULL)
                   2851:             break;
                   2852: 
                   2853:         /*
                   2854:          * Parse the command itself
                   2855:          */
                   2856:         cur = cmdline;
                   2857:         while ((*cur == ' ') || (*cur == '\t'))
                   2858:             cur++;
                   2859:         i = 0;
                   2860:         while ((*cur != ' ') && (*cur != '\t') &&
                   2861:                (*cur != '\n') && (*cur != '\r')) {
                   2862:             if (*cur == 0)
                   2863:                 break;
                   2864:             command[i++] = *cur++;
                   2865:         }
                   2866:         command[i] = 0;
                   2867:         if (i == 0)
                   2868:             continue;
                   2869: 
                   2870:         /*
                   2871:          * Parse the argument
                   2872:          */
                   2873:         while ((*cur == ' ') || (*cur == '\t'))
                   2874:             cur++;
                   2875:         i = 0;
                   2876:         while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
                   2877:             if (*cur == 0)
                   2878:                 break;
                   2879:             arg[i++] = *cur++;
                   2880:         }
                   2881:         arg[i] = 0;
                   2882: 
                   2883:         /*
                   2884:          * start interpreting the command
                   2885:          */
                   2886:         if (!strcmp(command, "exit"))
                   2887:             break;
                   2888:         if (!strcmp(command, "quit"))
                   2889:             break;
                   2890:         if (!strcmp(command, "bye"))
                   2891:             break;
                   2892:                if (!strcmp(command, "help")) {
                   2893:                  fprintf(ctxt->output, "\tbase         display XML base of the node\n");
                   2894:                  fprintf(ctxt->output, "\tsetbase URI  change the XML base of the node\n");
                   2895:                  fprintf(ctxt->output, "\tbye          leave shell\n");
                   2896:                  fprintf(ctxt->output, "\tcat [node]   display node or current node\n");
                   2897:                  fprintf(ctxt->output, "\tcd [path]    change directory to path or to root\n");
                   2898:                  fprintf(ctxt->output, "\tdir [path]   dumps informations about the node (namespace, attributes, content)\n");
                   2899:                  fprintf(ctxt->output, "\tdu [path]    show the structure of the subtree under path or the current node\n");
                   2900:                  fprintf(ctxt->output, "\texit         leave shell\n");
                   2901:                  fprintf(ctxt->output, "\thelp         display this help\n");
                   2902:                  fprintf(ctxt->output, "\tfree         display memory usage\n");
                   2903:                  fprintf(ctxt->output, "\tload [name]  load a new document with name\n");
                   2904:                  fprintf(ctxt->output, "\tls [path]    list contents of path or the current directory\n");
                   2905:                  fprintf(ctxt->output, "\tset xml_fragment replace the current node content with the fragment parsed in context\n");
                   2906: #ifdef LIBXML_XPATH_ENABLED
                   2907:                  fprintf(ctxt->output, "\txpath expr   evaluate the XPath expression in that context and print the result\n");
                   2908:                  fprintf(ctxt->output, "\tsetns nsreg  register a namespace to a prefix in the XPath evaluation context\n");
                   2909:                  fprintf(ctxt->output, "\t             format for nsreg is: prefix=[nsuri] (i.e. prefix= unsets a prefix)\n");
                   2910:                  fprintf(ctxt->output, "\tsetrootns    register all namespace found on the root element\n");
                   2911:                  fprintf(ctxt->output, "\t             the default namespace if any uses 'defaultns' prefix\n");
                   2912: #endif /* LIBXML_XPATH_ENABLED */
                   2913:                  fprintf(ctxt->output, "\tpwd          display current working directory\n");
                   2914:                  fprintf(ctxt->output, "\tquit         leave shell\n");
                   2915: #ifdef LIBXML_OUTPUT_ENABLED
                   2916:                  fprintf(ctxt->output, "\tsave [name]  save this document to name or the original name\n");
                   2917:                  fprintf(ctxt->output, "\twrite [name] write the current node to the filename\n");
                   2918: #endif /* LIBXML_OUTPUT_ENABLED */
                   2919: #ifdef LIBXML_VALID_ENABLED
                   2920:                  fprintf(ctxt->output, "\tvalidate     check the document for errors\n");
                   2921: #endif /* LIBXML_VALID_ENABLED */
                   2922: #ifdef LIBXML_SCHEMAS_ENABLED
                   2923:                  fprintf(ctxt->output, "\trelaxng rng  validate the document agaisnt the Relax-NG schemas\n");
                   2924: #endif
                   2925:                  fprintf(ctxt->output, "\tgrep string  search for a string in the subtree\n");
                   2926: #ifdef LIBXML_VALID_ENABLED
                   2927:         } else if (!strcmp(command, "validate")) {
                   2928:             xmlShellValidate(ctxt, arg, NULL, NULL);
                   2929: #endif /* LIBXML_VALID_ENABLED */
                   2930:         } else if (!strcmp(command, "load")) {
                   2931:             xmlShellLoad(ctxt, arg, NULL, NULL);
                   2932: #ifdef LIBXML_SCHEMAS_ENABLED
                   2933:         } else if (!strcmp(command, "relaxng")) {
                   2934:             xmlShellRNGValidate(ctxt, arg, NULL, NULL);
                   2935: #endif
                   2936: #ifdef LIBXML_OUTPUT_ENABLED
                   2937:         } else if (!strcmp(command, "save")) {
                   2938:             xmlShellSave(ctxt, arg, NULL, NULL);
                   2939:         } else if (!strcmp(command, "write")) {
                   2940:            if ((arg == NULL) || (arg[0] == 0))
                   2941:                xmlGenericError(xmlGenericErrorContext,
                   2942:                         "Write command requires a filename argument\n");
                   2943:            else
                   2944:                xmlShellWrite(ctxt, arg, ctxt->node, NULL);
                   2945: #endif /* LIBXML_OUTPUT_ENABLED */
                   2946:         } else if (!strcmp(command, "grep")) {
                   2947:             xmlShellGrep(ctxt, arg, ctxt->node, NULL);
                   2948:         } else if (!strcmp(command, "free")) {
                   2949:             if (arg[0] == 0) {
                   2950:                 xmlMemShow(ctxt->output, 0);
                   2951:             } else {
                   2952:                 int len = 0;
                   2953: 
                   2954:                 sscanf(arg, "%d", &len);
                   2955:                 xmlMemShow(ctxt->output, len);
                   2956:             }
                   2957:         } else if (!strcmp(command, "pwd")) {
                   2958:             char dir[500];
                   2959: 
                   2960:             if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
                   2961:                 fprintf(ctxt->output, "%s\n", dir);
                   2962:         } else if (!strcmp(command, "du")) {
                   2963:             xmlShellDu(ctxt, NULL, ctxt->node, NULL);
                   2964:         } else if (!strcmp(command, "base")) {
                   2965:             xmlShellBase(ctxt, NULL, ctxt->node, NULL);
                   2966:         } else if (!strcmp(command, "set")) {
                   2967:            xmlShellSetContent(ctxt, arg, ctxt->node, NULL);
                   2968: #ifdef LIBXML_XPATH_ENABLED
                   2969:         } else if (!strcmp(command, "setns")) {
                   2970:             if (arg[0] == 0) {
                   2971:                xmlGenericError(xmlGenericErrorContext,
                   2972:                                "setns: prefix=[nsuri] required\n");
                   2973:             } else {
                   2974:                 xmlShellRegisterNamespace(ctxt, arg, NULL, NULL);
                   2975:             }
                   2976:         } else if (!strcmp(command, "setrootns")) {
                   2977:            xmlNodePtr root;
                   2978: 
                   2979:            root = xmlDocGetRootElement(ctxt->doc);
                   2980:            xmlShellRegisterRootNamespaces(ctxt, NULL, root, NULL);
                   2981:         } else if (!strcmp(command, "xpath")) {
                   2982:             if (arg[0] == 0) {
                   2983:                xmlGenericError(xmlGenericErrorContext,
                   2984:                                "xpath: expression required\n");
                   2985:            } else {
                   2986:                 ctxt->pctxt->node = ctxt->node;
                   2987:                 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
                   2988:                xmlXPathDebugDumpObject(ctxt->output, list, 0);
                   2989:                xmlXPathFreeObject(list);
                   2990:            }
                   2991: #endif /* LIBXML_XPATH_ENABLED */
                   2992: #ifdef LIBXML_TREE_ENABLED
                   2993:         } else if (!strcmp(command, "setbase")) {
                   2994:             xmlShellSetBase(ctxt, arg, ctxt->node, NULL);
                   2995: #endif
                   2996:         } else if ((!strcmp(command, "ls")) || (!strcmp(command, "dir"))) {
                   2997:             int dir = (!strcmp(command, "dir"));
                   2998: 
                   2999:             if (arg[0] == 0) {
                   3000:                 if (dir)
                   3001:                     xmlShellDir(ctxt, NULL, ctxt->node, NULL);
                   3002:                 else
                   3003:                     xmlShellList(ctxt, NULL, ctxt->node, NULL);
                   3004:             } else {
                   3005:                 ctxt->pctxt->node = ctxt->node;
                   3006: #ifdef LIBXML_XPATH_ENABLED
                   3007:                 ctxt->pctxt->node = ctxt->node;
                   3008:                 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
                   3009: #else
                   3010:                 list = NULL;
                   3011: #endif /* LIBXML_XPATH_ENABLED */
                   3012:                 if (list != NULL) {
                   3013:                     switch (list->type) {
                   3014:                         case XPATH_UNDEFINED:
                   3015:                             xmlGenericError(xmlGenericErrorContext,
                   3016:                                             "%s: no such node\n", arg);
                   3017:                             break;
                   3018:                         case XPATH_NODESET:{
                   3019:                                 int indx;
                   3020: 
                   3021:                                if (list->nodesetval == NULL)
                   3022:                                    break;
                   3023: 
                   3024:                                 for (indx = 0;
                   3025:                                      indx < list->nodesetval->nodeNr;
                   3026:                                      indx++) {
                   3027:                                     if (dir)
                   3028:                                         xmlShellDir(ctxt, NULL,
                   3029:                                                     list->nodesetval->
                   3030:                                                     nodeTab[indx], NULL);
                   3031:                                     else
                   3032:                                         xmlShellList(ctxt, NULL,
                   3033:                                                      list->nodesetval->
                   3034:                                                      nodeTab[indx], NULL);
                   3035:                                 }
                   3036:                                 break;
                   3037:                             }
                   3038:                         case XPATH_BOOLEAN:
                   3039:                             xmlGenericError(xmlGenericErrorContext,
                   3040:                                             "%s is a Boolean\n", arg);
                   3041:                             break;
                   3042:                         case XPATH_NUMBER:
                   3043:                             xmlGenericError(xmlGenericErrorContext,
                   3044:                                             "%s is a number\n", arg);
                   3045:                             break;
                   3046:                         case XPATH_STRING:
                   3047:                             xmlGenericError(xmlGenericErrorContext,
                   3048:                                             "%s is a string\n", arg);
                   3049:                             break;
                   3050:                         case XPATH_POINT:
                   3051:                             xmlGenericError(xmlGenericErrorContext,
                   3052:                                             "%s is a point\n", arg);
                   3053:                             break;
                   3054:                         case XPATH_RANGE:
                   3055:                             xmlGenericError(xmlGenericErrorContext,
                   3056:                                             "%s is a range\n", arg);
                   3057:                             break;
                   3058:                         case XPATH_LOCATIONSET:
                   3059:                             xmlGenericError(xmlGenericErrorContext,
                   3060:                                             "%s is a range\n", arg);
                   3061:                             break;
                   3062:                         case XPATH_USERS:
                   3063:                             xmlGenericError(xmlGenericErrorContext,
                   3064:                                             "%s is user-defined\n", arg);
                   3065:                             break;
                   3066:                         case XPATH_XSLT_TREE:
                   3067:                             xmlGenericError(xmlGenericErrorContext,
                   3068:                                             "%s is an XSLT value tree\n",
                   3069:                                             arg);
                   3070:                             break;
                   3071:                     }
                   3072: #ifdef LIBXML_XPATH_ENABLED
                   3073:                     xmlXPathFreeObject(list);
                   3074: #endif
                   3075:                 } else {
                   3076:                     xmlGenericError(xmlGenericErrorContext,
                   3077:                                     "%s: no such node\n", arg);
                   3078:                 }
                   3079:                 ctxt->pctxt->node = NULL;
                   3080:             }
                   3081:         } else if (!strcmp(command, "cd")) {
                   3082:             if (arg[0] == 0) {
                   3083:                 ctxt->node = (xmlNodePtr) ctxt->doc;
                   3084:             } else {
                   3085: #ifdef LIBXML_XPATH_ENABLED
                   3086:                 ctxt->pctxt->node = ctxt->node;
                   3087:                 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
                   3088: #else
                   3089:                 list = NULL;
                   3090: #endif /* LIBXML_XPATH_ENABLED */
                   3091:                 if (list != NULL) {
                   3092:                     switch (list->type) {
                   3093:                         case XPATH_UNDEFINED:
                   3094:                             xmlGenericError(xmlGenericErrorContext,
                   3095:                                             "%s: no such node\n", arg);
                   3096:                             break;
                   3097:                         case XPATH_NODESET:
                   3098:                             if (list->nodesetval != NULL) {
                   3099:                                if (list->nodesetval->nodeNr == 1) {
                   3100:                                    ctxt->node = list->nodesetval->nodeTab[0];
                   3101:                                    if ((ctxt->node != NULL) &&
                   3102:                                        (ctxt->node->type ==
                   3103:                                         XML_NAMESPACE_DECL)) {
                   3104:                                        xmlGenericError(xmlGenericErrorContext,
                   3105:                                                    "cannot cd to namespace\n");
                   3106:                                        ctxt->node = NULL;
                   3107:                                    }
                   3108:                                } else
                   3109:                                    xmlGenericError(xmlGenericErrorContext,
                   3110:                                                    "%s is a %d Node Set\n",
                   3111:                                                    arg,
                   3112:                                                    list->nodesetval->nodeNr);
                   3113:                             } else
                   3114:                                 xmlGenericError(xmlGenericErrorContext,
                   3115:                                                 "%s is an empty Node Set\n",
                   3116:                                                 arg);
                   3117:                             break;
                   3118:                         case XPATH_BOOLEAN:
                   3119:                             xmlGenericError(xmlGenericErrorContext,
                   3120:                                             "%s is a Boolean\n", arg);
                   3121:                             break;
                   3122:                         case XPATH_NUMBER:
                   3123:                             xmlGenericError(xmlGenericErrorContext,
                   3124:                                             "%s is a number\n", arg);
                   3125:                             break;
                   3126:                         case XPATH_STRING:
                   3127:                             xmlGenericError(xmlGenericErrorContext,
                   3128:                                             "%s is a string\n", arg);
                   3129:                             break;
                   3130:                         case XPATH_POINT:
                   3131:                             xmlGenericError(xmlGenericErrorContext,
                   3132:                                             "%s is a point\n", arg);
                   3133:                             break;
                   3134:                         case XPATH_RANGE:
                   3135:                             xmlGenericError(xmlGenericErrorContext,
                   3136:                                             "%s is a range\n", arg);
                   3137:                             break;
                   3138:                         case XPATH_LOCATIONSET:
                   3139:                             xmlGenericError(xmlGenericErrorContext,
                   3140:                                             "%s is a range\n", arg);
                   3141:                             break;
                   3142:                         case XPATH_USERS:
                   3143:                             xmlGenericError(xmlGenericErrorContext,
                   3144:                                             "%s is user-defined\n", arg);
                   3145:                             break;
                   3146:                         case XPATH_XSLT_TREE:
                   3147:                             xmlGenericError(xmlGenericErrorContext,
                   3148:                                             "%s is an XSLT value tree\n",
                   3149:                                             arg);
                   3150:                             break;
                   3151:                     }
                   3152: #ifdef LIBXML_XPATH_ENABLED
                   3153:                     xmlXPathFreeObject(list);
                   3154: #endif
                   3155:                 } else {
                   3156:                     xmlGenericError(xmlGenericErrorContext,
                   3157:                                     "%s: no such node\n", arg);
                   3158:                 }
                   3159:                 ctxt->pctxt->node = NULL;
                   3160:             }
                   3161: #ifdef LIBXML_OUTPUT_ENABLED
                   3162:         } else if (!strcmp(command, "cat")) {
                   3163:             if (arg[0] == 0) {
                   3164:                 xmlShellCat(ctxt, NULL, ctxt->node, NULL);
                   3165:             } else {
                   3166:                 ctxt->pctxt->node = ctxt->node;
                   3167: #ifdef LIBXML_XPATH_ENABLED
                   3168:                 ctxt->pctxt->node = ctxt->node;
                   3169:                 list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
                   3170: #else
                   3171:                 list = NULL;
                   3172: #endif /* LIBXML_XPATH_ENABLED */
                   3173:                 if (list != NULL) {
                   3174:                     switch (list->type) {
                   3175:                         case XPATH_UNDEFINED:
                   3176:                             xmlGenericError(xmlGenericErrorContext,
                   3177:                                             "%s: no such node\n", arg);
                   3178:                             break;
                   3179:                         case XPATH_NODESET:{
                   3180:                                 int indx;
                   3181: 
                   3182:                                if (list->nodesetval == NULL)
                   3183:                                    break;
                   3184: 
                   3185:                                 for (indx = 0;
                   3186:                                      indx < list->nodesetval->nodeNr;
                   3187:                                      indx++) {
                   3188:                                     if (i > 0)
                   3189:                                         fprintf(ctxt->output, " -------\n");
                   3190:                                     xmlShellCat(ctxt, NULL,
                   3191:                                                 list->nodesetval->
                   3192:                                                 nodeTab[indx], NULL);
                   3193:                                 }
                   3194:                                 break;
                   3195:                             }
                   3196:                         case XPATH_BOOLEAN:
                   3197:                             xmlGenericError(xmlGenericErrorContext,
                   3198:                                             "%s is a Boolean\n", arg);
                   3199:                             break;
                   3200:                         case XPATH_NUMBER:
                   3201:                             xmlGenericError(xmlGenericErrorContext,
                   3202:                                             "%s is a number\n", arg);
                   3203:                             break;
                   3204:                         case XPATH_STRING:
                   3205:                             xmlGenericError(xmlGenericErrorContext,
                   3206:                                             "%s is a string\n", arg);
                   3207:                             break;
                   3208:                         case XPATH_POINT:
                   3209:                             xmlGenericError(xmlGenericErrorContext,
                   3210:                                             "%s is a point\n", arg);
                   3211:                             break;
                   3212:                         case XPATH_RANGE:
                   3213:                             xmlGenericError(xmlGenericErrorContext,
                   3214:                                             "%s is a range\n", arg);
                   3215:                             break;
                   3216:                         case XPATH_LOCATIONSET:
                   3217:                             xmlGenericError(xmlGenericErrorContext,
                   3218:                                             "%s is a range\n", arg);
                   3219:                             break;
                   3220:                         case XPATH_USERS:
                   3221:                             xmlGenericError(xmlGenericErrorContext,
                   3222:                                             "%s is user-defined\n", arg);
                   3223:                             break;
                   3224:                         case XPATH_XSLT_TREE:
                   3225:                             xmlGenericError(xmlGenericErrorContext,
                   3226:                                             "%s is an XSLT value tree\n",
                   3227:                                             arg);
                   3228:                             break;
                   3229:                     }
                   3230: #ifdef LIBXML_XPATH_ENABLED
                   3231:                     xmlXPathFreeObject(list);
                   3232: #endif
                   3233:                 } else {
                   3234:                     xmlGenericError(xmlGenericErrorContext,
                   3235:                                     "%s: no such node\n", arg);
                   3236:                 }
                   3237:                 ctxt->pctxt->node = NULL;
                   3238:             }
                   3239: #endif /* LIBXML_OUTPUT_ENABLED */
                   3240:         } else {
                   3241:             xmlGenericError(xmlGenericErrorContext,
                   3242:                             "Unknown command %s\n", command);
                   3243:         }
                   3244:         free(cmdline);          /* not xmlFree here ! */
                   3245:        cmdline = NULL;
                   3246:     }
                   3247: #ifdef LIBXML_XPATH_ENABLED
                   3248:     xmlXPathFreeContext(ctxt->pctxt);
                   3249: #endif /* LIBXML_XPATH_ENABLED */
                   3250:     if (ctxt->loaded) {
                   3251:         xmlFreeDoc(ctxt->doc);
                   3252:     }
                   3253:     if (ctxt->filename != NULL)
                   3254:         xmlFree(ctxt->filename);
                   3255:     xmlFree(ctxt);
                   3256:     if (cmdline != NULL)
                   3257:         free(cmdline);          /* not xmlFree here ! */
                   3258: }
                   3259: 
                   3260: #endif /* LIBXML_XPATH_ENABLED */
                   3261: #define bottom_debugXML
                   3262: #include "elfgcchack.h"
                   3263: #endif /* LIBXML_DEBUG_ENABLED */

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