xmlparse.c

来自「ARM上的如果你对底层感兴趣」· C语言 代码 · 共 2,269 行 · 第 1/5 页

C
2,269
字号
      return XML_ERROR_NO_MEMORY;
    if ((attId->name)[-1]) {
      if (enc == encoding)
	eventPtr = atts[i].name;
      return XML_ERROR_DUPLICATE_ATTRIBUTE;
    }
    (attId->name)[-1] = 1;
    appAtts[attIndex++] = attId->name;
    if (!atts[i].normalized) {
      enum XML_Error result;
      int isCdata = 1;

      if (attId->maybeTokenized) {
	int j;
	for (j = 0; j < nDefaultAtts; j++) {
	  if (attId == elementType->defaultAtts[j].id) {
	    isCdata = elementType->defaultAtts[j].isCdata;
	    break;
	  }
	}
      }

      result = storeAttributeValue(parser, enc, isCdata,
				   atts[i].valuePtr, atts[i].valueEnd,
			           &tempPool);
      if (result)
	return result;
      if (tagNamePtr) {
	appAtts[attIndex] = poolStart(&tempPool);
	poolFinish(&tempPool);
      }
      else
	poolDiscard(&tempPool);
    }
    else if (tagNamePtr) {
      appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd);
      if (appAtts[attIndex] == 0)
	return XML_ERROR_NO_MEMORY;
      poolFinish(&tempPool);
    }
    if (attId->prefix && tagNamePtr) {
      if (attId->xmlns) {
        if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr))
          return XML_ERROR_NO_MEMORY;
        --attIndex;
      }
      else {
        attIndex++;
        nPrefixes++;
        (attId->name)[-1] = 2;
      }
    }
    else
      attIndex++;
  }
  if (tagNamePtr) {
    int j;
    for (j = 0; j < nDefaultAtts; j++) {
      const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j;
      if (!(da->id->name)[-1] && da->value) {
        if (da->id->prefix) {
          if (da->id->xmlns) {
	    if (!addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr))
	      return XML_ERROR_NO_MEMORY;
	  }
          else {
	    (da->id->name)[-1] = 2;
	    nPrefixes++;
  	    appAtts[attIndex++] = da->id->name;
	    appAtts[attIndex++] = da->value;
	  }
	}
	else {
	  (da->id->name)[-1] = 1;
	  appAtts[attIndex++] = da->id->name;
	  appAtts[attIndex++] = da->value;
	}
      }
    }
    appAtts[attIndex] = 0;
  }
  i = 0;
  if (nPrefixes) {
    for (; i < attIndex; i += 2) {
      if (appAtts[i][-1] == 2) {
        ATTRIBUTE_ID *id;
        ((XML_Char *)(appAtts[i]))[-1] = 0;
	id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0);
	if (id->prefix->binding) {
	  int j;
	  const BINDING *b = id->prefix->binding;
	  const XML_Char *s = appAtts[i];
	  for (j = 0; j < b->uriLen; j++) {
	    if (!poolAppendChar(&tempPool, b->uri[j]))
	      return XML_ERROR_NO_MEMORY;
	  }
	  while (*s++ != ':')
	    ;
	  do {
	    if (!poolAppendChar(&tempPool, *s))
	      return XML_ERROR_NO_MEMORY;
	  } while (*s++);
	  appAtts[i] = poolStart(&tempPool);
	  poolFinish(&tempPool);
	}
	if (!--nPrefixes)
	  break;
      }
      else
	((XML_Char *)(appAtts[i]))[-1] = 0;
    }
  }
  for (; i < attIndex; i += 2)
    ((XML_Char *)(appAtts[i]))[-1] = 0;
  if (!tagNamePtr)
    return XML_ERROR_NONE;
  for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
    binding->attId->name[-1] = 0;
  if (elementType->prefix) {
    binding = elementType->prefix->binding;
    if (!binding)
      return XML_ERROR_NONE;
    localPart = *tagNamePtr;
    while (*localPart++ != XML_T(':'))
      ;
  }
  else if (dtd.defaultPrefix.binding) {
    binding = dtd.defaultPrefix.binding;
    localPart = *tagNamePtr;
  }
  else
    return XML_ERROR_NONE;
  i = binding->uriLen;
  do {
    if (i == binding->uriAlloc) {
      binding->uri = realloc(binding->uri, binding->uriAlloc *= 2);
      if (!binding->uri)
	return XML_ERROR_NO_MEMORY;
    }
    binding->uri[i++] = *localPart;
  } while (*localPart++);
  *tagNamePtr = binding->uri;
  return XML_ERROR_NONE;
}

static
int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr)
{
  BINDING *b;
  int len;
  for (len = 0; uri[len]; len++)
    ;
  if (namespaceSeparator)
    len++;
  if (freeBindingList) {
    b = freeBindingList;
    if (len > b->uriAlloc) {
      b->uri = realloc(b->uri, len + EXPAND_SPARE);
      if (!b->uri)
	return 0;
      b->uriAlloc = len + EXPAND_SPARE;
    }
    freeBindingList = b->nextTagBinding;
  }
  else {
    b = malloc(sizeof(BINDING));
    if (!b)
      return 0;
    b->uri = malloc(sizeof(XML_Char) * len + EXPAND_SPARE);
    if (!b->uri) {
      free(b);
      return 0;
    }
    b->uriAlloc = len;
  }
  b->uriLen = len;
  memcpy(b->uri, uri, len * sizeof(XML_Char));
  if (namespaceSeparator)
    b->uri[len - 1] = namespaceSeparator;
  b->prefix = prefix;
  b->attId = attId;
  b->prevPrefixBinding = b->prefix->binding;
  b->prefix->binding = *uri == XML_T('\0') ? 0 : b;
  b->nextTagBinding = *bindingsPtr;
  *bindingsPtr = b;
  return 1;
}

/* The idea here is to avoid using stack for each CDATA section when
the whole file is parsed with one call. */

static
enum XML_Error cdataSectionProcessor(XML_Parser parser,
				     const char *start,
			    	     const char *end,
				     const char **endPtr)
{
  enum XML_Error result = doCdataSection(parser, encoding, &start, end, endPtr);
  if (start) {
    processor = contentProcessor;
    return contentProcessor(parser, start, end, endPtr);
  }
  return result;
}

/* startPtr gets set to non-null is the section is closed, and to null if
the section is not yet closed. */

static
enum XML_Error doCdataSection(XML_Parser parser,
			      const ENCODING *enc,
			      const char **startPtr,
			      const char *end,
			      const char **nextPtr)
{
  const char *s = *startPtr;
  const char **eventPP;
  const char **eventEndPP;
  if (enc == encoding) {
    eventPP = &eventPtr;
    *eventPP = s;
    eventEndPP = &eventEndPtr;
  }
  else {
    eventPP = &(openInternalEntities->internalEventPtr);
    eventEndPP = &(openInternalEntities->internalEventEndPtr);
  }
  *eventPP = s;
  *startPtr = 0;
  for (;;) {
    const char *next;
    int tok = XmlCdataSectionTok(enc, s, end, &next);
    *eventEndPP = next;
    switch (tok) {
    case XML_TOK_CDATA_SECT_CLOSE:
      if (characterDataHandler)
	characterDataHandler(handlerArg, dataBuf, 0);
      else if (defaultHandler)
	reportDefault(parser, enc, s, next);
      *startPtr = next;
      return XML_ERROR_NONE;
    case XML_TOK_DATA_NEWLINE:
      if (characterDataHandler) {
	XML_Char c = XML_T('\n');
	characterDataHandler(handlerArg, &c, 1);
      }
      else if (defaultHandler)
	reportDefault(parser, enc, s, next);
      break;
    case XML_TOK_DATA_CHARS:
      if (characterDataHandler) {
	if (MUST_CONVERT(enc, s)) {
	  for (;;) {
  	    ICHAR *dataPtr = (ICHAR *)dataBuf;
	    XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
	    *eventEndPP = next;
	    characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
	    if (s == next)
	      break;
	    *eventPP = s;
	  }
	}
	else
	  characterDataHandler(handlerArg,
		  	       (XML_Char *)s,
			       (XML_Char *)next - (XML_Char *)s);
      }
      else if (defaultHandler)
	reportDefault(parser, enc, s, next);
      break;
    case XML_TOK_INVALID:
      *eventPP = next;
      return XML_ERROR_INVALID_TOKEN;
    case XML_TOK_PARTIAL_CHAR:
      if (nextPtr) {
	*nextPtr = s;
	return XML_ERROR_NONE;
      }
      return XML_ERROR_PARTIAL_CHAR;
    case XML_TOK_PARTIAL:
    case XML_TOK_NONE:
      if (nextPtr) {
	*nextPtr = s;
	return XML_ERROR_NONE;
      }
      return XML_ERROR_UNCLOSED_CDATA_SECTION;
    default:
      abort();
    }
    *eventPP = s = next;
  }
  /* not reached */
}

static enum XML_Error
initializeEncoding(XML_Parser parser)
{
  const char *s;
#ifdef XML_UNICODE
  char encodingBuf[128];
  if (!protocolEncodingName)
    s = 0;
  else {
    int i;
    for (i = 0; protocolEncodingName[i]; i++) {
      if (i == sizeof(encodingBuf) - 1
	  || protocolEncodingName[i] >= 0x80
	  || protocolEncodingName[i] < 0) {
	encodingBuf[0] = '\0';
	break;
      }
      encodingBuf[i] = (char)protocolEncodingName[i];
    }
    encodingBuf[i] = '\0';
    s = encodingBuf;
  }
#else
  s = protocolEncodingName;
#endif
  if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
    return XML_ERROR_NONE;
  return handleUnknownEncoding(parser, protocolEncodingName);
}

static enum XML_Error
processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
	       const char *s, const char *next)
{
  const char *encodingName = 0;
  const ENCODING *newEncoding = 0;
  const char *version;
  int standalone = -1;
  if (!(ns
        ? XmlParseXmlDeclNS
	: XmlParseXmlDecl)(isGeneralTextEntity,
		           encoding,
		           s,
		           next,
		           &eventPtr,
		           &version,
		           &encodingName,
		           &newEncoding,
		           &standalone))
    return XML_ERROR_SYNTAX;
  if (defaultHandler)
    reportDefault(parser, encoding, s, next);
  if (!protocolEncodingName) {
    if (newEncoding) {
      if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
	eventPtr = encodingName;
	return XML_ERROR_INCORRECT_ENCODING;
      }
      encoding = newEncoding;
    }
    else if (encodingName) {
      enum XML_Error result;
      const XML_Char *s = poolStoreString(&tempPool,
					  encoding,
					  encodingName,
					  encodingName
					  + XmlNameLength(encoding, encodingName));
      if (!s)
	return XML_ERROR_NO_MEMORY;
      result = handleUnknownEncoding(parser, s);
      poolDiscard(&tempPool);
      if (result == XML_ERROR_UNKNOWN_ENCODING)
	eventPtr = encodingName;
      return result;
    }
  }
  if (!isGeneralTextEntity && standalone == 1)
    dtd.standalone = 1;
  return XML_ERROR_NONE;
}

static enum XML_Error
handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
{
  if (unknownEncodingHandler) {
    XML_Encoding info;
    int i;
    for (i = 0; i < 256; i++)
      info.map[i] = -1;
    info.convert = 0;
    info.data = 0;
    info.release = 0;
    if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, &info)) {
      ENCODING *enc;
      unknownEncodingMem = malloc(XmlSizeOfUnknownEncoding());
      if (!unknownEncodingMem) {
	if (info.release)
	  info.release(info.data);
	return XML_ERROR_NO_MEMORY;
      }
      enc = (ns
	     ? XmlInitUnknownEncodingNS
	     : XmlInitUnknownEncoding)(unknownEncodingMem,
				       info.map,
				       info.convert,
				       info.data);
      if (enc) {
	unknownEncodingData = info.data;
	unknownEncodingRelease = info.release;
	encoding = enc;
	return XML_ERROR_NONE;
      }
    }
    if (info.release)
      info.release(info.data);
  }
  return XML_ERROR_UNKNOWN_ENCODING;
}

static enum XML_Error
prologInitProcessor(XML_Parser parser,
		    const char *s,
		    const char *end,
		    const char **nextPtr)
{
  enum XML_Error result = initializeEncoding(parser);
  if (result != XML_ERROR_NONE)
    return result;
  processor = prologProcessor;
  return prologProcessor(parser, s, end, nextPtr);
}

static enum XML_Error
prologProcessor(XML_Parser parser,
		const char *s,
		const char *end,
		const char **nextPtr)
{
  for (;;) {
    const char *next;
    int tok = XmlPrologTok(encoding, s, end, &next);
    if (tok <= 0) {
      if (nextPtr != 0 && tok != XML_TOK_INVALID) {
	*nextPtr = s;
	return XML_ERROR_NONE;
      }
      switch (tok) {
      case XML_TOK_INVALID:
	eventPtr = next;
	return XML_ERROR_INVALID_TOKEN;
      case XML_TOK_NONE:
	return XML_ERROR_NO_ELEMENTS;
      case XML_TOK_PARTIAL:
	return XML_ERROR_UNCLOSED_TOKEN;
      case XML_TOK_PARTIAL_CHAR:
	return XML_ERROR_PARTIAL_CHAR;
      case XML_TOK_TRAILING_CR:
	eventPtr = s + encoding->minBytesPerChar;
	return XML_ERROR_NO_ELEMENTS;
      default:

⌨️ 快捷键说明

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