⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 debugxml.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * debugXML.c : This is a set of routines used for debugging the tree
 *              produced by the XML parser.
 *
 * See Copyright for the status of this software.
 *
 * Daniel Veillard <daniel@veillard.com>
 */

#define IN_LIBXML
#include "libxml.h"
#ifdef LIBXML_DEBUG_ENABLED

#include <string.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <libxml/xmlmemory.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/parserInternals.h>
#include <libxml/valid.h>
#include <libxml/debugXML.h>
#include <libxml/HTMLtree.h>
#include <libxml/HTMLparser.h>
#include <libxml/xmlerror.h>
#include <libxml/globals.h>
#include <libxml/xpathInternals.h>
#include <libxml/uri.h>
#ifdef LIBXML_SCHEMAS_ENABLED
#include <libxml/relaxng.h>
#endif

typedef struct _xmlDebugCtxt xmlDebugCtxt;
typedef xmlDebugCtxt *xmlDebugCtxtPtr;
struct _xmlDebugCtxt {
    FILE *output;               /* the output file */
    char shift[101];            /* used for indenting */
    int depth;                  /* current depth */
    xmlDocPtr doc;              /* current document */
    xmlNodePtr node;		/* current node */
    xmlDictPtr dict;		/* the doc dictionnary */
    int check;                  /* do just checkings */
    int errors;                 /* number of errors found */
    int nodict;			/* if the document has no dictionnary */
};

static void xmlCtxtDumpNodeList(xmlDebugCtxtPtr ctxt, xmlNodePtr node);

static void
xmlCtxtDumpInitCtxt(xmlDebugCtxtPtr ctxt)
{
    int i;

    ctxt->depth = 0;
    ctxt->check = 0;
    ctxt->errors = 0;
    ctxt->output = stdout;
    ctxt->doc = NULL;
    ctxt->node = NULL;
    ctxt->dict = NULL;
    ctxt->nodict = 0;
    for (i = 0; i < 100; i++)
        ctxt->shift[i] = ' ';
    ctxt->shift[100] = 0;
}

static void
xmlCtxtDumpCleanCtxt(xmlDebugCtxtPtr ctxt ATTRIBUTE_UNUSED)
{
 /* remove the ATTRIBUTE_UNUSED when this is added */
}

/**
 * xmlNsCheckScope:
 * @node: the node
 * @ns: the namespace node
 *
 * Check that a given namespace is in scope on a node.
 *
 * Returns 1 if in scope, -1 in case of argument error, 
 *         -2 if the namespace is not in scope, and -3 if not on
 *         an ancestor node.
 */
static int
xmlNsCheckScope(xmlNodePtr node, xmlNsPtr ns)
{
    xmlNsPtr cur;

    if ((node == NULL) || (ns == NULL))
        return(-1);

    if ((node->type != XML_ELEMENT_NODE) &&
	(node->type != XML_ATTRIBUTE_NODE) &&
	(node->type != XML_DOCUMENT_NODE) &&
	(node->type != XML_TEXT_NODE) &&
	(node->type != XML_HTML_DOCUMENT_NODE) &&
	(node->type != XML_XINCLUDE_START))
	return(-2);

    while ((node != NULL) &&
           ((node->type == XML_ELEMENT_NODE) ||
            (node->type == XML_ATTRIBUTE_NODE) ||
            (node->type == XML_TEXT_NODE) ||
	    (node->type == XML_XINCLUDE_START))) {
	if ((node->type == XML_ELEMENT_NODE) ||
	    (node->type == XML_XINCLUDE_START)) {
	    cur = node->nsDef;
	    while (cur != NULL) {
	        if (cur == ns)
		    return(1);
		if (xmlStrEqual(cur->prefix, ns->prefix))
		    return(-2);
		cur = cur->next;
	    }
	}
	node = node->parent;
    }
    /* the xml namespace may be declared on the document node */
    if ((node != NULL) &&
        ((node->type == XML_DOCUMENT_NODE) ||
	 (node->type == XML_HTML_DOCUMENT_NODE))) {
	 xmlNsPtr oldNs = ((xmlDocPtr) node)->oldNs;
	 if (oldNs == ns)
	     return(1);
    }
    return(-3);
}

static void
xmlCtxtDumpSpaces(xmlDebugCtxtPtr ctxt)
{
    if (ctxt->check)
        return;
    if ((ctxt->output != NULL) && (ctxt->depth > 0)) {
        if (ctxt->depth < 50)
            fprintf(ctxt->output, &ctxt->shift[100 - 2 * ctxt->depth]);
        else
            fprintf(ctxt->output, ctxt->shift);
    }
}

/**
 * xmlDebugErr:
 * @ctxt:  a debug context
 * @error:  the error code
 *
 * Handle a debug error.
 */
static void
xmlDebugErr(xmlDebugCtxtPtr ctxt, int error, const char *msg)
{
    ctxt->errors++;
    __xmlRaiseError(NULL, NULL, NULL,
		    NULL, ctxt->node, XML_FROM_CHECK,
		    error, XML_ERR_ERROR, NULL, 0,
		    NULL, NULL, NULL, 0, 0,
		    msg);
}
static void
xmlDebugErr2(xmlDebugCtxtPtr ctxt, int error, const char *msg, int extra)
{
    ctxt->errors++;
    __xmlRaiseError(NULL, NULL, NULL,
		    NULL, ctxt->node, XML_FROM_CHECK,
		    error, XML_ERR_ERROR, NULL, 0,
		    NULL, NULL, NULL, 0, 0,
		    msg, extra);
}
static void
xmlDebugErr3(xmlDebugCtxtPtr ctxt, int error, const char *msg, const char *extra)
{
    ctxt->errors++;
    __xmlRaiseError(NULL, NULL, NULL,
		    NULL, ctxt->node, XML_FROM_CHECK,
		    error, XML_ERR_ERROR, NULL, 0,
		    NULL, NULL, NULL, 0, 0,
		    msg, extra);
}

/**
 * xmlCtxtNsCheckScope:
 * @ctxt: the debugging context
 * @node: the node
 * @ns: the namespace node
 *
 * Report if a given namespace is is not in scope.
 */
static void
xmlCtxtNsCheckScope(xmlDebugCtxtPtr ctxt, xmlNodePtr node, xmlNsPtr ns)
{
    int ret;

    ret = xmlNsCheckScope(node, ns);
    if (ret == -2) {
        if (ns->prefix == NULL)
	    xmlDebugErr(ctxt, XML_CHECK_NS_SCOPE,
			"Reference to default namespace not in scope\n");
	else
	    xmlDebugErr3(ctxt, XML_CHECK_NS_SCOPE,
			 "Reference to namespace '%s' not in scope\n",
			 (char *) ns->prefix);
    }
    if (ret == -3) {
        if (ns->prefix == NULL)
	    xmlDebugErr(ctxt, XML_CHECK_NS_ANCESTOR,
			"Reference to default namespace not on ancestor\n");
	else
	    xmlDebugErr3(ctxt, XML_CHECK_NS_ANCESTOR,
			 "Reference to namespace '%s' not on ancestor\n",
			 (char *) ns->prefix);
    }
}

/**
 * xmlCtxtCheckString:
 * @ctxt: the debug context
 * @str: the string
 *
 * Do debugging on the string, currently it just checks the UTF-8 content
 */
static void
xmlCtxtCheckString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
{
    if (str == NULL) return;
    if (ctxt->check) {
        if (!xmlCheckUTF8(str)) {
	    xmlDebugErr3(ctxt, XML_CHECK_NOT_UTF8,
			 "String is not UTF-8 %s", (const char *) str);
	}
    }
}

/**
 * xmlCtxtCheckName:
 * @ctxt: the debug context
 * @name: the name
 *
 * Do debugging on the name, for example the dictionnary status and
 * conformance to the Name production.
 */
static void
xmlCtxtCheckName(xmlDebugCtxtPtr ctxt, const xmlChar * name)
{
    if (ctxt->check) {
	if (name == NULL) {
	    xmlDebugErr(ctxt, XML_CHECK_NO_NAME, "Name is NULL");
	    return;
	}
        if (xmlValidateName(name, 0)) {
	    xmlDebugErr3(ctxt, XML_CHECK_NOT_NCNAME,
			 "Name is not an NCName '%s'", (const char *) name);
	}
	if ((ctxt->dict != NULL) &&
	    (!xmlDictOwns(ctxt->dict, name))) {
	    xmlDebugErr3(ctxt, XML_CHECK_OUTSIDE_DICT,
			 "Name is not from the document dictionnary '%s'",
			 (const char *) name);
	}
    }
}

static void
xmlCtxtGenericNodeCheck(xmlDebugCtxtPtr ctxt, xmlNodePtr node) {
    xmlDocPtr doc;
    xmlDictPtr dict;

    doc = node->doc;

    if (node->parent == NULL)
        xmlDebugErr(ctxt, XML_CHECK_NO_PARENT,
	            "Node has no parent\n");
    if (node->doc == NULL) {
        xmlDebugErr(ctxt, XML_CHECK_NO_DOC,
	            "Node has no doc\n");
        dict = NULL;
    } else {
	dict = doc->dict;
	if ((dict == NULL) && (ctxt->nodict == 0)) {
#if 0
            /* desactivated right now as it raises too many errors */
	    if (doc->type == XML_DOCUMENT_NODE)
		xmlDebugErr(ctxt, XML_CHECK_NO_DICT,
			    "Document has no dictionnary\n");
#endif
	    ctxt->nodict = 1;
	}
	if (ctxt->doc == NULL)
	    ctxt->doc = doc;

	if (ctxt->dict == NULL) {
	    ctxt->dict = dict;
	}
    }
    if ((node->parent != NULL) && (node->doc != node->parent->doc) &&
        (!xmlStrEqual(node->name, BAD_CAST "pseudoroot")))
        xmlDebugErr(ctxt, XML_CHECK_WRONG_DOC,
	            "Node doc differs from parent's one\n");
    if (node->prev == NULL) {
        if (node->type == XML_ATTRIBUTE_NODE) {
	    if ((node->parent != NULL) &&
	        (node != (xmlNodePtr) node->parent->properties))
		xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
                    "Attr has no prev and not first of attr list\n");
	        
        } else if ((node->parent != NULL) && (node->parent->children != node))
	    xmlDebugErr(ctxt, XML_CHECK_NO_PREV,
                    "Node has no prev and not first of parent list\n");
    } else {
        if (node->prev->next != node)
	    xmlDebugErr(ctxt, XML_CHECK_WRONG_PREV,
                        "Node prev->next : back link wrong\n");
    }
    if (node->next == NULL) {
	if ((node->parent != NULL) && (node->type != XML_ATTRIBUTE_NODE) &&
	    (node->parent->last != node))
	    xmlDebugErr(ctxt, XML_CHECK_NO_NEXT,
                    "Node has no next and not last of parent list\n");
    } else {
        if (node->next->prev != node)
	    xmlDebugErr(ctxt, XML_CHECK_WRONG_NEXT,
                    "Node next->prev : forward link wrong\n");
        if (node->next->parent != node->parent)
	    xmlDebugErr(ctxt, XML_CHECK_WRONG_PARENT,
                    "Node next->prev : forward link wrong\n");
    }
    if (node->type == XML_ELEMENT_NODE) {
        xmlNsPtr ns;

	ns = node->nsDef;
	while (ns != NULL) {
	    xmlCtxtNsCheckScope(ctxt, node, ns);
	    ns = ns->next;
	}
	if (node->ns != NULL)
	    xmlCtxtNsCheckScope(ctxt, node, node->ns);
    } else if (node->type == XML_ATTRIBUTE_NODE) {
	if (node->ns != NULL)
	    xmlCtxtNsCheckScope(ctxt, node, node->ns);
    }

    if ((node->type != XML_ELEMENT_NODE) &&
	(node->type != XML_ATTRIBUTE_NODE) &&
	(node->type != XML_ELEMENT_DECL) &&
	(node->type != XML_ATTRIBUTE_DECL) &&
	(node->type != XML_DTD_NODE) &&
	(node->type != XML_ELEMENT_DECL) &&
	(node->type != XML_HTML_DOCUMENT_NODE) &&
	(node->type != XML_DOCUMENT_NODE)) {
	if (node->content != NULL)
	    xmlCtxtCheckString(ctxt, (const xmlChar *) node->content);
    }
    switch (node->type) {
        case XML_ELEMENT_NODE:
        case XML_ATTRIBUTE_NODE:
	    xmlCtxtCheckName(ctxt, node->name);
	    break;
        case XML_TEXT_NODE:
	    if ((node->name == xmlStringText) ||
	        (node->name == xmlStringTextNoenc))
		break;
	    /* some case of entity substitution can lead to this */
	    if ((ctxt->dict != NULL) &&
	        (node->name == xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
		                             7)))
		break;

	    xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
			 "Text node has wrong name '%s'",
			 (const char *) node->name);
	    break;
        case XML_COMMENT_NODE:
	    if (node->name == xmlStringComment)
		break;
	    xmlDebugErr3(ctxt, XML_CHECK_WRONG_NAME,
			 "Comment node has wrong name '%s'",
			 (const char *) node->name);
	    break;
        case XML_PI_NODE:
	    xmlCtxtCheckName(ctxt, node->name);
	    break;
        case XML_CDATA_SECTION_NODE:
	    if (node->name == NULL)
		break;
	    xmlDebugErr3(ctxt, XML_CHECK_NAME_NOT_NULL,
			 "CData section has non NULL name '%s'",
			 (const char *) node->name);
	    break;
        case XML_ENTITY_REF_NODE:
        case XML_ENTITY_NODE:
        case XML_DOCUMENT_TYPE_NODE:
        case XML_DOCUMENT_FRAG_NODE:
        case XML_NOTATION_NODE:
        case XML_DTD_NODE:
        case XML_ELEMENT_DECL:
        case XML_ATTRIBUTE_DECL:
        case XML_ENTITY_DECL:
        case XML_NAMESPACE_DECL:
        case XML_XINCLUDE_START:
        case XML_XINCLUDE_END:
#ifdef LIBXML_DOCB_ENABLED
        case XML_DOCB_DOCUMENT_NODE:
#endif
        case XML_DOCUMENT_NODE:
        case XML_HTML_DOCUMENT_NODE:
	    break;
    }
}

static void
xmlCtxtDumpString(xmlDebugCtxtPtr ctxt, const xmlChar * str)
{
    int i;

    if (ctxt->check) {
        return;
    }
    /* TODO: check UTF8 content of the string */
    if (str == NULL) {
        fprintf(ctxt->output, "(NULL)");
        return;
    }
    for (i = 0; i < 40; i++)
        if (str[i] == 0)
            return;
        else if (IS_BLANK_CH(str[i]))
            fputc(' ', ctxt->output);
        else if (str[i] >= 0x80)
            fprintf(ctxt->output, "#%X", str[i]);
        else
            fputc(str[i], ctxt->output);
    fprintf(ctxt->output, "...");
}

static void
xmlCtxtDumpDtdNode(xmlDebugCtxtPtr ctxt, xmlDtdPtr dtd)
{
    xmlCtxtDumpSpaces(ctxt);

    if (dtd == NULL) {
        if (!ctxt->check)
            fprintf(ctxt->output, "DTD node is NULL\n");
        return;
    }

    if (dtd->type != XML_DTD_NODE) {
	xmlDebugErr(ctxt, XML_CHECK_NOT_DTD,
	            "Node is not a DTD");
        return;
    }
    if (!ctxt->check) {
        if (dtd->name != NULL)
            fprintf(ctxt->output, "DTD(%s)", (char *) dtd->name);
        else
            fprintf(ctxt->output, "DTD");
        if (dtd->ExternalID != NULL)
            fprintf(ctxt->output, ", PUBLIC %s", (char *) dtd->ExternalID);
        if (dtd->SystemID != NULL)
            fprintf(ctxt->output, ", SYSTEM %s", (char *) dtd->SystemID);
        fprintf(ctxt->output, "\n");
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -