diff --git a/ChangeLog b/ChangeLog index a71d6b29..1c7dbb11 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Sun Feb 25 18:03:42 CET 2001 Daniel Veillard + + * xmlmemory.h HTMLparser.c HTMLtree.c entities.c parser.c + xpath.c xpointer.c tree.c uri.c valid.c xinclude.c xmlIO.c: + avoiding memcpy in production builds MEM_CLEANUP macro use + * parser.[ch] parserInternals.c: optimizations of the tightest + internal loops inside the parser. Better checking of I/O + flushing/loading conditions + * xmllint.c : added --timing + Sun Feb 25 05:48:51 CET 2001 Daniel Veillard * configure.in: bumped to 2.3.2 diff --git a/HTMLparser.c b/HTMLparser.c index 4fb40df8..9dffd58c 100644 --- a/HTMLparser.c +++ b/HTMLparser.c @@ -1651,7 +1651,7 @@ htmlFreeInputStream(htmlParserInputPtr input) { input->free((xmlChar *) input->base); if (input->buf != NULL) xmlFreeParserInputBuffer(input->buf); - memset(input, -1, sizeof(htmlParserInput)); + MEM_CLEANUP(input, sizeof(htmlParserInput)); xmlFree(input); } diff --git a/HTMLtree.c b/HTMLtree.c index 8c6354a5..bc328fc8 100644 --- a/HTMLtree.c +++ b/HTMLtree.c @@ -663,7 +663,7 @@ htmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) { htmlDocContentDump(buf, cur); *mem = buf->content; *size = buf->use; - memset(buf, -1, sizeof(xmlBuffer)); + MEM_CLEANUP(buf, sizeof(xmlBuffer)); xmlFree(buf); } diff --git a/aclocal.m4 b/aclocal.m4 index 869e5fcc..e3726759 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -620,31 +620,35 @@ esac ]) # AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for -# the libltdl convenience library, adds --enable-ltdl-convenience to -# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor -# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed -# to be `${top_builddir}/libltdl'. Make sure you start DIR with -# '${top_builddir}/' (note the single quotes!) if your package is not -# flat, and, if you're not using automake, define top_builddir as -# appropriate in the Makefiles. +# the libltdl convenience library and INCLTDL to the include flags for +# the libltdl header and adds --enable-ltdl-convenience to the +# configure arguments. Note that LIBLTDL and INCLTDL are not +# AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If DIR is not +# provided, it is assumed to be `libltdl'. LIBLTDL will be prefixed +# with '${top_builddir}/' and INCLTDL will be prefixed with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and +# top_srcdir appropriately in the Makefiles. AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl case "$enable_ltdl_convenience" in no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; "") enable_ltdl_convenience=yes ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; esac - LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdlc.la - INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl']) + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) ]) # AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for -# the libltdl installable library, and adds --enable-ltdl-install to -# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor -# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed -# to be `${top_builddir}/libltdl'. Make sure you start DIR with -# '${top_builddir}/' (note the single quotes!) if your package is not -# flat, and, if you're not using automake, define top_builddir as -# appropriate in the Makefiles. +# the libltdl installable library and INCLTDL to the include flags for +# the libltdl header and adds --enable-ltdl-install to the configure +# arguments. Note that LIBLTDL and INCLTDL are not AC_SUBSTed, nor is +# AC_CONFIG_SUBDIRS called. If DIR is not provided and an installed +# libltdl is not found, it is assumed to be `libltdl'. LIBLTDL will +# be prefixed with '${top_builddir}/' and INCLTDL will be prefixed +# with '${top_srcdir}/' (note the single quotes!). If your package is +# not flat and you're not using automake, define top_builddir and +# top_srcdir appropriately in the Makefiles. # In the future, this macro may have to be called after AC_PROG_LIBTOOL. AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_CHECK_LIB(ltdl, main, @@ -657,8 +661,8 @@ AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl ]) if test x"$enable_ltdl_install" = x"yes"; then ac_configure_args="$ac_configure_args --enable-ltdl-install" - LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdl.la - INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl']) + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) else ac_configure_args="$ac_configure_args --enable-ltdl-install=no" LIBLTDL="-lltdl" diff --git a/entities.c b/entities.c index 0fc4e8eb..8885c89b 100644 --- a/entities.c +++ b/entities.c @@ -84,7 +84,7 @@ void xmlFreeEntity(xmlEntityPtr entity) { xmlFree((char *) entity->content); if (entity->orig != NULL) xmlFree((char *) entity->orig); - memset(entity, -1, sizeof(xmlEntity)); + MEM_CLEANUP(entity, sizeof(xmlEntity)); xmlFree(entity); } diff --git a/include/libxml/parser.h b/include/libxml/parser.h index b98f2a33..0c82ce42 100644 --- a/include/libxml/parser.h +++ b/include/libxml/parser.h @@ -44,6 +44,7 @@ struct _xmlParserInput { const char *directory; /* the directory/base of teh file */ const xmlChar *base; /* Base of the array to parse */ const xmlChar *cur; /* Current char being parsed */ + const xmlChar *end; /* end of the arry to parse */ int length; /* length if known */ int line; /* Current line */ int col; /* Current column */ diff --git a/include/libxml/xmlmemory.h b/include/libxml/xmlmemory.h index 1e533d15..c909e4ce 100644 --- a/include/libxml/xmlmemory.h +++ b/include/libxml/xmlmemory.h @@ -15,6 +15,7 @@ * DEBUG_MEMORY_LOCATION should be activated only done when debugging * libxml. */ +/* #define DEBUG_MEMORY_FREED */ /* #define DEBUG_MEMORY_LOCATION */ #ifdef DEBUG @@ -27,6 +28,12 @@ #define MEM_LIST /* keep a list of all the allocated memory blocks */ #endif +#ifdef DEBUG_MEMORY_FREED +#define MEM_CLEANUP(p,l) memset((p), -1, (l)); +#else +#define MEM_CLEANUP(p,l) +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/parser.c b/parser.c index 55416288..0077ea5f 100644 --- a/parser.c +++ b/parser.c @@ -231,25 +231,24 @@ int spacePop(xmlParserCtxtPtr ctxt) { #define SKIP(val) do { \ ctxt->nbChars += (val),ctxt->input->cur += (val); \ if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \ - /* DEPR if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt); */\ if ((*ctxt->input->cur == 0) && \ (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \ xmlPopInput(ctxt); \ } while (0) -#define SHRINK do { \ +#define SHRINK if (ctxt->input->cur - ctxt->input->base > INPUT_CHUNK) {\ xmlParserInputShrink(ctxt->input); \ if ((*ctxt->input->cur == 0) && \ (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \ xmlPopInput(ctxt); \ - } while (0) + } -#define GROW do { \ +#define GROW if (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK) { \ xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \ if ((*ctxt->input->cur == 0) && \ (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \ xmlPopInput(ctxt); \ - } while (0) + } #define SKIP_BLANKS xmlSkipBlankChars(ctxt) @@ -261,7 +260,6 @@ int spacePop(xmlParserCtxtPtr ctxt) { } else ctxt->input->col++; \ ctxt->token = 0; ctxt->input->cur += l; \ if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \ - /* DEPR if (*ctxt->input->cur == '&') xmlParserHandleReference(ctxt); */\ } while (0) #define CUR_CHAR(l) xmlCurrentChar(ctxt, &l) @@ -1610,11 +1608,35 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) { xmlChar * xmlParseName(xmlParserCtxtPtr ctxt) { xmlChar buf[XML_MAX_NAMELEN + 5]; + const xmlChar *in; + xmlChar *ret; int len = 0, l; int c; int count = 0; GROW; + + /* + * Accelerator for simple ASCII names + */ + in = ctxt->input->cur; + if (((*in >= 0x61) && (*in <= 0x7A)) || + ((*in >= 0x41) && (*in <= 0x5A)) || + (*in == '_') || (*in == ':')) { + in++; + while (((*in >= 0x61) && (*in <= 0x7A)) || + ((*in >= 0x41) && (*in <= 0x5A)) || + ((*in >= 0x30) && (*in <= 0x39)) || + (*in == '_') || (*in == ':')) + in++; + if ((*in == ' ') || (*in == '>') || (*in == '/')) { + count = in - ctxt->input->cur; + ret = xmlStrndup(ctxt->input->cur, count); + ctxt->input->cur = in; + return(ret); + } + } + c = CUR_CHAR(l); if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */ (!IS_LETTER(c) && (c != '_') && @@ -2370,6 +2392,7 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { return(buf); } +void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata); /** * xmlParseCharData: * @ctxt: an XML parser context @@ -2388,6 +2411,61 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { void xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) { + const xmlChar *in; + int nbchar = 0; + + SHRINK; + GROW; + /* + * Accelerated common case where input don't need to be + * modified before passing it to the handler. + */ + if ((ctxt->token == 0) && (!cdata)) { + in = ctxt->input->cur; + do { + while (((*in >= 0x20) && (*in != '<') && + (*in != '&') && (*in <= 0x7F)) || (*in == 0x09)) + in++; + if (*in == 0xA) { + ctxt->input->line++; + continue; /* while */ + } + nbchar = in - ctxt->input->cur; + if (IS_BLANK(*ctxt->input->cur) && + areBlanks(ctxt, ctxt->input->cur, nbchar)) { + if (ctxt->sax->ignorableWhitespace != NULL) + ctxt->sax->ignorableWhitespace(ctxt->userData, + ctxt->input->cur, nbchar); + } else { + if (ctxt->sax->characters != NULL) + ctxt->sax->characters(ctxt->userData, + ctxt->input->cur, nbchar); + } + ctxt->input->cur = in; + if (*in == 0xD) { + in++; + if (*in == 0xA) { + ctxt->input->cur = in; + in++; + ctxt->input->line++; + continue; /* while */ + } + in--; + } + if ((*in == '<') || (*in == '&')) { + return; + } + SHRINK; + GROW; + in = ctxt->input->cur; + } while ((*in >= 0x20) && (*in <= 0x7F)); + nbchar = 0; + } + xmlParseCharDataComplex(ctxt, cdata); +} + +void +xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) { xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5]; int nbchar = 0; int cur, l; @@ -8193,6 +8271,8 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size, xmlParserInputBufferPush(ctxt->input->buf, size, chunk); ctxt->input->base = ctxt->input->buf->buffer->content + base; ctxt->input->cur = ctxt->input->base + cur; + ctxt->input->end = + &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use]; #ifdef DEBUG_PUSH xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size); #endif @@ -8327,6 +8407,8 @@ xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data, inputStream->buf = buf; inputStream->base = inputStream->buf->buffer->content; inputStream->cur = inputStream->buf->buffer->content; + inputStream->end = + &inputStream->buf->buffer->content[inputStream->buf->buffer->use]; if (enc != XML_CHAR_ENCODING_NONE) { xmlSwitchEncoding(ctxt, enc); } @@ -9317,6 +9399,8 @@ xmlCreateFileParserCtxt(const char *filename) inputStream->buf = buf; inputStream->base = inputStream->buf->buffer->content; inputStream->cur = inputStream->buf->buffer->content; + inputStream->end = + &inputStream->buf->buffer->content[inputStream->buf->buffer->use]; inputPush(ctxt, inputStream); if ((ctxt->directory == NULL) && (directory == NULL)) @@ -9455,6 +9539,7 @@ xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer, input->filename = xmlMemStrdup(filename); input->base = buffer; input->cur = buffer; + input->end = &buffer[xmlStrlen(buffer)]; inputPush(ctxt, input); } @@ -9543,6 +9628,7 @@ xmlCreateMemoryParserCtxt(char *buffer, int size) { input->buf = buf; input->base = input->buf->buffer->content; input->cur = input->buf->buffer->content; + input->end = &input->buf->buffer->content[input->buf->buffer->use]; inputPush(ctxt, input); return(ctxt); diff --git a/parser.h b/parser.h index b98f2a33..0c82ce42 100644 --- a/parser.h +++ b/parser.h @@ -44,6 +44,7 @@ struct _xmlParserInput { const char *directory; /* the directory/base of teh file */ const xmlChar *base; /* Base of the array to parse */ const xmlChar *cur; /* Current char being parsed */ + const xmlChar *end; /* end of the arry to parse */ int length; /* length if known */ int line; /* Current line */ int col; /* Current column */ diff --git a/parserInternals.c b/parserInternals.c index 65ebf5fb..e271e388 100644 --- a/parserInternals.c +++ b/parserInternals.c @@ -960,6 +960,7 @@ xmlParserInputRead(xmlParserInputPtr in, int len) { in->base = in->buf->buffer->content; in->cur = &in->buf->buffer->content[index]; } + in->end = &in->buf->buffer->content[in->buf->buffer->use]; CHECK_BUFFER(in); @@ -1005,7 +1006,7 @@ xmlParserInputGrow(xmlParserInputPtr in, int len) { return(0); /* - * NOTE : in->base may be a "dandling" i.e. freed pointer in this + * NOTE : in->base may be a "dangling" i.e. freed pointer in this * block, but we use it really as an integer to do some * pointer arithmetic. Insure will raise it as a bug but in * that specific case, that's not ! @@ -1018,6 +1019,7 @@ xmlParserInputGrow(xmlParserInputPtr in, int len) { in->base = in->buf->buffer->content; in->cur = &in->buf->buffer->content[index]; } + in->end = &in->buf->buffer->content[in->buf->buffer->use]; CHECK_BUFFER(in); @@ -1059,6 +1061,7 @@ xmlParserInputShrink(xmlParserInputPtr in) { in->cur -= ret; in->consumed += ret; } + in->end = &in->buf->buffer->content[in->buf->buffer->use]; } CHECK_BUFFER(in); @@ -1075,6 +1078,7 @@ xmlParserInputShrink(xmlParserInputPtr in) { in->base = in->buf->buffer->content; in->cur = &in->buf->buffer->content[index]; } + in->end = &in->buf->buffer->content[in->buf->buffer->use]; CHECK_BUFFER(in); } @@ -1769,6 +1773,8 @@ xmlSwitchToEncoding(xmlParserCtxtPtr ctxt, xmlCharEncodingHandlerPtr handler) } ctxt->input->base = ctxt->input->cur = ctxt->input->buf->buffer->content; + ctxt->input->end = + &ctxt->input->base[ctxt->input->buf->buffer->use]; } return(0); @@ -1817,6 +1823,8 @@ xmlSwitchToEncoding(xmlParserCtxtPtr ctxt, xmlCharEncodingHandlerPtr handler) ctxt->input->free((xmlChar *) ctxt->input->base); ctxt->input->base = ctxt->input->cur = ctxt->input->buf->buffer->content; + ctxt->input->end = + &ctxt->input->base[ctxt->input->buf->buffer->use]; } } } else { @@ -1859,7 +1867,7 @@ xmlFreeInputStream(xmlParserInputPtr input) { input->free((xmlChar *) input->base); if (input->buf != NULL) xmlFreeParserInputBuffer(input->buf); - memset(input, -1, sizeof(xmlParserInput)); + MEM_CLEANUP(input, sizeof(xmlParserInput)); xmlFree(input); } @@ -1918,6 +1926,7 @@ xmlNewIOInputStream(xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr input, inputStream->buf = input; inputStream->base = inputStream->buf->buffer->content; inputStream->cur = inputStream->buf->buffer->content; + inputStream->end = &inputStream->base[inputStream->buf->buffer->use]; if (enc != XML_CHAR_ENCODING_NONE) { xmlSwitchEncoding(ctxt, enc); } @@ -1989,6 +1998,7 @@ xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) { input->base = entity->content; input->cur = entity->content; input->length = entity->length; + input->end = &entity->content[input->length]; return(input); } @@ -2021,6 +2031,7 @@ xmlNewStringInputStream(xmlParserCtxtPtr ctxt, const xmlChar *buffer) { input->base = buffer; input->cur = buffer; input->length = xmlStrlen(buffer); + input->end = &buffer[input->length]; return(input); } @@ -2064,6 +2075,7 @@ xmlNewInputFromFile(xmlParserCtxtPtr ctxt, const char *filename) { inputStream->base = inputStream->buf->buffer->content; inputStream->cur = inputStream->buf->buffer->content; + inputStream->end = &inputStream->base[inputStream->buf->buffer->use]; if ((ctxt->directory == NULL) && (directory != NULL)) ctxt->directory = (char *) xmlStrdup((const xmlChar *) directory); return(inputStream); diff --git a/tree.c b/tree.c index ae9c8c29..42acf7c8 100644 --- a/tree.c +++ b/tree.c @@ -205,7 +205,7 @@ xmlFreeNs(xmlNsPtr cur) { } if (cur->href != NULL) xmlFree((char *) cur->href); if (cur->prefix != NULL) xmlFree((char *) cur->prefix); - memset(cur, -1, sizeof(xmlNs)); + MEM_CLEANUP(cur, sizeof(xmlNs)); xmlFree(cur); } @@ -423,7 +423,7 @@ xmlFreeDtd(xmlDtdPtr cur) { if (cur->pentities != NULL) xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->pentities); - memset(cur, -1, sizeof(xmlDtd)); + MEM_CLEANUP(cur, sizeof(xmlDtd)); xmlFree(cur); } @@ -485,7 +485,7 @@ xmlFreeDoc(xmlDocPtr cur) { if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids); if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs); if (cur->URL != NULL) xmlFree((char *) cur->URL); - memset(cur, -1, sizeof(xmlDoc)); + MEM_CLEANUP(cur, sizeof(xmlDoc)); xmlFree(cur); } @@ -1110,7 +1110,7 @@ xmlFreeProp(xmlAttrPtr cur) { xmlRemoveID(cur->parent->doc, cur); if (cur->name != NULL) xmlFree((char *) cur->name); if (cur->children != NULL) xmlFreeNodeList(cur->children); - memset(cur, -1, sizeof(xmlAttr)); + MEM_CLEANUP(cur, sizeof(xmlAttr)); xmlFree(cur); } @@ -2305,7 +2305,7 @@ xmlFreeNode(xmlNodePtr cur) { (cur->name != xmlStringComment)) xmlFree((char *) cur->name); if (cur->nsDef != NULL) xmlFreeNsList(cur->nsDef); - memset(cur, -1, sizeof(xmlNode)); + MEM_CLEANUP(cur, sizeof(xmlNode)); xmlFree(cur); } @@ -4511,13 +4511,13 @@ xmlBufferFree(xmlBufferPtr buf) { } if (buf->content != NULL) { #ifndef XML_USE_BUFFER_CONTENT - memset(buf->content, -1, BASE_BUFFER_SIZE); + MEM_CLEANUP(buf->content, BASE_BUFFER_SIZE); #else - memset(buf->content, -1, buf->size); + MEM_CLEANUP(buf->content, buf->size); #endif xmlFree(buf->content); } - memset(buf, -1, sizeof(xmlBuffer)); + MEM_CLEANUP(buf, sizeof(xmlBuffer)); xmlFree(buf); } @@ -4531,7 +4531,7 @@ void xmlBufferEmpty(xmlBufferPtr buf) { if (buf->content == NULL) return; buf->use = 0; - memset(buf->content, -1, buf->size);/* just for debug */ + MEM_CLEANUP(buf->content, buf->size); } /** diff --git a/uri.c b/uri.c index 31875f7f..51c18041 100644 --- a/uri.c +++ b/uri.c @@ -596,7 +596,7 @@ xmlFreeURI(xmlURIPtr uri) { if (uri->opaque != NULL) xmlFree(uri->opaque); if (uri->authority != NULL) xmlFree(uri->authority); if (uri->query != NULL) xmlFree(uri->query); - memset(uri, -1, sizeof(xmlURI)); + MEM_CLEANUP(uri, sizeof(xmlURI)); xmlFree(uri); } diff --git a/valid.c b/valid.c index 1b7e6f65..cbfa5e0c 100644 --- a/valid.c +++ b/valid.c @@ -317,7 +317,7 @@ xmlFreeElementContent(xmlElementContentPtr cur) { 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)); + MEM_CLEANUP(cur, sizeof(xmlElementContent)); xmlFree(cur); } @@ -482,7 +482,7 @@ xmlFreeElement(xmlElementPtr elem) { xmlFree((xmlChar *) elem->name); if (elem->prefix != NULL) xmlFree((xmlChar *) elem->prefix); - memset(elem, -1, sizeof(xmlElement)); + MEM_CLEANUP(elem, sizeof(xmlElement)); xmlFree(elem); } @@ -777,7 +777,7 @@ xmlFreeEnumeration(xmlEnumerationPtr cur) { if (cur->next != NULL) xmlFreeEnumeration(cur->next); if (cur->name != NULL) xmlFree((xmlChar *) cur->name); - memset(cur, -1, sizeof(xmlEnumeration)); + MEM_CLEANUP(cur, sizeof(xmlEnumeration)); xmlFree(cur); } @@ -937,7 +937,7 @@ xmlFreeAttribute(xmlAttributePtr attr) { xmlFree((xmlChar *) attr->defaultValue); if (attr->prefix != NULL) xmlFree((xmlChar *) attr->prefix); - memset(attr, -1, sizeof(xmlAttribute)); + MEM_CLEANUP(attr, sizeof(xmlAttribute)); xmlFree(attr); } @@ -1285,7 +1285,7 @@ xmlFreeNotation(xmlNotationPtr nota) { xmlFree((xmlChar *) nota->PublicID); if (nota->SystemID != NULL) xmlFree((xmlChar *) nota->SystemID); - memset(nota, -1, sizeof(xmlNotation)); + MEM_CLEANUP(nota, sizeof(xmlNotation)); xmlFree(nota); } @@ -1489,7 +1489,7 @@ xmlFreeID(xmlIDPtr id) { if (id == NULL) return; if (id->value != NULL) xmlFree((xmlChar *) id->value); - memset(id, -1, sizeof(xmlID)); + MEM_CLEANUP(id, sizeof(xmlID)); xmlFree(id); } @@ -1717,7 +1717,7 @@ xmlFreeRef(xmlLinkPtr lk) { if (ref == NULL) return; if (ref->value != NULL) xmlFree((xmlChar *)ref->value); - memset(ref, -1, sizeof(xmlRef)); + MEM_CLEANUP(ref, sizeof(xmlRef)); xmlFree(ref); } diff --git a/xinclude.c b/xinclude.c index c377f64e..343eef78 100644 --- a/xinclude.c +++ b/xinclude.c @@ -281,7 +281,7 @@ xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) { xmlFree(ctxt->txtTab); if (ctxt->txturlTab != NULL) xmlFree(ctxt->txturlTab); - memset(ctxt, 0xeb, sizeof(xmlXIncludeCtxt)); + MEM_CLEANUP(ctxt, sizeof(xmlXIncludeCtxt)); xmlFree(ctxt); } diff --git a/xmlIO.c b/xmlIO.c index 290ceab8..f623af9c 100644 --- a/xmlIO.c +++ b/xmlIO.c @@ -908,7 +908,7 @@ xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) { in->buffer = NULL; } - memset(in, 0xbe, (size_t) sizeof(xmlParserInputBuffer)); + MEM_CLEANUP(in, (size_t) sizeof(xmlParserInputBuffer)); xmlFree(in); } @@ -945,7 +945,7 @@ xmlOutputBufferClose(xmlOutputBufferPtr out) { out->buffer = NULL; } - memset(out, 0xbe, (size_t) sizeof(xmlOutputBuffer)); + MEM_CLEANUP(out, (size_t) sizeof(xmlOutputBuffer)); xmlFree(out); return(written); } diff --git a/xmllint.c b/xmllint.c index df4b4c1b..332146a2 100644 --- a/xmllint.c +++ b/xmllint.c @@ -16,6 +16,8 @@ #include #include #include +#include + #ifdef HAVE_SYS_TYPES_H #include @@ -88,6 +90,8 @@ static char *encoding = NULL; static int xinclude = 0; #endif static int progresult = 0; +static int timing = 0; +static struct timeval begin, end; #ifdef VMS @@ -386,6 +390,10 @@ void myClose(FILE *f) { void parseAndPrintFile(char *filename) { xmlDocPtr doc = NULL, tmp; + if ((timing) && (!repeat)) + gettimeofday(&begin, NULL); + + #ifdef LIBXML_HTML_ENABLED if (html) { doc = htmlParseFile(filename, NULL); @@ -527,9 +535,30 @@ void parseAndPrintFile(char *filename) { return; } + if ((timing) && (!repeat)) { + long msec; + gettimeofday(&end, NULL); + msec = end.tv_sec - begin.tv_sec; + msec *= 1000; + msec += (end.tv_usec - begin.tv_usec) / 1000; + fprintf(stderr, "Parsing took %ld ms\n", msec); + } + #ifdef LIBXML_XINCLUDE_ENABLED - if (xinclude) + if (xinclude) { + if ((timing) && (!repeat)) { + gettimeofday(&begin, NULL); + } xmlXIncludeProcess(doc); + if ((timing) && (!repeat)) { + long msec; + gettimeofday(&end, NULL); + msec = end.tv_sec - begin.tv_sec; + msec *= 1000; + msec += (end.tv_usec - begin.tv_usec) / 1000; + fprintf(stderr, "Xinclude processing took %ld ms\n", msec); + } + } #endif #ifdef LIBXML_DEBUG_ENABLED @@ -579,6 +608,9 @@ void parseAndPrintFile(char *filename) { #ifdef LIBXML_DEBUG_ENABLED if (!debug) { #endif + if ((timing) && (!repeat)) { + gettimeofday(&begin, NULL); + } if (memory) { xmlChar *result; int len; @@ -600,6 +632,14 @@ void parseAndPrintFile(char *filename) { xmlSaveFileEnc("-", doc, encoding); else xmlDocDump(stdout, doc); + if ((timing) && (!repeat)) { + long msec; + gettimeofday(&end, NULL); + msec = end.tv_sec - begin.tv_sec; + msec *= 1000; + msec += (end.tv_usec - begin.tv_usec) / 1000; + fprintf(stderr, "Saving took %ld ms\n", msec); + } #ifdef LIBXML_DEBUG_ENABLED } else { xmlDebugDumpDocument(stdout, doc); @@ -613,13 +653,27 @@ void parseAndPrintFile(char *filename) { if (dtdvalid != NULL) { xmlDtdPtr dtd; + if ((timing) && (!repeat)) { + gettimeofday(&begin, NULL); + } dtd = xmlParseDTD(NULL, (const xmlChar *)dtdvalid); + if ((timing) && (!repeat)) { + long msec; + gettimeofday(&end, NULL); + msec = end.tv_sec - begin.tv_sec; + msec *= 1000; + msec += (end.tv_usec - begin.tv_usec) / 1000; + fprintf(stderr, "Parsing DTD took %ld ms\n", msec); + } if (dtd == NULL) { xmlGenericError(xmlGenericErrorContext, "Could not parse DTD %s\n", dtdvalid); progresult = 2; } else { xmlValidCtxt cvp; + if ((timing) && (!repeat)) { + gettimeofday(&begin, NULL); + } cvp.userData = (void *) stderr; cvp.error = (xmlValidityErrorFunc) fprintf; cvp.warning = (xmlValidityWarningFunc) fprintf; if (!xmlValidateDtd(&cvp, doc, dtd)) { xmlGenericError(xmlGenericErrorContext, @@ -627,16 +681,35 @@ void parseAndPrintFile(char *filename) { filename, dtdvalid); progresult = 3; } + if ((timing) && (!repeat)) { + long msec; + gettimeofday(&end, NULL); + msec = end.tv_sec - begin.tv_sec; + msec *= 1000; + msec += (end.tv_usec - begin.tv_usec) / 1000; + fprintf(stderr, "Validating against DTD took %ld ms\n", msec); + } xmlFreeDtd(dtd); } } else if (postvalid) { xmlValidCtxt cvp; + if ((timing) && (!repeat)) { + gettimeofday(&begin, NULL); + } cvp.userData = (void *) stderr; cvp.error = (xmlValidityErrorFunc) fprintf; cvp.warning = (xmlValidityWarningFunc) fprintf; if (!xmlValidateDocument(&cvp, doc)) { xmlGenericError(xmlGenericErrorContext, "Document %s does not validate\n", filename); progresult = 3; } + if ((timing) && (!repeat)) { + long msec; + gettimeofday(&end, NULL); + msec = end.tv_sec - begin.tv_sec; + msec *= 1000; + msec += (end.tv_usec - begin.tv_usec) / 1000; + fprintf(stderr, "Validating took %ld ms\n", msec); + } } #ifdef LIBXML_DEBUG_ENABLED @@ -647,7 +720,18 @@ void parseAndPrintFile(char *filename) { /* * free it. */ + if ((timing) && (!repeat)) { + gettimeofday(&begin, NULL); + } xmlFreeDoc(doc); + if ((timing) && (!repeat)) { + long msec; + gettimeofday(&end, NULL); + msec = end.tv_sec - begin.tv_sec; + msec *= 1000; + msec += (end.tv_usec - begin.tv_usec) / 1000; + fprintf(stderr, "Freeing took %ld ms\n", msec); + } } int @@ -703,6 +787,9 @@ main(int argc, char **argv) { else if ((!strcmp(argv[i], "-insert")) || (!strcmp(argv[i], "--insert"))) insert++; + else if ((!strcmp(argv[i], "-timing")) || + (!strcmp(argv[i], "--timing"))) + timing++; else if ((!strcmp(argv[i], "-repeat")) || (!strcmp(argv[i], "--repeat"))) repeat++; @@ -784,6 +871,8 @@ main(int argc, char **argv) { i++; continue; } + if ((timing) && (repeat)) + gettimeofday(&begin, NULL); /* Remember file names. "-" means stding. */ if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) { if (repeat) { @@ -793,12 +882,20 @@ main(int argc, char **argv) { parseAndPrintFile(argv[i]); files ++; } + if ((timing) && (repeat)) { + long msec; + gettimeofday(&end, NULL); + msec = end.tv_sec - begin.tv_sec; + msec *= 1000; + msec += (end.tv_usec - begin.tv_usec) / 1000; + fprintf(stderr, "100 iteration took %ld ms\n", msec); + } } if ((htmlout) && (!nowrap)) { xmlGenericError(xmlGenericErrorContext, "\n"); } if (files == 0) { - printf("Usage : %s [--debug] [--debugent] [--copy] [--recover] [--noent] [--noout] [--valid] [--repeat] XMLfiles ...\n", + printf("Usage : %s [options] XMLfiles ...\n", argv[0]); printf("\tParse the XML files and output the result of the parsing\n"); #ifdef LIBXML_DEBUG_ENABLED @@ -815,6 +912,7 @@ main(int argc, char **argv) { printf("\t--valid : validate the document in addition to std well-formed check\n"); printf("\t--postvalid : do a posteriori validation, i.e after parsing\n"); printf("\t--dtdvalid URL : do a posteriori validation against a given DTD\n"); + printf("\t--timing : print some timings\n"); printf("\t--repeat : repeat 100 times, for timing or profiling\n"); printf("\t--insert : ad-hoc test for valid insertions\n"); printf("\t--compress : turn on gzip compression of output\n"); diff --git a/xmlmemory.h b/xmlmemory.h index 1e533d15..c909e4ce 100644 --- a/xmlmemory.h +++ b/xmlmemory.h @@ -15,6 +15,7 @@ * DEBUG_MEMORY_LOCATION should be activated only done when debugging * libxml. */ +/* #define DEBUG_MEMORY_FREED */ /* #define DEBUG_MEMORY_LOCATION */ #ifdef DEBUG @@ -27,6 +28,12 @@ #define MEM_LIST /* keep a list of all the allocated memory blocks */ #endif +#ifdef DEBUG_MEMORY_FREED +#define MEM_CLEANUP(p,l) memset((p), -1, (l)); +#else +#define MEM_CLEANUP(p,l) +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/xpath.c b/xpath.c index 63903f03..ff7a89b3 100644 --- a/xpath.c +++ b/xpath.c @@ -906,14 +906,10 @@ void xmlXPathFreeNodeSet(xmlNodeSetPtr obj) { if (obj == NULL) return; if (obj->nodeTab != NULL) { -#ifdef DEBUG - memset(obj->nodeTab, 0xB , (size_t) sizeof(xmlNodePtr) * obj->nodeMax); -#endif + MEM_CLEANUP(obj->nodeTab, (size_t) sizeof(xmlNodePtr) * obj->nodeMax); xmlFree(obj->nodeTab); } -#ifdef DEBUG - memset(obj, 0xB , (size_t) sizeof(xmlNodeSet)); -#endif + MEM_CLEANUP(obj, (size_t) sizeof(xmlNodeSet)); xmlFree(obj); } @@ -934,14 +930,10 @@ xmlXPathFreeValueTree(xmlNodeSetPtr obj) { xmlFreeNodeList(obj->nodeTab[i]); if (obj->nodeTab != NULL) { -#ifdef DEBUG - memset(obj->nodeTab, 0xB , (size_t) sizeof(xmlNodePtr) * obj->nodeMax); -#endif + MEM_CLEANUP(obj->nodeTab, (size_t) sizeof(xmlNodePtr) * obj->nodeMax); xmlFree(obj->nodeTab); } -#ifdef DEBUG - memset(obj, 0xB , (size_t) sizeof(xmlNodeSet)); -#endif + MEM_CLEANUP(obj, (size_t) sizeof(xmlNodeSet)); xmlFree(obj); } @@ -1098,9 +1090,7 @@ xmlXPathWrapNodeSet(xmlNodeSetPtr val) { void xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) { if (obj == NULL) return; -#ifdef DEBUG - memset(obj, 0xB , (size_t) sizeof(xmlXPathObject)); -#endif + MEM_CLEANUP(obj, (size_t) sizeof(xmlXPathObject)); xmlFree(obj); } @@ -1611,9 +1601,7 @@ xmlXPathFreeObject(xmlXPathObjectPtr obj) { xmlXPathFreeValueTree(obj->nodesetval); } -#ifdef DEBUG - memset(obj, 0xB , (size_t) sizeof(xmlXPathObject)); -#endif + MEM_CLEANUP(obj, (size_t) sizeof(xmlXPathObject)); xmlFree(obj); } @@ -1679,9 +1667,7 @@ xmlXPathFreeContext(xmlXPathContextPtr ctxt) { xmlXPathRegisteredNsCleanup(ctxt); xmlXPathRegisteredFuncsCleanup(ctxt); xmlXPathRegisteredVariablesCleanup(ctxt); -#ifdef DEBUG - memset(ctxt, 0xB , (size_t) sizeof(xmlXPathContext)); -#endif + MEM_CLEANUP(ctxt, (size_t) sizeof(xmlXPathContext)); xmlFree(ctxt); } @@ -1758,14 +1744,10 @@ xmlXPathNewParserContext(const xmlChar *str, xmlXPathContextPtr ctxt) { void xmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt) { if (ctxt->valueTab != NULL) { -#ifdef DEBUG - memset(ctxt->valueTab, 0xB , 10 * (size_t) sizeof(xmlXPathObjectPtr)); -#endif + MEM_CLEANUP(ctxt->valueTab, 10 * (size_t) sizeof(xmlXPathObjectPtr)); xmlFree(ctxt->valueTab); } -#ifdef DEBUG - memset(ctxt, 0xB , (size_t) sizeof(xmlXPathParserContext)); -#endif + MEM_CLEANUP(ctxt, (size_t) sizeof(xmlXPathParserContext)); xmlFree(ctxt); } diff --git a/xpointer.c b/xpointer.c index 7d2da1b1..9380d15b 100644 --- a/xpointer.c +++ b/xpointer.c @@ -715,15 +715,11 @@ xmlXPtrFreeLocationSet(xmlLocationSetPtr obj) { for (i = 0;i < obj->locNr; i++) { xmlXPathFreeObject(obj->locTab[i]); } -#ifdef DEBUG - memset(obj->locTab, 0xB , + MEM_CLEANUP(obj->locTab, (size_t) sizeof(xmlXPathObjectPtr) * obj->locMax); -#endif xmlFree(obj->locTab); } -#ifdef DEBUG - memset(obj, 0xB , (size_t) sizeof(xmlLocationSet)); -#endif + MEM_CLEANUP(obj, (size_t) sizeof(xmlLocationSet)); xmlFree(obj); }