Annotation of XML/debugXML.c, revision 1.42

1.1       daniel      1: /*
                      2:  * debugXML.c : This is a set of routines used for debugging the tree
                      3:  *              produced by the XML parser.
                      4:  *
1.2       daniel      5:  * See Copyright for the status of this software.
                      6:  *
1.1       daniel      7:  * Daniel Veillard <Daniel.Veillard@w3.org>
                      8:  */
                      9: 
1.11      daniel     10: #ifdef WIN32
                     11: #include "win32config.h"
                     12: #else
                     13: #include "config.h"
                     14: #endif
1.23      daniel     15: 
1.41      veillard   16: #include <libxml/xmlversion.h>
1.23      daniel     17: #ifdef LIBXML_DEBUG_ENABLED
                     18: 
1.1       daniel     19: #include <stdio.h>
1.26      veillard   20: #include <string.h>
1.12      daniel     21: #ifdef HAVE_STDLIB_H
                     22: #include <stdlib.h>
                     23: #endif
1.14      daniel     24: #ifdef HAVE_STRING_H
                     25: #include <string.h>
                     26: #endif
1.23      daniel     27: #include <libxml/xmlmemory.h>
                     28: #include <libxml/tree.h>
                     29: #include <libxml/parser.h>
                     30: #include <libxml/valid.h>
                     31: #include <libxml/debugXML.h>
                     32: #include <libxml/HTMLtree.h>
                     33: #include <libxml/HTMLparser.h>
1.1       daniel     34: 
                     35: #define IS_BLANK(c)                                                    \
                     36:   (((c) == '\n') || ((c) == '\r') || ((c) == '\t') || ((c) == ' '))
                     37: 
1.6       daniel     38: void xmlDebugDumpString(FILE *output, const xmlChar *str) {
1.1       daniel     39:     int i;
1.29      veillard   40:     if (str == NULL) {
                     41:        fprintf(output, "(NULL)");
                     42:        return;
                     43:     }
1.1       daniel     44:     for (i = 0;i < 40;i++)
                     45:         if (str[i] == 0) return;
                     46:        else if (IS_BLANK(str[i])) fputc(' ', output);
1.27      veillard   47:        else if (str[i] >= 0x80)
                     48:             fprintf(output, "#%X", str[i]);
1.1       daniel     49:        else fputc(str[i], output);
                     50:     fprintf(output, "...");
                     51: }
                     52: 
1.18      daniel     53: void xmlDebugDumpDtd(FILE *output, xmlDtdPtr dtd, int depth) {
                     54:     int i;
                     55:     char shift[100];
                     56: 
                     57:     for (i = 0;((i < depth) && (i < 25));i++)
                     58:         shift[2 * i] = shift[2 * i + 1] = ' ';
                     59:     shift[2 * i] = shift[2 * i + 1] = 0;
                     60: 
                     61:     fprintf(output, shift);
                     62: 
                     63:     if (dtd->type != XML_DTD_NODE) {
                     64:        fprintf(output, "PBM: not a DTD\n");
                     65:        return;
                     66:     }
                     67:     if (dtd->name != NULL)
                     68:        fprintf(output, "DTD(%s)", dtd->name);
                     69:     else
                     70:        fprintf(output, "DTD");
                     71:     if (dtd->ExternalID != NULL)
                     72:        fprintf(output, ", PUBLIC %s", dtd->ExternalID);
                     73:     if (dtd->SystemID != NULL)
                     74:        fprintf(output, ", SYSTEM %s", dtd->SystemID);
                     75:     fprintf(output, "\n");
                     76:     /*
                     77:      * Do a bit of checking
                     78:      */
                     79:     if (dtd->parent == NULL)
                     80:        fprintf(output, "PBM: Dtd has no parent\n");
                     81:     if (dtd->doc == NULL)
                     82:        fprintf(output, "PBM: Dtd has no doc\n");
                     83:     if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
                     84:        fprintf(output, "PBM: Dtd doc differs from parent's one\n");
                     85:     if (dtd->prev == NULL) {
                     86:        if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
                     87:            fprintf(output, "PBM: Dtd has no prev and not first of list\n");
                     88:     } else {
                     89:        if (dtd->prev->next != (xmlNodePtr) dtd)
                     90:            fprintf(output, "PBM: Dtd prev->next : back link wrong\n");
                     91:     }
                     92:     if (dtd->next == NULL) {
                     93:        if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
                     94:            fprintf(output, "PBM: Dtd has no next and not last of list\n");
                     95:     } else {
                     96:        if (dtd->next->prev != (xmlNodePtr) dtd)
                     97:            fprintf(output, "PBM: Dtd next->prev : forward link wrong\n");
                     98:     }
                     99: }
                    100: 
                    101: void xmlDebugDumpAttrDecl(FILE *output, xmlAttributePtr attr, int depth) {
                    102:     int i;
                    103:     char shift[100];
                    104: 
                    105:     for (i = 0;((i < depth) && (i < 25));i++)
                    106:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    107:     shift[2 * i] = shift[2 * i + 1] = 0;
                    108: 
                    109:     fprintf(output, shift);
                    110: 
                    111:     if (attr->type != XML_ATTRIBUTE_DECL) {
                    112:        fprintf(output, "PBM: not a Attr\n");
                    113:        return;
                    114:     }
                    115:     if (attr->name != NULL)
                    116:        fprintf(output, "ATTRDECL(%s)", attr->name);
                    117:     else
                    118:        fprintf(output, "PBM ATTRDECL noname!!!");
                    119:     if (attr->elem != NULL)
                    120:        fprintf(output, " for %s", attr->elem);
                    121:     else
                    122:        fprintf(output, " PBM noelem!!!");
                    123:     switch (attr->atype) {
                    124:         case XML_ATTRIBUTE_CDATA:
                    125:            fprintf(output, " CDATA");
                    126:            break;
                    127:         case XML_ATTRIBUTE_ID:
                    128:            fprintf(output, " ID");
                    129:            break;
                    130:         case XML_ATTRIBUTE_IDREF:
                    131:            fprintf(output, " IDREF");
                    132:            break;
                    133:         case XML_ATTRIBUTE_IDREFS:
                    134:            fprintf(output, " IDREFS");
                    135:            break;
                    136:         case XML_ATTRIBUTE_ENTITY:
                    137:            fprintf(output, " ENTITY");
                    138:            break;
                    139:         case XML_ATTRIBUTE_ENTITIES:
                    140:            fprintf(output, " ENTITIES");
                    141:            break;
                    142:         case XML_ATTRIBUTE_NMTOKEN:
                    143:            fprintf(output, " NMTOKEN");
                    144:            break;
                    145:         case XML_ATTRIBUTE_NMTOKENS:
                    146:            fprintf(output, " NMTOKENS");
                    147:            break;
                    148:         case XML_ATTRIBUTE_ENUMERATION:
                    149:            fprintf(output, " ENUMERATION");
                    150:            break;
                    151:         case XML_ATTRIBUTE_NOTATION:
                    152:            fprintf(output, " NOTATION ");
                    153:            break;
                    154:     }
                    155:     if (attr->tree != NULL) {
                    156:        int i;
                    157:        xmlEnumerationPtr cur = attr->tree;
                    158: 
                    159:        for (i = 0;i < 5; i++) {
                    160:            if (i != 0)
                    161:                fprintf(output, "|%s", cur->name);
                    162:            else
                    163:                fprintf(output, " (%s", cur->name);
                    164:            cur = cur->next;
                    165:            if (cur == NULL) break;
                    166:        }
                    167:        if (cur == NULL)
                    168:            fprintf(output, ")");
                    169:        else
                    170:            fprintf(output, "...)");
                    171:     }
                    172:     switch (attr->def) {
                    173:         case XML_ATTRIBUTE_NONE:
                    174:            break;
                    175:         case XML_ATTRIBUTE_REQUIRED:
                    176:            fprintf(output, " REQUIRED");
                    177:            break;
                    178:         case XML_ATTRIBUTE_IMPLIED:
                    179:            fprintf(output, " IMPLIED");
                    180:            break;
                    181:         case XML_ATTRIBUTE_FIXED:
                    182:            fprintf(output, " FIXED");
                    183:            break;
                    184:     }
                    185:     if (attr->defaultValue != NULL) {
                    186:        fprintf(output, "\"");
                    187:        xmlDebugDumpString(output, attr->defaultValue);
                    188:        fprintf(output, "\"");
                    189:     }
                    190:     printf("\n");
                    191: 
                    192:     /*
                    193:      * Do a bit of checking
                    194:      */
                    195:     if (attr->parent == NULL)
                    196:        fprintf(output, "PBM: Attr has no parent\n");
                    197:     if (attr->doc == NULL)
                    198:        fprintf(output, "PBM: Attr has no doc\n");
                    199:     if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
                    200:        fprintf(output, "PBM: Attr doc differs from parent's one\n");
                    201:     if (attr->prev == NULL) {
                    202:        if ((attr->parent != NULL) && (attr->parent->children != (xmlNodePtr)attr))
                    203:            fprintf(output, "PBM: Attr has no prev and not first of list\n");
                    204:     } else {
                    205:        if (attr->prev->next != (xmlNodePtr) attr)
                    206:            fprintf(output, "PBM: Attr prev->next : back link wrong\n");
                    207:     }
                    208:     if (attr->next == NULL) {
                    209:        if ((attr->parent != NULL) && (attr->parent->last != (xmlNodePtr) attr))
                    210:            fprintf(output, "PBM: Attr has no next and not last of list\n");
                    211:     } else {
                    212:        if (attr->next->prev != (xmlNodePtr) attr)
                    213:            fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
                    214:     }
                    215: }
                    216: 
                    217: void xmlDebugDumpElemDecl(FILE *output, xmlElementPtr elem, int depth) {
                    218:     int i;
                    219:     char shift[100];
                    220: 
                    221:     for (i = 0;((i < depth) && (i < 25));i++)
                    222:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    223:     shift[2 * i] = shift[2 * i + 1] = 0;
                    224: 
                    225:     fprintf(output, shift);
                    226: 
                    227:     if (elem->type != XML_ELEMENT_DECL) {
                    228:        fprintf(output, "PBM: not a Elem\n");
                    229:        return;
                    230:     }
1.27      veillard  231:     if (elem->name != NULL) {
                    232:        fprintf(output, "ELEMDECL(");
                    233:        xmlDebugDumpString(output, elem->name);
                    234:        fprintf(output, ")");
                    235:     } else
1.18      daniel    236:        fprintf(output, "PBM ELEMDECL noname!!!");
                    237:     switch (elem->etype) {
                    238:        case XML_ELEMENT_TYPE_EMPTY: 
                    239:            fprintf(output, ", EMPTY");
                    240:            break;
                    241:        case XML_ELEMENT_TYPE_ANY: 
                    242:            fprintf(output, ", ANY");
                    243:            break;
                    244:        case XML_ELEMENT_TYPE_MIXED: 
                    245:            fprintf(output, ", MIXED ");
                    246:            break;
                    247:        case XML_ELEMENT_TYPE_ELEMENT: 
                    248:            fprintf(output, ", MIXED ");
                    249:            break;
                    250:     }
                    251:     if (elem->content != NULL) {
1.30      veillard  252:        char buf[5001];
1.18      daniel    253: 
                    254:        buf[0] = 0;
                    255:        xmlSprintfElementContent(buf, elem->content, 1);
1.30      veillard  256:        buf[5000] = 0;
1.18      daniel    257:        fprintf(output, "%s", buf);
                    258:     }
                    259:     printf("\n");
                    260: 
                    261:     /*
                    262:      * Do a bit of checking
                    263:      */
                    264:     if (elem->parent == NULL)
                    265:        fprintf(output, "PBM: Elem has no parent\n");
                    266:     if (elem->doc == NULL)
                    267:        fprintf(output, "PBM: Elem has no doc\n");
                    268:     if ((elem->parent != NULL) && (elem->doc != elem->parent->doc))
                    269:        fprintf(output, "PBM: Elem doc differs from parent's one\n");
                    270:     if (elem->prev == NULL) {
                    271:        if ((elem->parent != NULL) && (elem->parent->children != (xmlNodePtr)elem))
                    272:            fprintf(output, "PBM: Elem has no prev and not first of list\n");
                    273:     } else {
                    274:        if (elem->prev->next != (xmlNodePtr) elem)
                    275:            fprintf(output, "PBM: Elem prev->next : back link wrong\n");
                    276:     }
                    277:     if (elem->next == NULL) {
                    278:        if ((elem->parent != NULL) && (elem->parent->last != (xmlNodePtr) elem))
                    279:            fprintf(output, "PBM: Elem has no next and not last of list\n");
                    280:     } else {
                    281:        if (elem->next->prev != (xmlNodePtr) elem)
                    282:            fprintf(output, "PBM: Elem next->prev : forward link wrong\n");
                    283:     }
                    284: }
                    285: 
1.20      daniel    286: void xmlDebugDumpEntityDecl(FILE *output, xmlEntityPtr ent, int depth) {
                    287:     int i;
                    288:     char shift[100];
                    289: 
                    290:     for (i = 0;((i < depth) && (i < 25));i++)
                    291:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    292:     shift[2 * i] = shift[2 * i + 1] = 0;
                    293: 
                    294:     fprintf(output, shift);
                    295: 
                    296:     if (ent->type != XML_ENTITY_DECL) {
                    297:        fprintf(output, "PBM: not a Entity decl\n");
                    298:        return;
                    299:     }
1.27      veillard  300:     if (ent->name != NULL) {
                    301:        fprintf(output, "ENTITYDECL(");
                    302:        xmlDebugDumpString(output, ent->name);
                    303:        fprintf(output, ")");
                    304:     } else
1.20      daniel    305:        fprintf(output, "PBM ENTITYDECL noname!!!");
                    306:     switch (ent->etype) {
                    307:        case XML_INTERNAL_GENERAL_ENTITY: 
                    308:            fprintf(output, ", internal\n");
                    309:            break;
                    310:        case XML_EXTERNAL_GENERAL_PARSED_ENTITY: 
                    311:            fprintf(output, ", external parsed\n");
                    312:            break;
                    313:        case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: 
                    314:            fprintf(output, ", unparsed\n");
                    315:            break;
                    316:        case XML_INTERNAL_PARAMETER_ENTITY: 
                    317:            fprintf(output, ", parameter\n");
                    318:            break;
                    319:        case XML_EXTERNAL_PARAMETER_ENTITY: 
                    320:            fprintf(output, ", external parameter\n");
                    321:            break;
                    322:        case XML_INTERNAL_PREDEFINED_ENTITY: 
                    323:            fprintf(output, ", predefined\n");
                    324:            break;
                    325:     }
                    326:     if (ent->ExternalID) {
                    327:         fprintf(output, shift);
1.32      veillard  328:         fprintf(output, " ExternalID=%s\n", ent->ExternalID);
1.20      daniel    329:     }
                    330:     if (ent->SystemID) {
                    331:         fprintf(output, shift);
1.32      veillard  332:         fprintf(output, " SystemID=%s\n", ent->SystemID);
                    333:     }
                    334:     if (ent->URI != NULL) {
                    335:         fprintf(output, shift);
                    336:         fprintf(output, " URI=%s\n", ent->URI);
1.20      daniel    337:     }
                    338:     if (ent->content) {
                    339:         fprintf(output, shift);
1.32      veillard  340:        fprintf(output, " content=");
1.20      daniel    341:        xmlDebugDumpString(output, ent->content);
                    342:        fprintf(output, "\n");
                    343:     }
                    344: 
                    345:     /*
                    346:      * Do a bit of checking
                    347:      */
                    348:     if (ent->parent == NULL)
                    349:        fprintf(output, "PBM: Ent has no parent\n");
                    350:     if (ent->doc == NULL)
                    351:        fprintf(output, "PBM: Ent has no doc\n");
                    352:     if ((ent->parent != NULL) && (ent->doc != ent->parent->doc))
                    353:        fprintf(output, "PBM: Ent doc differs from parent's one\n");
                    354:     if (ent->prev == NULL) {
                    355:        if ((ent->parent != NULL) && (ent->parent->children != (xmlNodePtr)ent))
                    356:            fprintf(output, "PBM: Ent has no prev and not first of list\n");
                    357:     } else {
                    358:        if (ent->prev->next != (xmlNodePtr) ent)
                    359:            fprintf(output, "PBM: Ent prev->next : back link wrong\n");
                    360:     }
                    361:     if (ent->next == NULL) {
                    362:        if ((ent->parent != NULL) && (ent->parent->last != (xmlNodePtr) ent))
                    363:            fprintf(output, "PBM: Ent has no next and not last of list\n");
                    364:     } else {
                    365:        if (ent->next->prev != (xmlNodePtr) ent)
                    366:            fprintf(output, "PBM: Ent next->prev : forward link wrong\n");
                    367:     }
                    368: }
                    369: 
1.1       daniel    370: void xmlDebugDumpNamespace(FILE *output, xmlNsPtr ns, int depth) {
                    371:     int i;
                    372:     char shift[100];
                    373: 
                    374:     for (i = 0;((i < depth) && (i < 25));i++)
                    375:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    376:     shift[2 * i] = shift[2 * i + 1] = 0;
                    377: 
                    378:     fprintf(output, shift);
                    379:     if (ns->type == XML_GLOBAL_NAMESPACE)
                    380:         fprintf(output, "old ");
1.29      veillard  381:     if (ns->href == NULL) {
                    382:        if (ns->prefix != NULL)
                    383:            fprintf(output, "incomplete namespace %s href=NULL\n", ns->prefix);
                    384:        else
                    385:            fprintf(output, "incomplete default namespace href=NULL\n");
                    386:     } else {
                    387:        if (ns->prefix != NULL)
                    388:            fprintf(output, "namespace %s href=", ns->prefix);
                    389:        else
                    390:            fprintf(output, "default namespace href=");
1.10      daniel    391: 
1.29      veillard  392:        xmlDebugDumpString(output, ns->href);
                    393:        fprintf(output, "\n");
                    394:     }
1.1       daniel    395: }
                    396: 
                    397: void xmlDebugDumpNamespaceList(FILE *output, xmlNsPtr ns, int depth) {
                    398:     while (ns != NULL) {
                    399:         xmlDebugDumpNamespace(output, ns, depth);
                    400:        ns = ns->next;
                    401:     }
                    402: }
                    403: 
                    404: void xmlDebugDumpEntity(FILE *output, xmlEntityPtr ent, int depth) {
                    405:     int i;
                    406:     char shift[100];
                    407: 
                    408:     for (i = 0;((i < depth) && (i < 25));i++)
                    409:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    410:     shift[2 * i] = shift[2 * i + 1] = 0;
                    411: 
                    412:     fprintf(output, shift);
1.19      daniel    413:     switch (ent->etype) {
1.1       daniel    414:         case XML_INTERNAL_GENERAL_ENTITY:
                    415:            fprintf(output, "INTERNAL_GENERAL_ENTITY ");
                    416:            break;
                    417:         case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                    418:            fprintf(output, "EXTERNAL_GENERAL_PARSED_ENTITY ");
                    419:            break;
                    420:         case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                    421:            fprintf(output, "EXTERNAL_GENERAL_UNPARSED_ENTITY ");
                    422:            break;
                    423:         case XML_INTERNAL_PARAMETER_ENTITY:
                    424:            fprintf(output, "INTERNAL_PARAMETER_ENTITY ");
                    425:            break;
                    426:         case XML_EXTERNAL_PARAMETER_ENTITY:
                    427:            fprintf(output, "EXTERNAL_PARAMETER_ENTITY ");
                    428:            break;
                    429:        default:
1.19      daniel    430:            fprintf(output, "ENTITY_%d ! ", ent->etype);
1.1       daniel    431:     }
                    432:     fprintf(output, "%s\n", ent->name);
                    433:     if (ent->ExternalID) {
                    434:         fprintf(output, shift);
                    435:         fprintf(output, "ExternalID=%s\n", ent->ExternalID);
                    436:     }
                    437:     if (ent->SystemID) {
                    438:         fprintf(output, shift);
                    439:         fprintf(output, "SystemID=%s\n", ent->SystemID);
                    440:     }
1.32      veillard  441:     if (ent->URI) {
                    442:         fprintf(output, shift);
                    443:         fprintf(output, "URI=%s\n", ent->URI);
                    444:     }
1.1       daniel    445:     if (ent->content) {
                    446:         fprintf(output, shift);
                    447:        fprintf(output, "content=");
                    448:        xmlDebugDumpString(output, ent->content);
                    449:        fprintf(output, "\n");
                    450:     }
                    451: }
                    452: 
                    453: void xmlDebugDumpAttr(FILE *output, xmlAttrPtr attr, int depth) {
                    454:     int i;
                    455:     char shift[100];
                    456: 
                    457:     for (i = 0;((i < depth) && (i < 25));i++)
                    458:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    459:     shift[2 * i] = shift[2 * i + 1] = 0;
                    460: 
                    461:     fprintf(output, shift);
1.18      daniel    462: 
1.27      veillard  463:     fprintf(output, "ATTRIBUTE ");
                    464:     xmlDebugDumpString(output, attr->name);
                    465:     fprintf(output, "\n");
1.16      daniel    466:     if (attr->children != NULL) 
                    467:         xmlDebugDumpNodeList(output, attr->children, depth + 1);
1.18      daniel    468: 
                    469:     /*
                    470:      * Do a bit of checking
                    471:      */
                    472:     if (attr->parent == NULL)
                    473:        fprintf(output, "PBM: Attr has no parent\n");
                    474:     if (attr->doc == NULL)
                    475:        fprintf(output, "PBM: Attr has no doc\n");
                    476:     if ((attr->parent != NULL) && (attr->doc != attr->parent->doc))
                    477:        fprintf(output, "PBM: Attr doc differs from parent's one\n");
                    478:     if (attr->prev == NULL) {
                    479:        if ((attr->parent != NULL) && (attr->parent->properties != attr))
                    480:            fprintf(output, "PBM: Attr has no prev and not first of list\n");
                    481:     } else {
                    482:        if (attr->prev->next != attr)
                    483:            fprintf(output, "PBM: Attr prev->next : back link wrong\n");
                    484:     }
                    485:     if (attr->next != NULL) {
                    486:        if (attr->next->prev != attr)
                    487:            fprintf(output, "PBM: Attr next->prev : forward link wrong\n");
                    488:     }
1.1       daniel    489: }
                    490: 
                    491: void xmlDebugDumpAttrList(FILE *output, xmlAttrPtr attr, int depth) {
                    492:     while (attr != NULL) {
                    493:         xmlDebugDumpAttr(output, attr, depth);
                    494:        attr = attr->next;
                    495:     }
                    496: }
                    497: 
1.3       daniel    498: void xmlDebugDumpOneNode(FILE *output, xmlNodePtr node, int depth) {
1.1       daniel    499:     int i;
                    500:     char shift[100];
                    501: 
                    502:     for (i = 0;((i < depth) && (i < 25));i++)
                    503:         shift[2 * i] = shift[2 * i + 1] = ' ';
                    504:     shift[2 * i] = shift[2 * i + 1] = 0;
                    505: 
                    506:     switch (node->type) {
                    507:        case XML_ELEMENT_NODE:
1.21      daniel    508:            fprintf(output, shift);
1.1       daniel    509:            fprintf(output, "ELEMENT ");
1.27      veillard  510:            if (node->ns != NULL) {
                    511:                xmlDebugDumpString(output, node->ns->prefix);
                    512:                fprintf(output, ":");
                    513:            }
                    514:            xmlDebugDumpString(output, node->name);
                    515:            fprintf(output, "\n");
1.1       daniel    516:            break;
                    517:        case XML_ATTRIBUTE_NODE:
1.21      daniel    518:            fprintf(output, shift);
1.1       daniel    519:            fprintf(output, "Error, ATTRIBUTE found here\n");
                    520:            break;
                    521:        case XML_TEXT_NODE:
1.21      daniel    522:            fprintf(output, shift);
1.1       daniel    523:            fprintf(output, "TEXT\n");
                    524:            break;
                    525:        case XML_CDATA_SECTION_NODE:
1.21      daniel    526:            fprintf(output, shift);
1.1       daniel    527:            fprintf(output, "CDATA_SECTION\n");
                    528:            break;
                    529:        case XML_ENTITY_REF_NODE:
1.21      daniel    530:            fprintf(output, shift);
1.15      daniel    531:            fprintf(output, "ENTITY_REF(%s)\n", node->name);
1.1       daniel    532:            break;
                    533:        case XML_ENTITY_NODE:
1.21      daniel    534:            fprintf(output, shift);
1.1       daniel    535:            fprintf(output, "ENTITY\n");
                    536:            break;
                    537:        case XML_PI_NODE:
1.21      daniel    538:            fprintf(output, shift);
1.4       daniel    539:            fprintf(output, "PI %s\n", node->name);
1.1       daniel    540:            break;
                    541:        case XML_COMMENT_NODE:
1.21      daniel    542:            fprintf(output, shift);
1.1       daniel    543:            fprintf(output, "COMMENT\n");
                    544:            break;
                    545:        case XML_DOCUMENT_NODE:
1.7       daniel    546:        case XML_HTML_DOCUMENT_NODE:
1.21      daniel    547:            fprintf(output, shift);
1.1       daniel    548:            fprintf(output, "Error, DOCUMENT found here\n");
                    549:            break;
                    550:        case XML_DOCUMENT_TYPE_NODE:
1.21      daniel    551:            fprintf(output, shift);
1.1       daniel    552:            fprintf(output, "DOCUMENT_TYPE\n");
                    553:            break;
                    554:        case XML_DOCUMENT_FRAG_NODE:
1.21      daniel    555:            fprintf(output, shift);
1.1       daniel    556:            fprintf(output, "DOCUMENT_FRAG\n");
                    557:            break;
                    558:        case XML_NOTATION_NODE:
                    559:            fprintf(output, "NOTATION\n");
                    560:            break;
1.18      daniel    561:        case XML_DTD_NODE:
1.21      daniel    562:            xmlDebugDumpDtd(output, (xmlDtdPtr) node, depth);
1.18      daniel    563:            return;
                    564:        case XML_ELEMENT_DECL:
1.21      daniel    565:            xmlDebugDumpElemDecl(output, (xmlElementPtr) node, depth);
1.18      daniel    566:            return;
                    567:        case XML_ATTRIBUTE_DECL:
1.21      daniel    568:            xmlDebugDumpAttrDecl(output, (xmlAttributePtr) node, depth);
1.18      daniel    569:            return;
1.20      daniel    570:         case XML_ENTITY_DECL:
1.21      daniel    571:            xmlDebugDumpEntityDecl(output, (xmlEntityPtr) node, depth);
1.20      daniel    572:            return;
1.1       daniel    573:        default:
1.21      daniel    574:            fprintf(output, shift);
1.40      veillard  575:            fprintf(output, "NODE_%d !!!\n", node->type);
                    576:            return;
1.1       daniel    577:     }
                    578:     if (node->doc == NULL) {
                    579:         fprintf(output, shift);
                    580:        fprintf(output, "doc == NULL !!!\n");
                    581:     }
                    582:     if (node->nsDef != NULL) 
                    583:         xmlDebugDumpNamespaceList(output, node->nsDef, depth + 1);
                    584:     if (node->properties != NULL)
                    585:        xmlDebugDumpAttrList(output, node->properties, depth + 1);
                    586:     if (node->type != XML_ENTITY_REF_NODE) {
                    587:        if (node->content != NULL) {
1.38      veillard  588:             shift[2 * i] = shift[2 * i + 1] = ' ' ;
                    589:             shift[2 * i + 2] = shift[2 * i + 3] = 0 ;
1.1       daniel    590:            fprintf(output, shift);
                    591:            fprintf(output, "content=");
1.8       daniel    592: #ifndef XML_USE_BUFFER_CONTENT     
1.1       daniel    593:            xmlDebugDumpString(output, node->content);
1.8       daniel    594: #else
                    595:            xmlDebugDumpString(output, xmlBufferContent(node->content));
                    596: #endif
1.1       daniel    597:            fprintf(output, "\n");
                    598:        }
                    599:     } else {
                    600:         xmlEntityPtr ent;
                    601:        ent = xmlGetDocEntity(node->doc, node->name);
                    602:        if (ent != NULL)
                    603:            xmlDebugDumpEntity(output, ent, depth + 1);
1.18      daniel    604:     }
                    605:     /*
                    606:      * Do a bit of checking
                    607:      */
                    608:     if (node->parent == NULL)
                    609:        fprintf(output, "PBM: Node has no parent\n");
                    610:     if (node->doc == NULL)
                    611:        fprintf(output, "PBM: Node has no doc\n");
                    612:     if ((node->parent != NULL) && (node->doc != node->parent->doc))
                    613:        fprintf(output, "PBM: Node doc differs from parent's one\n");
                    614:     if (node->prev == NULL) {
                    615:        if ((node->parent != NULL) && (node->parent->children != node))
                    616:            fprintf(output, "PBM: Node has no prev and not first of list\n");
                    617:     } else {
                    618:        if (node->prev->next != node)
                    619:            fprintf(output, "PBM: Node prev->next : back link wrong\n");
                    620:     }
                    621:     if (node->next == NULL) {
                    622:        if ((node->parent != NULL) && (node->parent->last != node))
                    623:            fprintf(output, "PBM: Node has no next and not last of list\n");
                    624:     } else {
                    625:        if (node->next->prev != node)
                    626:            fprintf(output, "PBM: Node next->prev : forward link wrong\n");
1.1       daniel    627:     }
1.3       daniel    628: }
                    629: 
                    630: void xmlDebugDumpNode(FILE *output, xmlNodePtr node, int depth) {
                    631:     xmlDebugDumpOneNode(output, node, depth);
1.32      veillard  632:     if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE))
1.16      daniel    633:        xmlDebugDumpNodeList(output, node->children, depth + 1);
1.1       daniel    634: }
                    635: 
                    636: void xmlDebugDumpNodeList(FILE *output, xmlNodePtr node, int depth) {
                    637:     while (node != NULL) {
                    638:         xmlDebugDumpNode(output, node, depth);
                    639:        node = node->next;
                    640:     }
                    641: }
                    642: 
                    643: 
1.12      daniel    644: void xmlDebugDumpDocumentHead(FILE *output, xmlDocPtr doc) {
1.1       daniel    645:     if (output == NULL) output = stdout;
                    646:     if (doc == NULL) {
                    647:         fprintf(output, "DOCUMENT == NULL !\n");
                    648:        return;
                    649:     }
                    650: 
                    651:     switch (doc->type) {
                    652:        case XML_ELEMENT_NODE:
                    653:            fprintf(output, "Error, ELEMENT found here ");
                    654:            break;
                    655:        case XML_ATTRIBUTE_NODE:
                    656:            fprintf(output, "Error, ATTRIBUTE found here\n");
                    657:            break;
                    658:        case XML_TEXT_NODE:
                    659:            fprintf(output, "Error, TEXT\n");
                    660:            break;
                    661:        case XML_CDATA_SECTION_NODE:
                    662:            fprintf(output, "Error, CDATA_SECTION\n");
                    663:            break;
                    664:        case XML_ENTITY_REF_NODE:
                    665:            fprintf(output, "Error, ENTITY_REF\n");
                    666:            break;
                    667:        case XML_ENTITY_NODE:
                    668:            fprintf(output, "Error, ENTITY\n");
                    669:            break;
                    670:        case XML_PI_NODE:
                    671:            fprintf(output, "Error, PI\n");
                    672:            break;
                    673:        case XML_COMMENT_NODE:
                    674:            fprintf(output, "Error, COMMENT\n");
                    675:            break;
                    676:        case XML_DOCUMENT_NODE:
                    677:            fprintf(output, "DOCUMENT\n");
1.7       daniel    678:            break;
                    679:        case XML_HTML_DOCUMENT_NODE:
                    680:            fprintf(output, "HTML DOCUMENT\n");
1.1       daniel    681:            break;
                    682:        case XML_DOCUMENT_TYPE_NODE:
                    683:            fprintf(output, "Error, DOCUMENT_TYPE\n");
                    684:            break;
                    685:        case XML_DOCUMENT_FRAG_NODE:
                    686:            fprintf(output, "Error, DOCUMENT_FRAG\n");
                    687:            break;
                    688:        case XML_NOTATION_NODE:
                    689:            fprintf(output, "Error, NOTATION\n");
                    690:            break;
                    691:        default:
                    692:            fprintf(output, "NODE_%d\n", doc->type);
                    693:     }
                    694:     if (doc->name != NULL) {
                    695:        fprintf(output, "name=");
1.5       daniel    696:         xmlDebugDumpString(output, BAD_CAST doc->name);
1.1       daniel    697:        fprintf(output, "\n");
                    698:     }
                    699:     if (doc->version != NULL) {
                    700:        fprintf(output, "version=");
                    701:         xmlDebugDumpString(output, doc->version);
                    702:        fprintf(output, "\n");
                    703:     }
                    704:     if (doc->encoding != NULL) {
                    705:        fprintf(output, "encoding=");
                    706:         xmlDebugDumpString(output, doc->encoding);
1.32      veillard  707:        fprintf(output, "\n");
                    708:     }
                    709:     if (doc->URL != NULL) {
                    710:        fprintf(output, "URL=");
                    711:         xmlDebugDumpString(output, doc->URL);
1.1       daniel    712:        fprintf(output, "\n");
                    713:     }
                    714:     if (doc->standalone)
                    715:         fprintf(output, "standalone=true\n");
                    716:     if (doc->oldNs != NULL) 
                    717:         xmlDebugDumpNamespaceList(output, doc->oldNs, 0);
1.12      daniel    718: }
                    719: 
                    720: void xmlDebugDumpDocument(FILE *output, xmlDocPtr doc) {
                    721:     if (output == NULL) output = stdout;
                    722:     if (doc == NULL) {
                    723:         fprintf(output, "DOCUMENT == NULL !\n");
                    724:        return;
                    725:     }
                    726:     xmlDebugDumpDocumentHead(output, doc);
                    727:     if (((doc->type == XML_DOCUMENT_NODE) ||
                    728:          (doc->type == XML_HTML_DOCUMENT_NODE)) &&
1.16      daniel    729:         (doc->children != NULL))
                    730:         xmlDebugDumpNodeList(output, doc->children, 1);
1.12      daniel    731: }    
1.30      veillard  732: 
                    733: void xmlDebugDumpDTD(FILE *output, xmlDtdPtr dtd) {
                    734:     if (dtd == NULL)
                    735:        return;
                    736:     if (dtd->type != XML_DTD_NODE) {
                    737:        fprintf(output, "PBM: not a DTD\n");
                    738:        return;
                    739:     }
                    740:     if (dtd->name != NULL)
                    741:        fprintf(output, "DTD(%s)", dtd->name);
                    742:     else
                    743:        fprintf(output, "DTD");
                    744:     if (dtd->ExternalID != NULL)
                    745:        fprintf(output, ", PUBLIC %s", dtd->ExternalID);
                    746:     if (dtd->SystemID != NULL)
                    747:        fprintf(output, ", SYSTEM %s", dtd->SystemID);
                    748:     fprintf(output, "\n");
                    749:     /*
                    750:      * Do a bit of checking
                    751:      */
                    752:     if ((dtd->parent != NULL) && (dtd->doc != dtd->parent->doc))
                    753:        fprintf(output, "PBM: Dtd doc differs from parent's one\n");
                    754:     if (dtd->prev == NULL) {
                    755:        if ((dtd->parent != NULL) && (dtd->parent->children != (xmlNodePtr)dtd))
                    756:            fprintf(output, "PBM: Dtd has no prev and not first of list\n");
                    757:     } else {
                    758:        if (dtd->prev->next != (xmlNodePtr) dtd)
                    759:            fprintf(output, "PBM: Dtd prev->next : back link wrong\n");
                    760:     }
                    761:     if (dtd->next == NULL) {
                    762:        if ((dtd->parent != NULL) && (dtd->parent->last != (xmlNodePtr) dtd))
                    763:            fprintf(output, "PBM: Dtd has no next and not last of list\n");
                    764:     } else {
                    765:        if (dtd->next->prev != (xmlNodePtr) dtd)
                    766:            fprintf(output, "PBM: Dtd next->prev : forward link wrong\n");
                    767:     }
                    768:     if (dtd->children == NULL)
                    769:        fprintf(output, "    DTD is empty\n");
                    770:     else
                    771:         xmlDebugDumpNodeList(output, dtd->children, 1);
                    772: }
1.9       daniel    773: 
                    774: void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
                    775:     int i;
1.42    ! veillard  776:     xmlHashEntryPtr ent;
1.9       daniel    777:     xmlEntityPtr cur;
                    778: 
                    779:     if (output == NULL) output = stdout;
                    780:     if (doc == NULL) {
                    781:         fprintf(output, "DOCUMENT == NULL !\n");
                    782:        return;
                    783:     }
                    784: 
                    785:     switch (doc->type) {
                    786:        case XML_ELEMENT_NODE:
                    787:            fprintf(output, "Error, ELEMENT found here ");
                    788:            break;
                    789:        case XML_ATTRIBUTE_NODE:
                    790:            fprintf(output, "Error, ATTRIBUTE found here\n");
                    791:            break;
                    792:        case XML_TEXT_NODE:
                    793:            fprintf(output, "Error, TEXT\n");
                    794:            break;
                    795:        case XML_CDATA_SECTION_NODE:
                    796:            fprintf(output, "Error, CDATA_SECTION\n");
                    797:            break;
                    798:        case XML_ENTITY_REF_NODE:
                    799:            fprintf(output, "Error, ENTITY_REF\n");
                    800:            break;
                    801:        case XML_ENTITY_NODE:
                    802:            fprintf(output, "Error, ENTITY\n");
                    803:            break;
                    804:        case XML_PI_NODE:
                    805:            fprintf(output, "Error, PI\n");
                    806:            break;
                    807:        case XML_COMMENT_NODE:
                    808:            fprintf(output, "Error, COMMENT\n");
                    809:            break;
                    810:        case XML_DOCUMENT_NODE:
                    811:            fprintf(output, "DOCUMENT\n");
                    812:            break;
                    813:        case XML_HTML_DOCUMENT_NODE:
                    814:            fprintf(output, "HTML DOCUMENT\n");
                    815:            break;
                    816:        case XML_DOCUMENT_TYPE_NODE:
                    817:            fprintf(output, "Error, DOCUMENT_TYPE\n");
                    818:            break;
                    819:        case XML_DOCUMENT_FRAG_NODE:
                    820:            fprintf(output, "Error, DOCUMENT_FRAG\n");
                    821:            break;
                    822:        case XML_NOTATION_NODE:
                    823:            fprintf(output, "Error, NOTATION\n");
                    824:            break;
                    825:        default:
                    826:            fprintf(output, "NODE_%d\n", doc->type);
                    827:     }
                    828:     if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
                    829:         xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) 
                    830:                                    doc->intSubset->entities;
                    831:        fprintf(output, "Entities in internal subset\n");
1.42    ! veillard  832:        for (i = 0;i < table->size;i++) {
        !           833:            ent = table->table[i];
        !           834:            while (ent != NULL) {
        !           835:                cur = (xmlEntityPtr) ent->payload;
1.28      veillard  836:                fprintf(output, "%d : %s : ", i, cur->name);
                    837:                switch (cur->etype) {
                    838:                    case XML_INTERNAL_GENERAL_ENTITY:
                    839:                        fprintf(output, "INTERNAL GENERAL, ");
                    840:                        break;
                    841:                    case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                    842:                        fprintf(output, "EXTERNAL PARSED, ");
                    843:                        break;
                    844:                    case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                    845:                        fprintf(output, "EXTERNAL UNPARSED, ");
                    846:                        break;
                    847:                    case XML_INTERNAL_PARAMETER_ENTITY:
                    848:                        fprintf(output, "INTERNAL PARAMETER, ");
                    849:                        break;
                    850:                    case XML_EXTERNAL_PARAMETER_ENTITY:
                    851:                        fprintf(output, "EXTERNAL PARAMETER, ");
                    852:                        break;
                    853:                    default:
                    854:                        fprintf(output, "UNKNOWN TYPE %d",
                    855:                                cur->etype);
                    856:                }
                    857:                if (cur->ExternalID != NULL) 
                    858:                    fprintf(output, "ID \"%s\"", cur->ExternalID);
                    859:                if (cur->SystemID != NULL)
                    860:                    fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
                    861:                if (cur->orig != NULL)
                    862:                    fprintf(output, "\n orig \"%s\"", cur->orig);
                    863:                if (cur->content != NULL)
                    864:                    fprintf(output, "\n content \"%s\"", cur->content);
                    865:                fprintf(output, "\n");  
1.42    ! veillard  866:                ent = ent->next;
1.9       daniel    867:            }
                    868:        }
                    869:     } else
                    870:        fprintf(output, "No entities in internal subset\n");
                    871:     if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
                    872:         xmlEntitiesTablePtr table = (xmlEntitiesTablePtr) 
                    873:                                    doc->extSubset->entities;
                    874:        fprintf(output, "Entities in external subset\n");
1.42    ! veillard  875:        for (i = 0;i < table->size;i++) {
        !           876:            ent = table->table[i];
        !           877:            while (ent != NULL) {
        !           878:                cur = (xmlEntityPtr) ent->payload;
1.28      veillard  879:                fprintf(output, "%d : %s : ", i, cur->name);
                    880:                switch (cur->etype) {
                    881:                    case XML_INTERNAL_GENERAL_ENTITY:
                    882:                        fprintf(output, "INTERNAL GENERAL, ");
                    883:                        break;
                    884:                    case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
                    885:                        fprintf(output, "EXTERNAL PARSED, ");
                    886:                        break;
                    887:                    case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
                    888:                        fprintf(output, "EXTERNAL UNPARSED, ");
                    889:                        break;
                    890:                    case XML_INTERNAL_PARAMETER_ENTITY:
                    891:                        fprintf(output, "INTERNAL PARAMETER, ");
                    892:                        break;
                    893:                    case XML_EXTERNAL_PARAMETER_ENTITY:
                    894:                        fprintf(output, "EXTERNAL PARAMETER, ");
                    895:                        break;
                    896:                    default:
                    897:                        fprintf(output, "UNKNOWN TYPE %d",
                    898:                                cur->etype);
                    899:                }
                    900:                if (cur->ExternalID != NULL) 
                    901:                    fprintf(output, "ID \"%s\"", cur->ExternalID);
                    902:                if (cur->SystemID != NULL)
                    903:                    fprintf(output, "SYSTEM \"%s\"", cur->SystemID);
                    904:                if (cur->orig != NULL)
                    905:                    fprintf(output, "\n orig \"%s\"", cur->orig);
                    906:                if (cur->content != NULL)
                    907:                    fprintf(output, "\n content \"%s\"", cur->content);
                    908:                fprintf(output, "\n");  
1.42    ! veillard  909:                ent = ent->next;
1.9       daniel    910:            }
                    911:        }
                    912:     } else
                    913:        fprintf(output, "No entities in external subset\n");
                    914: }
1.12      daniel    915: 
                    916: static int xmlLsCountNode(xmlNodePtr node) {
                    917:     int ret = 0;
                    918:     xmlNodePtr list = NULL;
                    919: 
                    920:     switch (node->type) {
                    921:        case XML_ELEMENT_NODE:
1.16      daniel    922:            list = node->children;
1.12      daniel    923:            break;
                    924:        case XML_DOCUMENT_NODE:
                    925:        case XML_HTML_DOCUMENT_NODE:
1.33      veillard  926: #ifdef LIBXML_SGML_ENABLED
                    927:        case XML_SGML_DOCUMENT_NODE:
                    928: #endif
1.16      daniel    929:            list = ((xmlDocPtr) node)->children;
1.12      daniel    930:            break;
                    931:        case XML_ATTRIBUTE_NODE:
1.16      daniel    932:            list = ((xmlAttrPtr) node)->children;
1.12      daniel    933:            break;
                    934:        case XML_TEXT_NODE:
                    935:        case XML_CDATA_SECTION_NODE:
                    936:        case XML_PI_NODE:
                    937:        case XML_COMMENT_NODE:
                    938:            if (node->content != NULL) {
                    939: #ifndef XML_USE_BUFFER_CONTENT     
                    940:                ret = xmlStrlen(node->content);
                    941: #else
                    942:                ret = xmlBufferLength(node->content);
                    943: #endif
                    944:             }
                    945:            break;
                    946:        case XML_ENTITY_REF_NODE:
                    947:        case XML_DOCUMENT_TYPE_NODE:
                    948:        case XML_ENTITY_NODE:
                    949:        case XML_DOCUMENT_FRAG_NODE:
                    950:        case XML_NOTATION_NODE:
1.16      daniel    951:        case XML_DTD_NODE:
1.17      daniel    952:         case XML_ELEMENT_DECL:
                    953:         case XML_ATTRIBUTE_DECL:
1.20      daniel    954:         case XML_ENTITY_DECL:
1.12      daniel    955:            ret = 1;
                    956:            break;
                    957:     }
                    958:     for (;list != NULL;ret++) 
                    959:         list = list->next;
                    960:     return(ret);
                    961: }
                    962: 
                    963: void xmlLsOneNode(FILE *output, xmlNodePtr node) {
                    964:     switch (node->type) {
                    965:        case XML_ELEMENT_NODE:
                    966:            fprintf(output, "-");
                    967:            break;
                    968:        case XML_ATTRIBUTE_NODE:
                    969:            fprintf(output, "a");
                    970:            break;
                    971:        case XML_TEXT_NODE:
                    972:            fprintf(output, "t");
                    973:            break;
                    974:        case XML_CDATA_SECTION_NODE:
                    975:            fprintf(output, "c");
                    976:            break;
                    977:        case XML_ENTITY_REF_NODE:
                    978:            fprintf(output, "e");
                    979:            break;
                    980:        case XML_ENTITY_NODE:
                    981:            fprintf(output, "E");
                    982:            break;
                    983:        case XML_PI_NODE:
                    984:            fprintf(output, "p");
                    985:            break;
                    986:        case XML_COMMENT_NODE:
                    987:            fprintf(output, "c");
                    988:            break;
                    989:        case XML_DOCUMENT_NODE:
                    990:            fprintf(output, "d");
                    991:            break;
                    992:        case XML_HTML_DOCUMENT_NODE:
                    993:            fprintf(output, "h");
                    994:            break;
                    995:        case XML_DOCUMENT_TYPE_NODE:
                    996:            fprintf(output, "T");
                    997:            break;
                    998:        case XML_DOCUMENT_FRAG_NODE:
                    999:            fprintf(output, "F");
                   1000:            break;
                   1001:        case XML_NOTATION_NODE:
                   1002:            fprintf(output, "N");
                   1003:            break;
                   1004:        default:
                   1005:            fprintf(output, "?");
                   1006:     }
                   1007:     if (node->properties != NULL)
                   1008:        fprintf(output, "a");
                   1009:     else       
                   1010:        fprintf(output, "-");
                   1011:     if (node->nsDef != NULL) 
                   1012:        fprintf(output, "n");
                   1013:     else       
                   1014:        fprintf(output, "-");
                   1015: 
                   1016:     fprintf(output, " %8d ", xmlLsCountNode(node));
                   1017: 
                   1018:     switch (node->type) {
                   1019:        case XML_ELEMENT_NODE:
                   1020:            if (node->name != NULL)
                   1021:                fprintf(output, "%s", node->name);
                   1022:            break;
                   1023:        case XML_ATTRIBUTE_NODE:
                   1024:            if (node->name != NULL)
                   1025:                fprintf(output, "%s", node->name);
                   1026:            break;
                   1027:        case XML_TEXT_NODE:
                   1028:            if (node->content != NULL) {
                   1029: #ifndef XML_USE_BUFFER_CONTENT     
                   1030:                xmlDebugDumpString(output, node->content);
                   1031: #else
                   1032:                xmlDebugDumpString(output, xmlBufferContent(node->content));
                   1033: #endif
                   1034:             }
                   1035:            break;
                   1036:        case XML_CDATA_SECTION_NODE:
                   1037:            break;
                   1038:        case XML_ENTITY_REF_NODE:
                   1039:            if (node->name != NULL)
                   1040:                fprintf(output, "%s", node->name);
                   1041:            break;
                   1042:        case XML_ENTITY_NODE:
                   1043:            if (node->name != NULL)
                   1044:                fprintf(output, "%s", node->name);
                   1045:            break;
                   1046:        case XML_PI_NODE:
                   1047:            if (node->name != NULL)
                   1048:                fprintf(output, "%s", node->name);
                   1049:            break;
                   1050:        case XML_COMMENT_NODE:
                   1051:            break;
                   1052:        case XML_DOCUMENT_NODE:
                   1053:            break;
                   1054:        case XML_HTML_DOCUMENT_NODE:
                   1055:            break;
                   1056:        case XML_DOCUMENT_TYPE_NODE:
                   1057:            break;
                   1058:        case XML_DOCUMENT_FRAG_NODE:
                   1059:            break;
                   1060:        case XML_NOTATION_NODE:
                   1061:            break;
                   1062:        default:
                   1063:            if (node->name != NULL)
                   1064:                fprintf(output, "%s", node->name);
                   1065:     }
                   1066:     fprintf(output, "\n");
                   1067: }
                   1068: 
                   1069: /****************************************************************
                   1070:  *                                                             *
                   1071:  *             The XML shell related functions                 *
                   1072:  *                                                             *
                   1073:  ****************************************************************/
                   1074: 
                   1075: /*
                   1076:  * TODO: Improvement/cleanups for the XML shell
                   1077:  *     - allow to shell out an editor on a subpart
                   1078:  *     - cleanup function registrations (with help) and calling
                   1079:  *     - provide registration routines
                   1080:  */
                   1081: 
                   1082: /**
                   1083:  * xmlShellList:
                   1084:  * @ctxt:  the shell context
                   1085:  * @arg:  unused
                   1086:  * @node:  a node
                   1087:  * @node2:  unused
                   1088:  *
                   1089:  * Implements the XML shell function "ls"
                   1090:  * Does an Unix like listing of the given node (like a directory)
                   1091:  *
                   1092:  * Returns 0
                   1093:  */
                   1094: int
                   1095: xmlShellList(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
                   1096:                   xmlNodePtr node2) {
                   1097:     xmlNodePtr cur;
                   1098: 
                   1099:     if ((node->type == XML_DOCUMENT_NODE) ||
                   1100:         (node->type == XML_HTML_DOCUMENT_NODE)) {
1.16      daniel   1101:         cur = ((xmlDocPtr) node)->children;
                   1102:     } else if (node->children != NULL) {
                   1103:         cur = node->children;
1.12      daniel   1104:     } else {
                   1105:        xmlLsOneNode(stdout, node);
                   1106:         return(0);
                   1107:     }
                   1108:     while (cur != NULL) {
                   1109:        xmlLsOneNode(stdout, cur);
                   1110:        cur = cur->next;
                   1111:     }
                   1112:     return(0);
                   1113: }
                   1114: 
                   1115: /**
                   1116:  * xmlShellDir:
                   1117:  * @ctxt:  the shell context
                   1118:  * @arg:  unused
                   1119:  * @node:  a node
                   1120:  * @node2:  unused
                   1121:  *
                   1122:  * Implements the XML shell function "dir"
                   1123:  * dumps informations about the node (namespace, attributes, content).
                   1124:  *
                   1125:  * Returns 0
                   1126:  */
                   1127: int
                   1128: xmlShellDir(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
                   1129:                   xmlNodePtr node2) {
                   1130:     if ((node->type == XML_DOCUMENT_NODE) ||
                   1131:         (node->type == XML_HTML_DOCUMENT_NODE)) {
                   1132:        xmlDebugDumpDocumentHead(stdout, (xmlDocPtr) node);
                   1133:     } else if (node->type == XML_ATTRIBUTE_NODE) {
                   1134:        xmlDebugDumpAttr(stdout, (xmlAttrPtr) node, 0);
                   1135:     } else {
                   1136:        xmlDebugDumpOneNode(stdout, node, 0);
                   1137:     }
                   1138:     return(0);
                   1139: }
                   1140: 
                   1141: /**
                   1142:  * xmlShellCat:
                   1143:  * @ctxt:  the shell context
                   1144:  * @arg:  unused
                   1145:  * @node:  a node
                   1146:  * @node2:  unused
                   1147:  *
                   1148:  * Implements the XML shell function "cat"
                   1149:  * dumps the serialization node content (XML or HTML).
                   1150:  *
                   1151:  * Returns 0
                   1152:  */
                   1153: int
                   1154: xmlShellCat(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node,
                   1155:                   xmlNodePtr node2) {
1.13      daniel   1156:     if (ctxt->doc->type == XML_HTML_DOCUMENT_NODE) {
1.23      daniel   1157: #ifdef LIBXML_HTML_ENABLED
1.13      daniel   1158:        if (node->type == XML_HTML_DOCUMENT_NODE)
                   1159:            htmlDocDump(stdout, (htmlDocPtr) node);
                   1160:        else
1.14      daniel   1161:            htmlNodeDumpFile(stdout, ctxt->doc, node);
1.23      daniel   1162: #else
                   1163:        if (node->type == XML_DOCUMENT_NODE)
                   1164:            xmlDocDump(stdout, (xmlDocPtr) node);
                   1165:        else
                   1166:            xmlElemDump(stdout, ctxt->doc, node);
                   1167: #endif /* LIBXML_HTML_ENABLED */
1.13      daniel   1168:     } else {
                   1169:        if (node->type == XML_DOCUMENT_NODE)
                   1170:            xmlDocDump(stdout, (xmlDocPtr) node);
                   1171:        else
                   1172:            xmlElemDump(stdout, ctxt->doc, node);
                   1173:     }
1.12      daniel   1174:     printf("\n");
                   1175:     return(0);
                   1176: }
                   1177: 
                   1178: /**
                   1179:  * xmlShellLoad:
                   1180:  * @ctxt:  the shell context
                   1181:  * @filename:  the file name
                   1182:  * @node:  unused
                   1183:  * @node2:  unused
                   1184:  *
                   1185:  * Implements the XML shell function "load"
                   1186:  * loads a new document specified by the filename
                   1187:  *
                   1188:  * Returns 0 or -1 if loading failed
                   1189:  */
                   1190: int
                   1191: xmlShellLoad(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
                   1192:              xmlNodePtr node2) {
                   1193:     xmlDocPtr doc;
                   1194:     int html = 0;
                   1195: 
                   1196:     if (ctxt->doc != NULL)
                   1197:        html = (ctxt->doc->type == XML_HTML_DOCUMENT_NODE);
                   1198: 
                   1199:     if (html) {
1.23      daniel   1200: #ifdef LIBXML_HTML_ENABLED
1.12      daniel   1201:        doc = htmlParseFile(filename, NULL);
1.23      daniel   1202: #else  
                   1203:        printf("HTML support not compiled in\n");
                   1204:        doc = NULL;
                   1205: #endif /* LIBXML_HTML_ENABLED */
1.12      daniel   1206:     } else {
                   1207:        doc = xmlParseFile(filename);
                   1208:     }
                   1209:     if (doc != NULL) {
                   1210:         if (ctxt->loaded == 1) {
                   1211:            xmlFreeDoc(ctxt->doc);
                   1212:        }
                   1213:        ctxt->loaded = 1;
1.23      daniel   1214: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1215:        xmlXPathFreeContext(ctxt->pctxt);
1.23      daniel   1216: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1217:        xmlFree(ctxt->filename);
                   1218:        ctxt->doc = doc;
                   1219:        ctxt->node = (xmlNodePtr) doc;   
1.23      daniel   1220: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1221:        ctxt->pctxt = xmlXPathNewContext(doc);
1.23      daniel   1222: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1223:        ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
                   1224:     } else
                   1225:         return(-1);
                   1226:     return(0);
                   1227: }
                   1228: 
                   1229: /**
                   1230:  * xmlShellWrite:
                   1231:  * @ctxt:  the shell context
                   1232:  * @filename:  the file name
                   1233:  * @node:  a node in the tree
                   1234:  * @node2:  unused
                   1235:  *
                   1236:  * Implements the XML shell function "write"
                   1237:  * Write the current node to the filename, it saves the serailization
                   1238:  * of the subtree under the @node specified
                   1239:  *
                   1240:  * Returns 0 or -1 in case of error
                   1241:  */
                   1242: int
                   1243: xmlShellWrite(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
                   1244:                   xmlNodePtr node2) {
                   1245:     if (node == NULL)
                   1246:         return(-1);
                   1247:     if ((filename == NULL) || (filename[0] == 0)) {
                   1248:         fprintf(stderr, "Write command requires a filename argument\n");
                   1249:        return(-1);
                   1250:     }
                   1251: #ifdef W_OK
                   1252:     if (access((char *) filename, W_OK)) {
                   1253:         fprintf(stderr, "Cannot write to %s\n", filename);
                   1254:        return(-1);
                   1255:     }
                   1256: #endif    
                   1257:     switch(node->type) {
                   1258:         case XML_DOCUMENT_NODE:
                   1259:            if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
                   1260:                fprintf(stderr, "Failed to write to %s\n", filename);
                   1261:                return(-1);
                   1262:            }
                   1263:            break;
                   1264:         case XML_HTML_DOCUMENT_NODE:
1.23      daniel   1265: #ifdef LIBXML_HTML_ENABLED
1.12      daniel   1266:            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   1267:                fprintf(stderr, "Failed to write to %s\n", filename);
                   1268:                return(-1);
                   1269:            }
1.23      daniel   1270: #else
                   1271:            if (xmlSaveFile((char *) filename, ctxt->doc) < -1) {
                   1272:                fprintf(stderr, "Failed to write to %s\n", filename);
                   1273:                return(-1);
                   1274:            }
                   1275: #endif /* LIBXML_HTML_ENABLED */
1.12      daniel   1276:            break;
                   1277:        default: {
                   1278:            FILE *f;
                   1279: 
                   1280:            f = fopen((char *) filename, "w");
                   1281:            if (f == NULL) {
                   1282:                fprintf(stderr, "Failed to write to %s\n", filename);
                   1283:                return(-1);
                   1284:            }
                   1285:            xmlElemDump(f, ctxt->doc, node);
                   1286:            fclose(f);
                   1287:        }
                   1288:     }
                   1289:     return(0);
                   1290: }
                   1291: 
                   1292: /**
                   1293:  * xmlShellSave:
                   1294:  * @ctxt:  the shell context
                   1295:  * @filename:  the file name (optionnal)
                   1296:  * @node:  unused
                   1297:  * @node2:  unused
                   1298:  *
                   1299:  * Implements the XML shell function "save"
                   1300:  * Write the current document to the filename, or it's original name
                   1301:  *
                   1302:  * Returns 0 or -1 in case of error
                   1303:  */
                   1304: int 
                   1305: xmlShellSave(xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node,
                   1306:              xmlNodePtr node2) {
                   1307:     if (ctxt->doc == NULL)
                   1308:        return(-1);
                   1309:     if ((filename == NULL) || (filename[0] == 0))
                   1310:         filename = ctxt->filename;
                   1311: #ifdef W_OK
                   1312:     if (access((char *) filename, W_OK)) {
                   1313:         fprintf(stderr, "Cannot save to %s\n", filename);
                   1314:        return(-1);
                   1315:     }
                   1316: #endif
                   1317:     switch(ctxt->doc->type) {
                   1318:         case XML_DOCUMENT_NODE:
                   1319:            if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   1320:                fprintf(stderr, "Failed to save to %s\n", filename);
                   1321:            }
                   1322:            break;
                   1323:         case XML_HTML_DOCUMENT_NODE:
1.23      daniel   1324: #ifdef LIBXML_HTML_ENABLED
1.12      daniel   1325:            if (htmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   1326:                fprintf(stderr, "Failed to save to %s\n", filename);
                   1327:            }
1.23      daniel   1328: #else
                   1329:            if (xmlSaveFile((char *) filename, ctxt->doc) < 0) {
                   1330:                fprintf(stderr, "Failed to save to %s\n", filename);
                   1331:            }
                   1332: #endif /* LIBXML_HTML_ENABLED */
1.12      daniel   1333:            break;
                   1334:        default:
                   1335:            fprintf(stderr, 
                   1336:              "To save to subparts of a document use the 'write' command\n");
                   1337:            return(-1);
                   1338:            
                   1339:     }
                   1340:     return(0);
                   1341: }
                   1342: 
                   1343: /**
                   1344:  * xmlShellValidate:
                   1345:  * @ctxt:  the shell context
                   1346:  * @dtd:  the DTD URI (optionnal)
                   1347:  * @node:  unused
                   1348:  * @node2:  unused
                   1349:  *
                   1350:  * Implements the XML shell function "validate"
                   1351:  * Validate the document, if a DTD path is provided, then the validation
                   1352:  * is done against the given DTD.
                   1353:  *
                   1354:  * Returns 0 or -1 in case of error
                   1355:  */
                   1356: int 
                   1357: xmlShellValidate(xmlShellCtxtPtr ctxt, char *dtd, xmlNodePtr node,
                   1358:                  xmlNodePtr node2) {
                   1359:     xmlValidCtxt vctxt;
                   1360:     int res = -1;
                   1361: 
                   1362:     vctxt.userData = stderr;
                   1363:     vctxt.error = (xmlValidityErrorFunc) fprintf;
                   1364:     vctxt.warning = (xmlValidityWarningFunc) fprintf;
                   1365: 
                   1366:     if ((dtd == NULL) || (dtd[0] == 0)) {
                   1367:         res = xmlValidateDocument(&vctxt, ctxt->doc);
                   1368:     } else {
                   1369:         xmlDtdPtr subset;
                   1370: 
                   1371:        subset = xmlParseDTD(NULL, (xmlChar *) dtd);
                   1372:        if (subset != NULL) {
                   1373:             res = xmlValidateDtd(&vctxt, ctxt->doc, subset);
                   1374: 
                   1375:            xmlFreeDtd(subset);
                   1376:        }
                   1377:     }
                   1378:     return(res);
                   1379: }
                   1380: 
                   1381: /**
                   1382:  * xmlShellDu:
                   1383:  * @ctxt:  the shell context
                   1384:  * @arg:  unused
                   1385:  * @tree:  a node defining a subtree
                   1386:  * @node2:  unused
                   1387:  *
                   1388:  * Implements the XML shell function "du"
                   1389:  * show the structure of the subtree under node @tree
                   1390:  * If @tree is null, the command works on the current node.
                   1391:  *
                   1392:  * Returns 0 or -1 in case of error
                   1393:  */
                   1394: int 
                   1395: xmlShellDu(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr tree,
                   1396:                   xmlNodePtr node2) {
                   1397:     xmlNodePtr node;
                   1398:     int indent = 0,i;
                   1399: 
                   1400:     if (tree == NULL) return(-1);
                   1401:     node = tree;
                   1402:     while (node != NULL) {
                   1403:         if ((node->type == XML_DOCUMENT_NODE) ||
                   1404:             (node->type == XML_HTML_DOCUMENT_NODE)) {
                   1405:            printf("/\n");
                   1406:        } else if (node->type == XML_ELEMENT_NODE) {
                   1407:            for (i = 0;i < indent;i++)
                   1408:                printf("  ");
                   1409:            printf("%s\n", node->name);
                   1410:        } else {
                   1411:        }
                   1412: 
                   1413:        /*
                   1414:         * Browse the full subtree, deep first
                   1415:         */
                   1416: 
                   1417:         if ((node->type == XML_DOCUMENT_NODE) ||
                   1418:             (node->type == XML_HTML_DOCUMENT_NODE)) {
1.16      daniel   1419:            node = ((xmlDocPtr) node)->children;
1.25      daniel   1420:         } else if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
1.12      daniel   1421:            /* deep first */
1.16      daniel   1422:            node = node->children;
1.12      daniel   1423:            indent++;
                   1424:        } else if ((node != tree) && (node->next != NULL)) {
                   1425:            /* then siblings */
                   1426:            node = node->next;
                   1427:        } else if (node != tree) {
                   1428:            /* go up to parents->next if needed */
                   1429:            while (node != tree) {
                   1430:                if (node->parent != NULL) {
                   1431:                    node = node->parent;
                   1432:                    indent--;
                   1433:                }
                   1434:                if ((node != tree) && (node->next != NULL)) {
                   1435:                    node = node->next;
                   1436:                    break;
                   1437:                }
                   1438:                if (node->parent == NULL) {
                   1439:                    node = NULL;
                   1440:                    break;
                   1441:                }
                   1442:                if (node == tree) {
                   1443:                    node = NULL;
                   1444:                    break;
                   1445:                }
                   1446:            }
                   1447:            /* exit condition */
                   1448:            if (node == tree) 
                   1449:                node = NULL;
                   1450:        } else
                   1451:            node = NULL;
                   1452:     }
                   1453:     return(0);
                   1454: }
                   1455: 
                   1456: /**
                   1457:  * xmlShellPwd:
                   1458:  * @ctxt:  the shell context
                   1459:  * @buffer:  the output buffer
                   1460:  * @tree:  a node 
                   1461:  * @node2:  unused
                   1462:  *
                   1463:  * Implements the XML shell function "pwd"
                   1464:  * Show the full path from the root to the node, if needed building
                   1465:  * thumblers when similar elements exists at a given ancestor level.
                   1466:  * The output is compatible with XPath commands.
                   1467:  *
                   1468:  * Returns 0 or -1 in case of error
                   1469:  */
                   1470: int 
                   1471: xmlShellPwd(xmlShellCtxtPtr ctxt, char *buffer, xmlNodePtr node,
                   1472:                   xmlNodePtr node2) {
                   1473:     xmlNodePtr cur, tmp, next;
                   1474:     char buf[500];
                   1475:     char sep;
                   1476:     const char *name;
                   1477:     int occur = 0;
                   1478: 
                   1479:     buffer[0] = 0;
                   1480:     if (node == NULL) return(-1);
                   1481:     cur = node;
                   1482:     do {
                   1483:        name = "";
                   1484:        sep= '?';
                   1485:        occur = 0;
                   1486:        if ((cur->type == XML_DOCUMENT_NODE) ||
                   1487:            (cur->type == XML_HTML_DOCUMENT_NODE)) {
                   1488:            sep = '/';
                   1489:            next = NULL;
                   1490:        } else if (cur->type == XML_ELEMENT_NODE) {
                   1491:            sep = '/';
                   1492:            name = (const char *)cur->name;
                   1493:            next = cur->parent;
                   1494: 
                   1495:            /*
                   1496:             * Thumbler index computation
                   1497:             */
                   1498:            tmp = cur->prev;
                   1499:             while (tmp != NULL) {
1.35      veillard 1500:                if (xmlStrEqual(cur->name, tmp->name))
1.12      daniel   1501:                    occur++;
                   1502:                tmp = tmp->prev;
                   1503:            }
                   1504:            if (occur == 0) {
                   1505:                tmp = cur->next;
                   1506:                while (tmp != NULL) {
1.35      veillard 1507:                    if (xmlStrEqual(cur->name, tmp->name))
1.12      daniel   1508:                        occur++;
                   1509:                    tmp = tmp->next;
                   1510:                }
                   1511:                if (occur != 0) occur = 1;
                   1512:            } else
                   1513:                occur++;
                   1514:        } else if (cur->type == XML_ATTRIBUTE_NODE) {
                   1515:            sep = '@';
                   1516:            name = (const char *) (((xmlAttrPtr) cur)->name);
1.16      daniel   1517:            next = ((xmlAttrPtr) cur)->parent;
1.12      daniel   1518:        } else {
                   1519:            next = cur->parent;
                   1520:        }
                   1521:        if (occur == 0)
1.31      veillard 1522: #ifdef HAVE_SNPRINTF
                   1523:            snprintf(buf, sizeof(buf), "%c%s%s", sep, name, buffer);
                   1524: #else
1.12      daniel   1525:            sprintf(buf, "%c%s%s", sep, name, buffer);
1.31      veillard 1526: #endif
                   1527:         else
                   1528: #ifdef HAVE_SNPRINTF
                   1529:            snprintf(buf, sizeof(buf), "%c%s[%d]%s",
                   1530:                     sep, name, occur, buffer);
                   1531: #else
1.12      daniel   1532:            sprintf(buf, "%c%s[%d]%s", sep, name, occur, buffer);
1.31      veillard 1533: #endif
                   1534:         buf[sizeof(buf) - 1] = 0;
                   1535:         /*
                   1536:          * This test prevents buffer overflow, because this routine
                   1537:          * is only called by xmlShell, in which the second argument is
                   1538:          * 500 chars long.
                   1539:          * It is a dirty hack before a cleaner solution is found.
                   1540:          * Documentation should mention that the second argument must
                   1541:          * be at least 500 chars long, and could be stripped if too long.
                   1542:          */
                   1543:         if (strlen(buffer) + strlen(buf) > 499)
                   1544:            break;
1.12      daniel   1545:        strcpy(buffer, buf);
                   1546:         cur = next;
                   1547:     } while (cur != NULL);
                   1548:     return(0);
                   1549: }
                   1550: 
                   1551: /**
                   1552:  * xmlShell
                   1553:  * @doc:  the initial document
                   1554:  * @filename:  the output buffer
                   1555:  * @input:  the line reading function
                   1556:  * @output:  the output FILE*
                   1557:  *
                   1558:  * Implements the XML shell 
                   1559:  * This allow to load, validate, view, modify and save a document
                   1560:  * using a environment similar to a UNIX commandline.
                   1561:  */
                   1562: void
                   1563: xmlShell(xmlDocPtr doc, char *filename, xmlShellReadlineFunc input,
                   1564:          FILE *output) {
                   1565:     char prompt[500] = "/ > ";
1.39      veillard 1566:     char *cmdline = NULL, *cur;
1.12      daniel   1567:     int nbargs;
                   1568:     char command[100];
                   1569:     char arg[400];
1.39      veillard 1570:     int i;
1.12      daniel   1571:     xmlShellCtxtPtr ctxt;
                   1572:     xmlXPathObjectPtr list;
                   1573: 
                   1574:     if (doc == NULL)
                   1575:         return;
                   1576:     if (filename == NULL)
                   1577:         return;
                   1578:     if (input == NULL)
                   1579:         return;
                   1580:     if (output == NULL)
                   1581:         return;
                   1582:     ctxt = (xmlShellCtxtPtr) xmlMalloc(sizeof(xmlShellCtxt));
                   1583:     if (ctxt == NULL) 
                   1584:         return;
                   1585:     ctxt->loaded = 0;
                   1586:     ctxt->doc = doc;
                   1587:     ctxt->input = input;
                   1588:     ctxt->output = output;
                   1589:     ctxt->filename = (char *) xmlStrdup((xmlChar *) filename);
                   1590:     ctxt->node = (xmlNodePtr) ctxt->doc;        
                   1591: 
1.23      daniel   1592: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1593:     ctxt->pctxt = xmlXPathNewContext(ctxt->doc);
                   1594:     if (ctxt->pctxt == NULL) {
                   1595:        xmlFree(ctxt);
                   1596:        return;
                   1597:     }
1.23      daniel   1598: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1599:     while (1) {
                   1600:         if (ctxt->node == (xmlNodePtr) ctxt->doc)
                   1601:            sprintf(prompt, "%s > ", "/");
                   1602:        else if (ctxt->node->name)
1.31      veillard 1603: #ifdef HAVE_SNPRINTF
                   1604:            snprintf(prompt, sizeof(prompt), "%s > ", ctxt->node->name);
                   1605: #else
1.34      veillard 1606:            sprintf(prompt, "%s > ", ctxt->node->name);
1.31      veillard 1607: #endif
                   1608:         else
1.12      daniel   1609:            sprintf(prompt, "? > ");
1.31      veillard 1610:         prompt[sizeof(prompt) - 1] = 0;
1.12      daniel   1611: 
1.39      veillard 1612:        /*
                   1613:         * Get a new command line
                   1614:         */
1.12      daniel   1615:         cmdline = ctxt->input(prompt);
                   1616:         if (cmdline == NULL) break;
                   1617: 
1.39      veillard 1618:        /*
                   1619:         * Parse the command itself
                   1620:         */
                   1621:        cur = cmdline;
                   1622:        while ((*cur == ' ') || (*cur == '\t')) cur++;
                   1623:        i = 0;
                   1624:        while ((*cur != ' ') && (*cur != '\t') &&
                   1625:               (*cur != '\n') && (*cur != '\r')) {
                   1626:            if (*cur == 0)
                   1627:                break;
                   1628:            command[i++] = *cur++;
                   1629:        }
                   1630:        command[i] = 0;
                   1631:        if (i == 0) continue;
                   1632:        nbargs++;
1.12      daniel   1633: 
1.39      veillard 1634:        /*
                   1635:         * Parse the argument
                   1636:         */
                   1637:        while ((*cur == ' ') || (*cur == '\t')) cur++;
                   1638:        i = 0;
                   1639:        while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) {
                   1640:            if (*cur == 0)
                   1641:                break;
                   1642:            arg[i++] = *cur++;
                   1643:        }
                   1644:        arg[i] = 0;
                   1645:        if (i != 0) 
                   1646:            nbargs++;
                   1647: 
                   1648:        /*
                   1649:         * start interpreting the command
                   1650:         */
1.12      daniel   1651:         if (!strcmp(command, "exit"))
                   1652:            break;
                   1653:         if (!strcmp(command, "quit"))
                   1654:            break;
                   1655:         if (!strcmp(command, "bye"))
                   1656:            break;
                   1657:        if (!strcmp(command, "validate")) {
                   1658:            xmlShellValidate(ctxt, arg, NULL, NULL);
                   1659:        } else if (!strcmp(command, "load")) {
                   1660:            xmlShellLoad(ctxt, arg, NULL, NULL);
                   1661:        } else if (!strcmp(command, "save")) {
                   1662:            xmlShellSave(ctxt, arg, NULL, NULL);
                   1663:        } else if (!strcmp(command, "write")) {
                   1664:            xmlShellWrite(ctxt, arg, NULL, NULL);
                   1665:        } else if (!strcmp(command, "free")) {
                   1666:            if (arg[0] == 0) {
                   1667:                xmlMemShow(stdout, 0);
                   1668:            } else {
                   1669:                int len = 0;
                   1670:                sscanf(arg, "%d", &len);
                   1671:                xmlMemShow(stdout, len);
                   1672:            }
                   1673:        } else if (!strcmp(command, "pwd")) {
                   1674:            char dir[500];
                   1675:            if (!xmlShellPwd(ctxt, dir, ctxt->node, NULL))
                   1676:                printf("%s\n", dir);
                   1677:        } else  if (!strcmp(command, "du")) {
                   1678:            xmlShellDu(ctxt, NULL, ctxt->node, NULL);
                   1679:        } else  if ((!strcmp(command, "ls")) ||
                   1680:              (!strcmp(command, "dir"))) {
                   1681:            int dir = (!strcmp(command, "dir"));
                   1682:            if (arg[0] == 0) {
                   1683:                if (dir)
                   1684:                    xmlShellDir(ctxt, NULL, ctxt->node, NULL);
                   1685:                else
                   1686:                    xmlShellList(ctxt, NULL, ctxt->node, NULL);
                   1687:            } else {
                   1688:                ctxt->pctxt->node = ctxt->node;
1.23      daniel   1689: #ifdef LIBXML_XPATH_ENABLED
1.36      veillard 1690:                ctxt->pctxt->node = ctxt->node;
1.12      daniel   1691:                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1.23      daniel   1692: #else
                   1693:                list = NULL;
                   1694: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1695:                if (list != NULL) {
                   1696:                    switch (list->type) {
                   1697:                        case XPATH_UNDEFINED:
                   1698:                            fprintf(stderr, "%s: no such node\n", arg);
                   1699:                            break;
                   1700:                        case XPATH_NODESET: {
                   1701:                            int i;
                   1702: 
                   1703:                            for (i = 0;i < list->nodesetval->nodeNr;i++) {
                   1704:                                if (dir)
                   1705:                                    xmlShellDir(ctxt, NULL,
                   1706:                                       list->nodesetval->nodeTab[i], NULL);
                   1707:                                else
                   1708:                                    xmlShellList(ctxt, NULL,
                   1709:                                       list->nodesetval->nodeTab[i], NULL);
                   1710:                            }
                   1711:                            break;
                   1712:                        }
                   1713:                        case XPATH_BOOLEAN:
                   1714:                            fprintf(stderr, "%s is a Boolean\n", arg);
                   1715:                            break;
                   1716:                        case XPATH_NUMBER:
                   1717:                            fprintf(stderr, "%s is a number\n", arg);
                   1718:                            break;
                   1719:                        case XPATH_STRING:
                   1720:                            fprintf(stderr, "%s is a string\n", arg);
                   1721:                            break;
1.37      veillard 1722:                        case XPATH_POINT:
                   1723:                            fprintf(stderr, "%s is a point\n", arg);
                   1724:                            break;
                   1725:                        case XPATH_RANGE:
                   1726:                            fprintf(stderr, "%s is a range\n", arg);
                   1727:                            break;
1.38      veillard 1728:                        case XPATH_LOCATIONSET:
1.37      veillard 1729:                            fprintf(stderr, "%s is a range\n", arg);
                   1730:                            break;
                   1731:                        case XPATH_USERS:
                   1732:                            fprintf(stderr, "%s is user-defined\n", arg);
                   1733:                            break;
1.12      daniel   1734:                    }
                   1735:                    xmlXPathFreeNodeSetList(list);
                   1736:                } else {
                   1737:                    fprintf(stderr, "%s: no such node\n", arg);
                   1738:                }
1.36      veillard 1739:                ctxt->pctxt->node = NULL;
1.12      daniel   1740:            }
                   1741:        } else if (!strcmp(command, "cd")) {
                   1742:            if (arg[0] == 0) {
                   1743:                ctxt->node = (xmlNodePtr) ctxt->doc;
                   1744:            } else {
1.36      veillard 1745: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1746:                ctxt->pctxt->node = ctxt->node;
                   1747:                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1.23      daniel   1748: #else
                   1749:                list = NULL;
                   1750: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1751:                if (list != NULL) {
                   1752:                    switch (list->type) {
                   1753:                        case XPATH_UNDEFINED:
                   1754:                            fprintf(stderr, "%s: no such node\n", arg);
                   1755:                            break;
                   1756:                        case XPATH_NODESET:
                   1757:                            if (list->nodesetval->nodeNr == 1) {
                   1758:                                ctxt->node = list->nodesetval->nodeTab[0];
                   1759:                            } else 
                   1760:                                fprintf(stderr, "%s is a %d Node Set\n",
                   1761:                                        arg, list->nodesetval->nodeNr);
                   1762:                            break;
                   1763:                        case XPATH_BOOLEAN:
                   1764:                            fprintf(stderr, "%s is a Boolean\n", arg);
                   1765:                            break;
                   1766:                        case XPATH_NUMBER:
                   1767:                            fprintf(stderr, "%s is a number\n", arg);
                   1768:                            break;
                   1769:                        case XPATH_STRING:
                   1770:                            fprintf(stderr, "%s is a string\n", arg);
                   1771:                            break;
1.37      veillard 1772:                        case XPATH_POINT:
                   1773:                            fprintf(stderr, "%s is a point\n", arg);
                   1774:                            break;
                   1775:                        case XPATH_RANGE:
                   1776:                            fprintf(stderr, "%s is a range\n", arg);
                   1777:                            break;
1.38      veillard 1778:                        case XPATH_LOCATIONSET:
1.37      veillard 1779:                            fprintf(stderr, "%s is a range\n", arg);
                   1780:                            break;
                   1781:                        case XPATH_USERS:
                   1782:                            fprintf(stderr, "%s is user-defined\n", arg);
                   1783:                            break;
1.12      daniel   1784:                    }
                   1785:                    xmlXPathFreeNodeSetList(list);
                   1786:                } else {
                   1787:                    fprintf(stderr, "%s: no such node\n", arg);
                   1788:                }
1.36      veillard 1789:                ctxt->pctxt->node = NULL;
1.12      daniel   1790:            }
                   1791:        } else if (!strcmp(command, "cat")) {
                   1792:            if (arg[0] == 0) {
                   1793:                xmlShellCat(ctxt, NULL, ctxt->node, NULL);
                   1794:            } else {
                   1795:                ctxt->pctxt->node = ctxt->node;
1.23      daniel   1796: #ifdef LIBXML_XPATH_ENABLED
1.36      veillard 1797:                ctxt->pctxt->node = ctxt->node;
1.12      daniel   1798:                list = xmlXPathEval((xmlChar *) arg, ctxt->pctxt);
1.23      daniel   1799: #else
                   1800:                list = NULL;
                   1801: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1802:                if (list != NULL) {
                   1803:                    switch (list->type) {
                   1804:                        case XPATH_UNDEFINED:
                   1805:                            fprintf(stderr, "%s: no such node\n", arg);
                   1806:                            break;
                   1807:                        case XPATH_NODESET: {
                   1808:                            int i;
                   1809: 
                   1810:                            for (i = 0;i < list->nodesetval->nodeNr;i++) {
                   1811:                                if (i > 0) printf(" -------\n");
                   1812:                                xmlShellCat(ctxt, NULL,
                   1813:                                    list->nodesetval->nodeTab[i], NULL);
                   1814:                            }
                   1815:                            break;
                   1816:                        }
                   1817:                        case XPATH_BOOLEAN:
                   1818:                            fprintf(stderr, "%s is a Boolean\n", arg);
                   1819:                            break;
                   1820:                        case XPATH_NUMBER:
                   1821:                            fprintf(stderr, "%s is a number\n", arg);
                   1822:                            break;
                   1823:                        case XPATH_STRING:
                   1824:                            fprintf(stderr, "%s is a string\n", arg);
1.37      veillard 1825:                            break;
                   1826:                        case XPATH_POINT:
                   1827:                            fprintf(stderr, "%s is a point\n", arg);
                   1828:                            break;
                   1829:                        case XPATH_RANGE:
                   1830:                            fprintf(stderr, "%s is a range\n", arg);
                   1831:                            break;
1.38      veillard 1832:                        case XPATH_LOCATIONSET:
1.37      veillard 1833:                            fprintf(stderr, "%s is a range\n", arg);
                   1834:                            break;
                   1835:                        case XPATH_USERS:
                   1836:                            fprintf(stderr, "%s is user-defined\n", arg);
1.12      daniel   1837:                            break;
                   1838:                    }
                   1839:                    xmlXPathFreeNodeSetList(list);
                   1840:                } else {
                   1841:                    fprintf(stderr, "%s: no such node\n", arg);
                   1842:                }
1.36      veillard 1843:                ctxt->pctxt->node = NULL;
1.12      daniel   1844:            }
                   1845:        } else {
                   1846:            fprintf(stderr, "Unknown command %s\n", command);
                   1847:        }
                   1848:        free(cmdline); /* not xmlFree here ! */
                   1849:     }
1.23      daniel   1850: #ifdef LIBXML_XPATH_ENABLED
1.12      daniel   1851:     xmlXPathFreeContext(ctxt->pctxt);
1.23      daniel   1852: #endif /* LIBXML_XPATH_ENABLED */
1.12      daniel   1853:     if (ctxt->loaded) {
                   1854:         xmlFreeDoc(ctxt->doc);
                   1855:     }
                   1856:     xmlFree(ctxt);
                   1857:     if (cmdline != NULL)
                   1858:         free(cmdline); /* not xmlFree here ! */
                   1859: }
                   1860: 
1.23      daniel   1861: #endif /* LIBXML_DEBUG_ENABLED */

Webmaster