summaryrefslogtreecommitdiffstats
path: root/libjava/classpath/native/jni/xmlj/xmlj_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/native/jni/xmlj/xmlj_io.c')
-rw-r--r--libjava/classpath/native/jni/xmlj/xmlj_io.c799
1 files changed, 799 insertions, 0 deletions
diff --git a/libjava/classpath/native/jni/xmlj/xmlj_io.c b/libjava/classpath/native/jni/xmlj/xmlj_io.c
new file mode 100644
index 00000000000..aa2964dc312
--- /dev/null
+++ b/libjava/classpath/native/jni/xmlj/xmlj_io.c
@@ -0,0 +1,799 @@
+/* xmlj_io.c -
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+#include "xmlj_io.h"
+#include "xmlj_error.h"
+#include "xmlj_node.h"
+#include "xmlj_sax.h"
+#include "xmlj_util.h"
+
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <libxml/xmlIO.h>
+#include <libxml/parserInternals.h>
+
+#include <pthread.h>
+
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define UNSIGN(a) (((a) < 0) ? ((a) + 0x100) : (a))
+
+#define DETECT_BUFFER_SIZE 50
+
+typedef struct _OutputStreamContext
+{
+
+ JNIEnv *env;
+ jobject outputStream;
+ jmethodID outputStreamWriteFunc;
+ jmethodID outputStreamCloseFunc;
+
+}
+OutputStreamContext;
+
+typedef struct _InputStreamContext
+{
+
+ JNIEnv *env;
+ jobject inputStream;
+ jmethodID inputStreamReadFunc;
+ jmethodID inputStreamCloseFunc;
+ jobject bufferByteArray;
+ jint bufferLength;
+
+}
+InputStreamContext;
+
+InputStreamContext *xmljNewInputStreamContext (JNIEnv * env,
+ jobject inputStream);
+
+void xmljFreeInputStreamContext (InputStreamContext * inContext);
+
+int xmljInputReadCallback (void *context, char *buffer, int len);
+
+int xmljInputCloseCallback (void *context);
+
+int xmljOutputWriteCallback (void *context, const char *buffer, int len);
+
+int xmljOutputCloseCallback (void *context);
+
+OutputStreamContext *xmljNewOutputStreamContext (JNIEnv * env,
+ jobject outputStream);
+
+void
+xmljFreeOutputStreamContext (OutputStreamContext * outContext);
+
+xmlCharEncoding
+xmljDetectCharEncoding (JNIEnv * env, jbyteArray buffer);
+
+int
+xmljOutputWriteCallback (void *context, const char *buffer, int len)
+{
+ OutputStreamContext *outContext;
+ JNIEnv *env;
+ jbyteArray byteArray;
+
+ outContext = (OutputStreamContext *) context;
+ env = outContext->env;
+ byteArray = (*env)->NewByteArray (env, len);
+
+ if (0 != byteArray)
+ {
+ (*env)->SetByteArrayRegion (env, byteArray, 0, len, (jbyte *) buffer);
+
+ (*env)->CallVoidMethod (env,
+ outContext->outputStream,
+ outContext->outputStreamWriteFunc, byteArray);
+
+ (*env)->DeleteLocalRef (env, byteArray);
+
+ return (*env)->ExceptionOccurred (env) ? -1 : len;
+ }
+ else
+ {
+ /* Out of memory, signal error */
+ return -1;
+ }
+}
+
+int
+xmljOutputCloseCallback (void *context)
+{
+ OutputStreamContext *outContext;
+ JNIEnv *env;
+
+ outContext = (OutputStreamContext *) context;
+ env = outContext->env;
+ (*env)->CallVoidMethod (env,
+ outContext->outputStream,
+ outContext->outputStreamCloseFunc);
+
+ return (*env)->ExceptionOccurred (env) ? -1 : 0;
+}
+
+int
+xmljInputReadCallback (void *context, char *buffer, int len)
+{
+ InputStreamContext *inContext;
+ JNIEnv *env;
+ jint nread;
+ int offset;
+
+ inContext = (InputStreamContext *) context;
+ env = inContext->env;
+ nread = 0;
+
+ for (offset = 0; offset < len && nread >= 0;)
+ {
+ nread = (*env)->CallIntMethod (env,
+ inContext->inputStream,
+ inContext->inputStreamReadFunc,
+ inContext->bufferByteArray,
+ 0, MIN (len - offset,
+ inContext->bufferLength));
+
+ if (nread > 0)
+ {
+ (*env)->GetByteArrayRegion (env,
+ inContext->bufferByteArray,
+ 0, nread, ((jbyte *) buffer) + offset);
+
+ offset += nread;
+ }
+ }
+
+ return (*env)->ExceptionOccurred (env) ? -1 : offset;
+}
+
+int
+xmljInputCloseCallback (void *context)
+{
+ InputStreamContext *inContext;
+ JNIEnv *env;
+
+ inContext = (InputStreamContext *) context;
+ env = inContext->env;
+ (*env)->CallVoidMethod (env, inContext->inputStream,
+ inContext->inputStreamCloseFunc);
+
+ return (*env)->ExceptionOccurred (env) ? -1 : 0;
+}
+
+InputStreamContext *
+xmljNewInputStreamContext (JNIEnv * env, jobject inputStream)
+{
+ jclass inputStreamClass;
+ InputStreamContext *result;
+
+ inputStreamClass = (*env)->FindClass (env, "java/io/InputStream");
+ if (inputStreamClass == NULL)
+ {
+ return NULL;
+ }
+ result = (InputStreamContext *) malloc (sizeof (InputStreamContext));
+ if (result == NULL)
+ {
+ return NULL;
+ }
+
+ result->env = env;
+ result->inputStream = inputStream;
+ result->inputStreamReadFunc =
+ (*env)->GetMethodID (env, inputStreamClass, "read", "([BII)I");
+ result->inputStreamCloseFunc =
+ (*env)->GetMethodID (env, inputStreamClass, "close", "()V");
+ result->bufferLength = 4096;
+ result->bufferByteArray = (*env)->NewByteArray (env, result->bufferLength);
+ return result;
+}
+
+void
+xmljFreeInputStreamContext (InputStreamContext * inContext)
+{
+ JNIEnv *env;
+
+ env = inContext->env;
+ (*env)->DeleteLocalRef (env, inContext->bufferByteArray);
+ free (inContext);
+}
+
+OutputStreamContext *
+xmljNewOutputStreamContext (JNIEnv * env, jobject outputStream)
+{
+ jclass outputStreamClass;
+ OutputStreamContext *result;
+
+ outputStreamClass = (*env)->FindClass (env, "java/io/OutputStream");
+ if (outputStreamClass == NULL)
+ {
+ return NULL;
+ }
+ result = (OutputStreamContext *) malloc (sizeof (OutputStreamContext));
+ if (result == NULL)
+ {
+ return NULL;
+ }
+
+ result->env = env;
+ result->outputStream = outputStream;
+ result->outputStreamWriteFunc =
+ (*env)->GetMethodID (env, outputStreamClass, "write", "([B)V");
+ result->outputStreamCloseFunc =
+ (*env)->GetMethodID (env, outputStreamClass, "close", "()V");
+ return result;
+}
+
+
+void
+xmljFreeOutputStreamContext (OutputStreamContext * outContext)
+{
+ free (outContext);
+}
+
+SAXParseContext *
+xmljNewSAXParseContext (JNIEnv * env, jobject obj, xmlParserCtxtPtr ctx,
+ jstring publicId, jstring systemId)
+{
+ SAXParseContext *ret;
+
+ ret = (SAXParseContext *) malloc (sizeof (SAXParseContext));
+ ret->env = env;
+ ret->obj = obj;
+ ret->ctx = ctx;
+ ret->sax = ctx->sax;
+ ret->loc = NULL;
+ ret->publicId = publicId;
+ ret->systemId = systemId;
+
+ ret->startDTD = NULL;
+ ret->externalEntityDecl = NULL;
+ ret->internalEntityDecl = NULL;
+ ret->resolveEntity = NULL;
+ ret->notationDecl = NULL;
+ ret->attributeDecl = NULL;
+ ret->elementDecl = NULL;
+ ret->unparsedEntityDecl = NULL;
+ ret->setDocumentLocator = NULL;
+ ret->startDocument = NULL;
+ ret->endDocument = NULL;
+ ret->startElement = NULL;
+ ret->endElement = NULL;
+ ret->characters = NULL;
+ ret->ignorableWhitespace = NULL;
+ ret->processingInstruction = NULL;
+ ret->comment = NULL;
+ ret->cdataBlock = NULL;
+ ret->warning = NULL;
+ ret->error = NULL;
+ ret->fatalError = NULL;
+
+ ret->resolveURIAndOpen = NULL;
+ ret->stringClass = NULL;
+ return ret;
+}
+
+void
+xmljFreeSAXParseContext (SAXParseContext * saxCtx)
+{
+ free (saxCtx);
+}
+
+xmlCharEncoding
+xmljDetectCharEncoding (JNIEnv * env, jbyteArray buffer)
+{
+ xmlCharEncoding ret;
+ jint nread;
+
+ if (buffer == NULL)
+ {
+ return XML_CHAR_ENCODING_ERROR;
+ }
+ nread = (*env)->GetArrayLength (env, buffer);
+ if (nread >= 5)
+ {
+ jbyte nativeBuffer[DETECT_BUFFER_SIZE + 1];
+ unsigned char converted[DETECT_BUFFER_SIZE + 1];
+ int i;
+
+ memset (nativeBuffer, 0, DETECT_BUFFER_SIZE + 1);
+ (*env)->GetByteArrayRegion (env, buffer, 0, nread, nativeBuffer);
+ /* Convert from signed to unsigned */
+ for (i = 0; i < DETECT_BUFFER_SIZE + 1; i++)
+ {
+ converted[i] = UNSIGN (nativeBuffer[i]);
+ }
+ ret = xmlDetectCharEncoding (converted, nread);
+ }
+ else
+ {
+ ret = XML_CHAR_ENCODING_NONE;
+ }
+ return ret;
+}
+
+xmlParserCtxtPtr
+xmljNewParserContext (JNIEnv * env,
+ jobject inputStream,
+ jbyteArray detectBuffer,
+ jstring publicId,
+ jstring systemId,
+ jstring base,
+ jboolean validate,
+ jboolean coalesce,
+ jboolean expandEntities,
+ jboolean loadEntities)
+{
+ InputStreamContext *inputContext;
+ xmlCharEncoding encoding;
+ xmlParserCtxtPtr ctx;
+ int options;
+
+ encoding = xmljDetectCharEncoding (env, detectBuffer);
+ if (encoding != XML_CHAR_ENCODING_ERROR)
+ {
+ inputContext = xmljNewInputStreamContext (env, inputStream);
+ if (NULL != inputContext)
+ {
+ /* NOTE: userdata must be NULL for DOM to work */
+ ctx = xmlCreateIOParserCtxt (NULL,
+ NULL,
+ xmljInputReadCallback,
+ xmljInputCloseCallback,
+ inputContext,
+ encoding);
+ if (NULL != ctx)
+ {
+ ctx->userData = ctx;
+
+ /* Set parsing options */
+ options = 0;
+ if (validate)
+ {
+ options |= XML_PARSE_DTDVALID;
+ }
+ if (coalesce)
+ {
+ options |= XML_PARSE_NOCDATA;
+ }
+ if (expandEntities)
+ {
+ options |= XML_PARSE_NOENT;
+ }
+ if (loadEntities)
+ {
+ options |= XML_PARSE_DTDLOAD;
+ }
+ if (xmlCtxtUseOptions (ctx, options))
+ {
+ xmljThrowException (env,
+ "java/lang/RuntimeException",
+ "Unable to set xmlParserCtxtPtr options");
+ }
+ if (base != NULL)
+ {
+ ctx->input->directory =
+ (*env)->GetStringUTFChars (env, base, 0);
+ }
+ return ctx;
+ }
+ xmljFreeInputStreamContext (inputContext);
+ }
+ }
+ return NULL;
+}
+
+void
+xmljFreeParserContext (xmlParserCtxtPtr ctx)
+{
+ InputStreamContext *inputStreamContext = NULL;
+
+ if (ctx->input != NULL && ctx->input->buf != NULL)
+ {
+ inputStreamContext
+ = (InputStreamContext *) ctx->input->buf->context;
+
+ }
+ xmlFreeParserCtxt (ctx);
+ if (inputStreamContext != NULL)
+ {
+ xmljFreeInputStreamContext (inputStreamContext);
+ }
+}
+
+xmlDocPtr
+xmljParseDocument (JNIEnv * env,
+ jobject self,
+ jobject in,
+ jbyteArray detectBuffer,
+ jstring publicId,
+ jstring systemId,
+ jstring base,
+ jboolean validate,
+ jboolean coalesce,
+ jboolean expandEntities,
+ jboolean contentHandler,
+ jboolean dtdHandler,
+ jboolean entityResolver,
+ jboolean errorHandler,
+ jboolean declarationHandler,
+ jboolean lexicalHandler,
+ int mode)
+{
+ xmlParserCtxtPtr ctx;
+ SAXParseContext *saxCtx;
+ xmlSAXHandlerPtr sax;
+
+ ctx = xmljNewParserContext (env, in, detectBuffer, publicId, systemId, base,
+ validate, coalesce, expandEntities,
+ entityResolver);
+ if (ctx != NULL)
+ {
+ saxCtx = xmljNewSAXParseContext (env, self, ctx, publicId, systemId);
+ if (saxCtx != NULL)
+ {
+ sax = xmljNewSAXHandler (contentHandler,
+ dtdHandler,
+ entityResolver,
+ errorHandler,
+ declarationHandler,
+ lexicalHandler);
+ if (sax != NULL)
+ {
+ return xmljParseDocument2 (env,
+ ctx,
+ saxCtx,
+ sax,
+ mode);
+ }
+ xmljFreeSAXParseContext (saxCtx);
+ }
+ xmljFreeParserContext (ctx);
+ }
+ if (!(*env)->ExceptionOccurred (env))
+ {
+ xmljThrowException (env, "java/io/IOException",
+ "Unable to create parser context");
+ }
+ return NULL;
+}
+
+xmlDocPtr
+xmljParseDocument2 (JNIEnv * env,
+ xmlParserCtxtPtr ctx,
+ SAXParseContext *saxCtx,
+ xmlSAXHandlerPtr sax,
+ int mode)
+{
+ xmlSAXHandlerPtr orig;
+ xmlDocPtr doc;
+ int ret;
+
+ ctx->_private = saxCtx;
+ ctx->userData = ctx;
+ orig = ctx->sax;
+ ctx->sax = sax;
+
+ xmljSetThreadContext (saxCtx);
+
+ ret = xmlParseDocument (ctx);
+ doc = ctx->myDoc;
+ if (ret || !doc)
+ {
+ const char *msg = ctx->lastError.message;
+ switch (mode)
+ {
+ case 0:
+ xmljSAXFatalError (ctx, msg);
+ break;
+ case 1:
+ xmljThrowDOMException (env, ret, msg);
+ break;
+ case 2:
+ xmljThrowException (env,
+ "javax/xml/transform/TransformerException",
+ msg);
+ }
+ }
+
+ xmljClearThreadContext ();
+
+ ctx->sax = orig;
+ free(sax);
+ xmljFreeSAXParseContext (saxCtx);
+ xmljFreeParserContext (ctx);
+ xmljClearStringCache ();
+ return doc;
+}
+
+xmlParserInputPtr
+xmljNewParserInput (JNIEnv * env,
+ jobject inputStream,
+ jbyteArray detectBuffer,
+ xmlParserCtxtPtr parserContext)
+{
+ xmlParserInputPtr ret;
+ xmlParserInputBufferPtr input;
+ xmlCharEncoding encoding;
+
+ encoding = xmljDetectCharEncoding (env, detectBuffer);
+ if (encoding != XML_CHAR_ENCODING_ERROR)
+ {
+ input = xmljNewParserInputBuffer (env, inputStream, encoding);
+ if (input != NULL)
+ {
+ ret = xmlNewIOInputStream (parserContext, input, encoding);
+ return ret;
+ }
+ xmlFreeParserInputBuffer (input);
+ }
+ return NULL;
+}
+
+xmlParserInputBufferPtr
+xmljNewParserInputBuffer (JNIEnv * env,
+ jobject inputStream, xmlCharEncoding encoding)
+{
+ xmlParserInputBufferPtr ret;
+ InputStreamContext *inputContext;
+
+ inputContext = xmljNewInputStreamContext (env, inputStream);
+ if (NULL != inputContext)
+ {
+ ret = xmlParserInputBufferCreateIO (&xmljInputReadCallback,
+ &xmljInputCloseCallback,
+ inputContext, encoding);
+ if (ret != NULL)
+ return ret;
+ xmljFreeInputStreamContext (inputContext);
+ }
+ return NULL;
+}
+
+void
+xmljSaveFileToJavaOutputStream (JNIEnv * env, jobject outputStream,
+ xmlDocPtr tree,
+ const char *outputEncodingName)
+{
+ OutputStreamContext *outputContext =
+ xmljNewOutputStreamContext (env, outputStream);
+
+ xmlCharEncoding outputEncoding = xmlParseCharEncoding (outputEncodingName);
+
+ xmlOutputBufferPtr outputBuffer =
+ xmlOutputBufferCreateIO (xmljOutputWriteCallback,
+ xmljOutputCloseCallback,
+ outputContext,
+ xmlGetCharEncodingHandler (outputEncoding));
+
+ /* Write result to output stream */
+
+ xmlSaveFileTo (outputBuffer, tree, outputEncodingName);
+
+ xmljFreeOutputStreamContext (outputContext);
+}
+
+/*
+jobject
+xmljResolveURI (SaxErrorContext * saxErrorContext,
+ const char *URL, const char *ID)
+{
+ JNIEnv *env = saxErrorContext->env;
+
+ jstring hrefString = (*env)->NewStringUTF (env, URL);
+ jstring baseString = saxErrorContext->systemId;
+
+ jobject sourceWrapper = (*env)->CallObjectMethod (env,
+ saxErrorContext->
+ saxErrorAdapter,
+ saxErrorContext->
+ resolveURIMethodID,
+ hrefString,
+ baseString);
+ (*env)->DeleteLocalRef (env, hrefString);
+
+ if (NULL == sourceWrapper)
+ {
+ return NULL;
+ }
+ else
+ {
+ jobject sourceInputStream = (*env)->CallObjectMethod (env,
+ sourceWrapper,
+ saxErrorContext->
+ getInputStreamMethodID);
+
+ (*env)->DeleteLocalRef (env, sourceWrapper);
+
+ if ((*env)->ExceptionOccurred (env))
+ {
+ -* Report to ErrorAdapter here? *-
+ return NULL;
+ }
+
+ return sourceInputStream;
+ }
+}*/
+
+xmlDocPtr
+xmljResolveURIAndOpen (SAXParseContext *saxContext,
+ const char *URL,
+ const char *ID)
+{
+ jobject libxmlDocument;
+ xmlDocPtr doc;
+ JNIEnv *env = saxContext->env;
+
+ jstring hrefString = (*env)->NewStringUTF (env, URL);
+ jstring baseString = saxContext->systemId;
+
+ if (saxContext->resolveURIAndOpen == NULL)
+ {
+ jclass cls = (*env)->GetObjectClass (env, saxContext->obj);
+ saxContext->resolveURIAndOpen =
+ (*env)->GetMethodID (env, cls, "resolveURIAndOpen",
+ "Ljava/lang/String;Ljava/lang/String)Lgnu/xml/libxmlj/transform/LibxmlDocument;");
+ }
+ libxmlDocument =
+ (*env)->CallObjectMethod (env,
+ saxContext->obj,
+ saxContext->resolveURIAndOpen,
+ hrefString,
+ baseString);
+
+ doc = (xmlDocPtr) xmljGetNodeID (env, libxmlDocument);
+
+ (*env)->DeleteLocalRef (env, libxmlDocument);
+
+ if ((*env)->ExceptionOccurred (env))
+ {
+ /* Report to ErrorAdapter here? */
+ return NULL;
+ }
+ else
+ {
+ return doc;
+ }
+}
+
+/*xmlParserInputPtr
+xmljLoadExternalEntity (const char *URL, const char *ID,
+ xmlParserCtxtPtr ctxt)
+{
+ SaxErrorContext *saxErrorContext = xmljGetThreadContext ();
+
+ JNIEnv *env = saxErrorContext->env;
+
+ jstring hrefString = (*env)->NewStringUTF (env, URL);
+ jstring baseString = saxErrorContext->systemId;
+
+ jobject sourceWrapper = (*env)->CallObjectMethod (env,
+ saxErrorContext->
+ saxErrorAdapter,
+ saxErrorContext->
+ resolveURIMethodID,
+ hrefString,
+ baseString);
+
+ (*env)->DeleteLocalRef (env, hrefString);
+
+ if (NULL == sourceWrapper)
+ {
+ return NULL;
+ }
+ else
+ {
+ InputStreamContext *inputContext;
+ xmlParserInputBufferPtr inputBuffer;
+ xmlParserInputPtr inputStream;
+
+ jobject sourceInputStream = (*env)->CallObjectMethod (env,
+ sourceWrapper,
+ saxErrorContext->
+ getInputStreamMethodID);
+
+ (*env)->DeleteLocalRef (env, sourceWrapper);
+
+ if ((*env)->ExceptionOccurred (env))
+ {
+ -* Report to ErrorAdapter *-
+ return NULL;
+ }
+
+ inputContext = xmljNewInputStreamContext (env, sourceInputStream);
+
+ inputBuffer
+ = xmlParserInputBufferCreateIO (xmljInputReadCallback,
+ xmljInputCloseCallback,
+ inputContext, XML_CHAR_ENCODING_NONE);
+
+ inputStream = xmlNewInputStream (ctxt);
+ if (inputStream == NULL)
+ {
+ return (NULL);
+ }
+
+ inputStream->filename = NULL;
+ inputStream->directory = NULL;
+ inputStream->buf = inputBuffer;
+
+ inputStream->base = inputStream->buf->buffer->content;
+ inputStream->cur = inputStream->buf->buffer->content;
+ inputStream->end = &inputStream->base[inputStream->buf->buffer->use];
+ if ((ctxt->directory == NULL) && (inputStream->directory != NULL))
+ ctxt->directory =
+ (char *) xmlStrdup ((const xmlChar *) inputStream->directory);
+ return (inputStream);
+ }
+}*/
+
+/* Key for the thread-specific buffer */
+static pthread_key_t thread_context_key;
+
+/* Once-only initialisation of the key */
+static pthread_once_t thread_context_once = PTHREAD_ONCE_INIT;
+
+static void
+thread_context_key_alloc (void);
+
+/* Allocate the key */
+static void
+thread_context_key_alloc ()
+{
+ pthread_key_create (&thread_context_key, NULL);
+}
+
+void
+xmljSetThreadContext (SAXParseContext * context)
+{
+ pthread_once (&thread_context_once, thread_context_key_alloc);
+ pthread_setspecific (thread_context_key, context);
+}
+
+void
+xmljClearThreadContext (void)
+{
+ pthread_setspecific (thread_context_key, NULL);
+}
+
+/* Return the thread-specific buffer */
+SAXParseContext *
+xmljGetThreadContext (void)
+{
+ return (SAXParseContext *) pthread_getspecific (thread_context_key);
+}
OpenPOWER on IntegriCloud