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

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

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