📄 valid.c
字号:
/* * valid.c : part of the code use to do the DTD handling and the validity * checking * * See Copyright for the status of this software. * * Daniel.Veillard@w3.org */#include "global.h"#ifdef WIN32#include "win32config.h"#else#include "config.h"#endif#include <stdio.h>#include <string.h>#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#include <libxml/xmlmemory.h>#include <libxml/valid.h>#include <libxml/parser.h>#include <libxml/parserInternals.h>/* * Generic function for accessing stacks in the Validity Context */#define PUSH_AND_POP(scope, type, name) \scope int name##VPush(xmlValidCtxtPtr ctxt, type value) { \ if (ctxt->name##Nr >= ctxt->name##Max) { \ ctxt->name##Max *= 2; \ ctxt->name##Tab = (void *) xmlRealloc(ctxt->name##Tab, \ ctxt->name##Max * sizeof(ctxt->name##Tab[0])); \ if (ctxt->name##Tab == NULL) { \ fprintf(stderr, "realloc failed !\n"); \ return(0); \ } \ } \ ctxt->name##Tab[ctxt->name##Nr] = value; \ ctxt->name = value; \ return(ctxt->name##Nr++); \} \scope type name##VPop(xmlValidCtxtPtr ctxt) { \ type ret; \ if (ctxt->name##Nr <= 0) return(0); \ ctxt->name##Nr--; \ if (ctxt->name##Nr > 0) \ ctxt->name = ctxt->name##Tab[ctxt->name##Nr - 1]; \ else \ ctxt->name = NULL; \ ret = ctxt->name##Tab[ctxt->name##Nr]; \ ctxt->name##Tab[ctxt->name##Nr] = 0; \ return(ret); \} \PUSH_AND_POP(static, xmlNodePtr, node)/* #define DEBUG_VALID_ALGO */#ifdef DEBUG_VALID_ALGOvoid xmlValidPrintNodeList(xmlNodePtr cur) { if (cur == NULL) fprintf(stderr, "null "); while (cur != NULL) { switch (cur->type) { case XML_ELEMENT_NODE: fprintf(stderr, "%s ", cur->name); break; case XML_TEXT_NODE: fprintf(stderr, "text "); break; case XML_CDATA_SECTION_NODE: fprintf(stderr, "cdata "); break; case XML_ENTITY_REF_NODE: fprintf(stderr, "&%s; ", cur->name); break; case XML_PI_NODE: fprintf(stderr, "pi(%s) ", cur->name); break; case XML_COMMENT_NODE: fprintf(stderr, "comment "); break; case XML_ATTRIBUTE_NODE: fprintf(stderr, "?attr? "); break; case XML_ENTITY_NODE: fprintf(stderr, "?ent? "); break; case XML_DOCUMENT_NODE: fprintf(stderr, "?doc? "); break; case XML_DOCUMENT_TYPE_NODE: fprintf(stderr, "?doctype? "); break; case XML_DOCUMENT_FRAG_NODE: fprintf(stderr, "?frag? "); break; case XML_NOTATION_NODE: fprintf(stderr, "?nota? "); break; case XML_HTML_DOCUMENT_NODE: fprintf(stderr, "?html? "); break; case XML_DTD_NODE: fprintf(stderr, "?dtd? "); break; case XML_ELEMENT_DECL: fprintf(stderr, "?edecl? "); break; case XML_ATTRIBUTE_DECL: fprintf(stderr, "?adecl? "); break; case XML_ENTITY_DECL: fprintf(stderr, "?entdecl? "); break; } cur = cur->next; }}void xmlValidDebug(xmlNodePtr cur, xmlElementContentPtr cont) { char expr[1000]; expr[0] = 0; fprintf(stderr, "valid: "); xmlValidPrintNodeList(cur); fprintf(stderr, "against "); xmlSprintfElementContent(expr, cont, 0); fprintf(stderr, "%s\n", expr);}#define DEBUG_VALID_STATE(n,c) xmlValidDebug(n,c);#else#define DEBUG_VALID_STATE(n,c)#endif/* TODO: use hash table for accesses to elem and attribute dedinitions */#define VERROR \ if ((ctxt != NULL) && (ctxt->error != NULL)) ctxt->error#define VWARNING \ if ((ctxt != NULL) && (ctxt->warning != NULL)) ctxt->warning#define CHECK_DTD \ if (doc == NULL) return(0); \ else if (doc->intSubset == NULL) return(0)xmlElementPtr xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name);xmlAttributePtr xmlScanAttributeDecl(xmlDtdPtr dtd, const xmlChar *elem);/**************************************************************** * * * Util functions for data allocation/deallocation * * * ****************************************************************//** * xmlNewElementContent: * @name: the subelement name or NULL * @type: the type of element content decl * * Allocate an element content structure. * * Returns NULL if not, othervise the new element content structure */xmlElementContentPtrxmlNewElementContent(xmlChar *name, xmlElementContentType type) { xmlElementContentPtr ret; switch(type) { case XML_ELEMENT_CONTENT_ELEMENT: if (name == NULL) { fprintf(stderr, "xmlNewElementContent : name == NULL !\n"); } break; case XML_ELEMENT_CONTENT_PCDATA: case XML_ELEMENT_CONTENT_SEQ: case XML_ELEMENT_CONTENT_OR: if (name != NULL) { fprintf(stderr, "xmlNewElementContent : name != NULL !\n"); } break; default: fprintf(stderr, "xmlNewElementContent: unknown type %d\n", type); return(NULL); } ret = (xmlElementContentPtr) xmlMalloc(sizeof(xmlElementContent)); if (ret == NULL) { fprintf(stderr, "xmlNewElementContent : out of memory!\n"); return(NULL); } ret->type = type; ret->ocur = XML_ELEMENT_CONTENT_ONCE; if (name != NULL) ret->name = xmlStrdup(name); else ret->name = NULL; ret->c1 = ret->c2 = NULL; return(ret);}/** * xmlCopyElementContent: * @content: An element content pointer. * * Build a copy of an element content description. * * Returns the new xmlElementContentPtr or NULL in case of error. */xmlElementContentPtrxmlCopyElementContent(xmlElementContentPtr cur) { xmlElementContentPtr ret; if (cur == NULL) return(NULL); ret = xmlNewElementContent((xmlChar *) cur->name, cur->type); if (ret == NULL) { fprintf(stderr, "xmlCopyElementContent : out of memory\n"); return(NULL); } ret->ocur = cur->ocur; if (cur->c1 != NULL) ret->c1 = xmlCopyElementContent(cur->c1); if (cur->c2 != NULL) ret->c2 = xmlCopyElementContent(cur->c2); return(ret);}/** * xmlFreeElementContent: * @cur: the element content tree to free * * Free an element content structure. This is a recursive call ! */voidxmlFreeElementContent(xmlElementContentPtr cur) { if (cur == NULL) return; if (cur->c1 != NULL) xmlFreeElementContent(cur->c1); if (cur->c2 != NULL) xmlFreeElementContent(cur->c2); if (cur->name != NULL) xmlFree((xmlChar *) cur->name); memset(cur, -1, sizeof(xmlElementContent)); xmlFree(cur);}/** * xmlDumpElementContent: * @buf: An XML buffer * @content: An element table * @glob: 1 if one must print the englobing parenthesis, 0 otherwise * * This will dump the content of the element table as an XML DTD definition */voidxmlDumpElementContent(xmlBufferPtr buf, xmlElementContentPtr content, int glob) { if (content == NULL) return; if (glob) xmlBufferWriteChar(buf, "("); switch (content->type) { case XML_ELEMENT_CONTENT_PCDATA: xmlBufferWriteChar(buf, "#PCDATA"); break; case XML_ELEMENT_CONTENT_ELEMENT: xmlBufferWriteCHAR(buf, content->name); break; case XML_ELEMENT_CONTENT_SEQ: if ((content->c1->type == XML_ELEMENT_CONTENT_OR) || (content->c1->type == XML_ELEMENT_CONTENT_SEQ)) xmlDumpElementContent(buf, content->c1, 1); else xmlDumpElementContent(buf, content->c1, 0); xmlBufferWriteChar(buf, " , "); if (content->c2->type == XML_ELEMENT_CONTENT_OR) xmlDumpElementContent(buf, content->c2, 1); else xmlDumpElementContent(buf, content->c2, 0); break; case XML_ELEMENT_CONTENT_OR: if ((content->c1->type == XML_ELEMENT_CONTENT_OR) || (content->c1->type == XML_ELEMENT_CONTENT_SEQ)) xmlDumpElementContent(buf, content->c1, 1); else xmlDumpElementContent(buf, content->c1, 0); xmlBufferWriteChar(buf, " | "); if (content->c2->type == XML_ELEMENT_CONTENT_SEQ) xmlDumpElementContent(buf, content->c2, 1); else xmlDumpElementContent(buf, content->c2, 0); break; default: fprintf(stderr, "xmlDumpElementContent: unknown type %d\n", content->type); } if (glob) xmlBufferWriteChar(buf, ")"); switch (content->ocur) { case XML_ELEMENT_CONTENT_ONCE: break; case XML_ELEMENT_CONTENT_OPT: xmlBufferWriteChar(buf, "?"); break; case XML_ELEMENT_CONTENT_MULT: xmlBufferWriteChar(buf, "*"); break; case XML_ELEMENT_CONTENT_PLUS: xmlBufferWriteChar(buf, "+"); break; }}/** * xmlSprintfElementContent: * @buf: an output buffer * @content: An element table * @glob: 1 if one must print the englobing parenthesis, 0 otherwise * * This will dump the content of the element content definition * Intended just for the debug routine */voidxmlSprintfElementContent(char *buf, xmlElementContentPtr content, int glob) { if (content == NULL) return; if (glob) strcat(buf, "("); switch (content->type) { case XML_ELEMENT_CONTENT_PCDATA: strcat(buf, "#PCDATA"); break; case XML_ELEMENT_CONTENT_ELEMENT: strcat(buf, (char *) content->name); break; case XML_ELEMENT_CONTENT_SEQ: if ((content->c1->type == XML_ELEMENT_CONTENT_OR) || (content->c1->type == XML_ELEMENT_CONTENT_SEQ)) xmlSprintfElementContent(buf, content->c1, 1); else xmlSprintfElementContent(buf, content->c1, 0); strcat(buf, " , "); if (content->c2->type == XML_ELEMENT_CONTENT_OR) xmlSprintfElementContent(buf, content->c2, 1); else xmlSprintfElementContent(buf, content->c2, 0); break; case XML_ELEMENT_CONTENT_OR: if ((content->c1->type == XML_ELEMENT_CONTENT_OR) || (content->c1->type == XML_ELEMENT_CONTENT_SEQ)) xmlSprintfElementContent(buf, content->c1, 1); else xmlSprintfElementContent(buf, content->c1, 0); strcat(buf, " | "); if (content->c2->type == XML_ELEMENT_CONTENT_SEQ) xmlSprintfElementContent(buf, content->c2, 1); else xmlSprintfElementContent(buf, content->c2, 0); break; } if (glob) strcat(buf, ")"); switch (content->ocur) { case XML_ELEMENT_CONTENT_ONCE: break; case XML_ELEMENT_CONTENT_OPT: strcat(buf, "?"); break; case XML_ELEMENT_CONTENT_MULT: strcat(buf, "*"); break; case XML_ELEMENT_CONTENT_PLUS: strcat(buf, "+"); break; }}/**************************************************************** * * * Registration of DTD declarations * * * ****************************************************************//** * xmlCreateElementTable: * * create and initialize an empty element hash table. * * Returns the xmlElementTablePtr just created or NULL in case of error. */xmlElementTablePtrxmlCreateElementTable(void) { xmlElementTablePtr ret; ret = (xmlElementTablePtr) xmlMalloc(sizeof(xmlElementTable)); if (ret == NULL) { fprintf(stderr, "xmlCreateElementTable : xmlMalloc(%ld) failed\n", (long)sizeof(xmlElementTable)); return(NULL); } ret->max_elements = XML_MIN_ELEMENT_TABLE; ret->nb_elements = 0; ret->table = (xmlElementPtr *) xmlMalloc(ret->max_elements * sizeof(xmlElementPtr)); if (ret == NULL) { fprintf(stderr, "xmlCreateElementTable : xmlMalloc(%ld) failed\n", ret->max_elements * (long)sizeof(xmlElement)); xmlFree(ret); return(NULL); } return(ret);}/** * xmlAddElementDecl: * @ctxt: the validation context * @dtd: pointer to the DTD * @name: the entity name * @type: the element type * @content: the element content tree or NULL * * Register a new element declaration * * Returns NULL if not, othervise the entity */xmlElementPtrxmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name, xmlElementTypeVal type, xmlElementContentPtr content) { xmlElementPtr ret, cur; xmlElementTablePtr table; int i; if (dtd == NULL) { fprintf(stderr, "xmlAddElementDecl: dtd == NULL\n"); return(NULL); } if (name == NULL) { fprintf(stderr, "xmlAddElementDecl: name == NULL\n"); return(NULL); } switch (type) { case XML_ELEMENT_TYPE_EMPTY: if (content != NULL) { fprintf(stderr, "xmlAddElementDecl: content != NULL for EMPTY\n"); return(NULL); } break; case XML_ELEMENT_TYPE_ANY: if (content != NULL) { fprintf(stderr, "xmlAddElementDecl: content != NULL for ANY\n"); return(NULL); } break; case XML_ELEMENT_TYPE_MIXED: if (content == NULL) { fprintf(stderr, "xmlAddElementDecl: content == NULL for MIXED\n"); return(NULL); } break; case XML_ELEMENT_TYPE_ELEMENT: if (content == NULL) { fprintf(stderr, "xmlAddElementDecl: content == NULL for ELEMENT\n"); return(NULL); } break; default: fprintf(stderr, "xmlAddElementDecl: unknown type %d\n", type); return(NULL); } /* * Create the Element table if needed. */ table = dtd->elements; if (table == NULL) table = dtd->elements = xmlCreateElementTable(); if (table == NULL) { fprintf(stderr, "xmlAddElementDecl: Table creation failed!\n"); return(NULL); } /* * Validity Check: * Search the DTD for previous declarations of the ELEMENT */ for (i = 0;i < table->nb_elements;i++) { cur = table->table[i]; if (!xmlStrcmp(cur->name, name)) { /* * The element is already defined in this Dtd. */ VERROR(ctxt->userData, "Redefinition of element %s\n", name); return(NULL); } } /* * Grow the table, if needed. */ if (table->nb_elements >= table->max_elements) { /* * need more elements. */ table->max_elements *= 2; table->table = (xmlElementPtr *) xmlRealloc(table->table, table->max_elements * sizeof(xmlElementPtr)); if (table->table == NULL) { fprintf(stderr, "xmlAddElementDecl: out of memory\n"); return(NULL); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -