Beispiel #1
0
NS_IMETHODIMP
nsHtml5Parser::ParseFragment(const nsAString& aSourceBuffer,
                             nsIContent* aTargetNode,
                             nsIAtom* aContextLocalName,
                             PRInt32 aContextNamespace,
                             PRBool aQuirks)
{
  nsIDocument* doc = aTargetNode->GetOwnerDoc();
  NS_ENSURE_TRUE(doc, NS_ERROR_NOT_AVAILABLE);
  
  nsIURI* uri = doc->GetDocumentURI();
  NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE);

  Initialize(doc, uri, nsnull, nsnull);

  mExecutor->SetParser(this);
  mExecutor->SetNodeInfoManager(doc->NodeInfoManager());

  nsIContent* target = aTargetNode;
  mTreeBuilder->setFragmentContext(aContextLocalName,
                                   aContextNamespace,
                                   &target,
                                   aQuirks);
  mExecutor->EnableFragmentMode();
  
  NS_PRECONDITION(!mExecutor->HasStarted(),
                  "Tried to start parse without initializing the parser.");
  mTreeBuilder->setScriptingEnabled(mExecutor->IsScriptEnabled());
  mTokenizer->start();
  mExecutor->Start(); // Don't call WillBuildModel in fragment case
  if (!aSourceBuffer.IsEmpty()) {
    PRBool lastWasCR = PR_FALSE;
    nsHtml5UTF16Buffer buffer(aSourceBuffer.Length());
    memcpy(buffer.getBuffer(),
           aSourceBuffer.BeginReading(),
           aSourceBuffer.Length() * sizeof(PRUnichar));
    buffer.setEnd(aSourceBuffer.Length());
    while (buffer.hasMore()) {
      buffer.adjust(lastWasCR);
      lastWasCR = PR_FALSE;
      if (buffer.hasMore()) {
        lastWasCR = mTokenizer->tokenizeBuffer(&buffer);
      }
    }
  }
  mTokenizer->eof();
  mTreeBuilder->StreamEnded();
  mTreeBuilder->Flush();
  mExecutor->FlushDocumentWrite();
  mTokenizer->end();
  mExecutor->DropParserAndPerfHint();
  mExecutor->DropHeldElements();
  mAtomTable.Clear();
  return NS_OK;
}
NS_IMETHODIMP
nsHtml5Parser::Parse(nsIURI* aURL,
                     nsIRequestObserver* aObserver,
                     void* aKey, // legacy; ignored
                     nsDTDMode aMode) // legacy; ignored
{
  /*
   * Do NOT cause WillBuildModel to be called synchronously from here!
   * The document won't be ready for it until OnStartRequest!
   */
  NS_PRECONDITION(!mExecutor->HasStarted(), 
                  "Tried to start parse without initializing the parser.");
  NS_PRECONDITION(mStreamParser, 
                  "Can't call this Parse() variant on script-created parser");
  mStreamParser->SetObserver(aObserver);
  mStreamParser->SetViewSourceTitle(aURL); // In case we're viewing source
  mExecutor->SetStreamParser(mStreamParser);
  mExecutor->SetParser(this);
  return NS_OK;
}
// class destructor
ClassBrowser::~ClassBrowser()
{
    int pos = XRCCTRL(*this, "splitterWin", wxSplitterWindow)->GetSashPosition();
    Manager::Get()->GetConfigManager(_T("code_completion"))->Write(_T("/splitter_pos"), pos);

    SetParser(NULL);

    if (m_ClassBrowserBuilderThread)
    {
        // tell the thread, that we want to terminate it, TestDestroy only works after Delete(), which should not
        // be used on joinable threads
        // if we disable the cc-plugin, we otherwise come to an infinite wait in the threads Entry()-function
        m_ClassBrowserBuilderThread->RequestTermination();
        // awake the thread
        m_ClassBrowserSemaphore.Post();
        // free the system-resources
        m_ClassBrowserBuilderThread->Wait();
        // according to the wxWidgets-documentation the wxThread object itself has to be deleted explicitely,
        // to free the memory, if it is created on the heap, this is not done by Wait()
        delete m_ClassBrowserBuilderThread;
    }
}
NS_IMETHODIMP
nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
                     void* aKey,
                     const nsACString& aContentType,
                     bool aLastCall,
                     nsDTDMode aMode) // ignored
{
  if (mExecutor->IsBroken()) {
    return NS_ERROR_OUT_OF_MEMORY;
  }
  if (aSourceBuffer.Length() > PR_INT32_MAX) {
    mExecutor->MarkAsBroken();
    return NS_ERROR_OUT_OF_MEMORY;
  }

  // Maintain a reference to ourselves so we don't go away
  // till we're completely done. The old parser grips itself in this method.
  nsCOMPtr<nsIParser> kungFuDeathGrip(this);
  
  // Gripping the other objects just in case, since the other old grip
  // required grips to these, too.
  nsRefPtr<nsHtml5StreamParser> streamKungFuDeathGrip(mStreamParser);
  nsRefPtr<nsHtml5TreeOpExecutor> treeOpKungFuDeathGrip(mExecutor);

  if (!mExecutor->HasStarted()) {
    NS_ASSERTION(!mStreamParser,
                 "Had stream parser but document.write started life cycle.");
    // This is the first document.write() on a document.open()ed document
    mExecutor->SetParser(this);
    mTreeBuilder->setScriptingEnabled(mExecutor->IsScriptEnabled());
    mTokenizer->start();
    mExecutor->Start();
    if (!aContentType.EqualsLiteral("text/html")) {
      mTreeBuilder->StartPlainText();
      mTokenizer->StartPlainText();
    }
    /*
     * If you move the following line, be very careful not to cause 
     * WillBuildModel to be called before the document has had its 
     * script global object set.
     */
    mExecutor->WillBuildModel(eDTDMode_unknown);
  }

  // Return early if the parser has processed EOF
  if (mExecutor->IsComplete()) {
    return NS_OK;
  }

  if (aLastCall && aSourceBuffer.IsEmpty() && !aKey) {
    // document.close()
    NS_ASSERTION(!mStreamParser,
                 "Had stream parser but got document.close().");
    if (mDocumentClosed) {
      // already closed
      return NS_OK;
    }
    mDocumentClosed = true;
    if (!mBlocked && !mInDocumentWrite) {
      ParseUntilBlocked();
    }
    return NS_OK;
  }

  // If we got this far, we are dealing with a document.write or
  // document.writeln call--not document.close().

  NS_ASSERTION(IsInsertionPointDefined(),
               "Doc.write reached parser with undefined insertion point.");

  NS_ASSERTION(!(mStreamParser && !aKey),
               "Got a null key in a non-script-created parser");

  // XXX is this optimization bogus?
  if (aSourceBuffer.IsEmpty()) {
    return NS_OK;
  }

  // This guard is here to prevent document.close from tokenizing synchronously
  // while a document.write (that wrote the script that called document.close!)
  // is still on the call stack.
  mozilla::AutoRestore<bool> guard(mInDocumentWrite);
  mInDocumentWrite = true;

  // The script is identified by aKey. If there's nothing in the buffer
  // chain for that key, we'll insert at the head of the queue.
  // When the script leaves something in the queue, a zero-length
  // key-holder "buffer" is inserted in the queue. If the same script
  // leaves something in the chain again, it will be inserted immediately
  // before the old key holder belonging to the same script.
  //
  // We don't do the actual data insertion yet in the hope that the data gets
  // tokenized and there no data or less data to copy to the heap after
  // tokenization. Also, this way, we avoid inserting one empty data buffer
  // per document.write, which matters for performance when the parser isn't
  // blocked and a badly-authored script calls document.write() once per
  // input character. (As seen in a benchmark!)
  //
  // The insertion into the input stream happens conceptually before anything
  // gets tokenized. To make sure multi-level document.write works right,
  // it's necessary to establish the location of our parser key up front
  // in case this is the first write with this key.
  //
  // In a document.open() case, the first write level has a null key, so that
  // case is handled separately, because normal buffers containing data
  // have null keys.

  // These don't need to be owning references, because they always point to
  // the buffer queue and buffers can't be removed from the buffer queue
  // before document.write() returns. The buffer queue clean-up happens the
  // next time ParseUntilBlocked() is called.
  // However, they are made owning just in case the reasoning above is flawed
  // and a flaw would lead to worse problems with plain pointers. If this
  // turns out to be a perf problem, it's worthwhile to consider making
  // prevSearchbuf a plain pointer again.
  nsRefPtr<nsHtml5OwningUTF16Buffer> prevSearchBuf;
  nsRefPtr<nsHtml5OwningUTF16Buffer> firstLevelMarker;

  if (aKey) {
    if (mFirstBuffer == mLastBuffer) {
      nsHtml5OwningUTF16Buffer* keyHolder = new nsHtml5OwningUTF16Buffer(aKey);
      keyHolder->next = mLastBuffer;
      mFirstBuffer = keyHolder;
    } else if (mFirstBuffer->key != aKey) {
      prevSearchBuf = mFirstBuffer;
      for (;;) {
        if (prevSearchBuf->next == mLastBuffer) {
          // key was not found
          nsHtml5OwningUTF16Buffer* keyHolder =
            new nsHtml5OwningUTF16Buffer(aKey);
          keyHolder->next = mFirstBuffer;
          mFirstBuffer = keyHolder;
          prevSearchBuf = nsnull;
          break;
        }
        if (prevSearchBuf->next->key == aKey) {
          // found a key holder
          break;
        }
        prevSearchBuf = prevSearchBuf->next;
      }
    } // else mFirstBuffer is the keyholder

    // prevSearchBuf is the previous buffer before the keyholder or null if
    // there isn't one.
  } else {
    // We have a first-level write in the document.open() case. We insert
    // before mLastBuffer. We need to put a marker there, because otherwise
    // additional document.writes from nested event loops would insert in the
    // wrong place. Sigh.
    firstLevelMarker = new nsHtml5OwningUTF16Buffer((void*)nsnull);
    if (mFirstBuffer == mLastBuffer) {
      firstLevelMarker->next = mLastBuffer;
      mFirstBuffer = firstLevelMarker;
    } else {
      prevSearchBuf = mFirstBuffer;
      while (prevSearchBuf->next != mLastBuffer) {
        prevSearchBuf = prevSearchBuf->next;
      }
      firstLevelMarker->next = mLastBuffer;
      prevSearchBuf->next = firstLevelMarker;
    }
  }

  nsHtml5DependentUTF16Buffer stackBuffer(aSourceBuffer);

  while (!mBlocked && stackBuffer.hasMore()) {
    stackBuffer.adjust(mLastWasCR);
    mLastWasCR = false;
    if (stackBuffer.hasMore()) {
      PRInt32 lineNumberSave;
      bool inRootContext = (!mStreamParser && !aKey);
      if (inRootContext) {
        mTokenizer->setLineNumber(mRootContextLineNumber);
      } else {
        // we aren't the root context, so save the line number on the
        // *stack* so that we can restore it.
        lineNumberSave = mTokenizer->getLineNumber();
      }

      mLastWasCR = mTokenizer->tokenizeBuffer(&stackBuffer);

      if (inRootContext) {
        mRootContextLineNumber = mTokenizer->getLineNumber();
      } else {
        mTokenizer->setLineNumber(lineNumberSave);
      }

      if (mTreeBuilder->HasScript()) {
        mTreeBuilder->Flush(); // Move ops to the executor
        mExecutor->FlushDocumentWrite(); // run the ops
        // Flushing tree ops can cause all sorts of things.
        // Return early if the parser got terminated.
        if (mExecutor->IsComplete()) {
          return NS_OK;
        }
      }
      // Ignore suspension requests
    }
  }

  nsRefPtr<nsHtml5OwningUTF16Buffer> heapBuffer;
  if (stackBuffer.hasMore()) {
    // The buffer wasn't tokenized to completion. Create a copy of the tail
    // on the heap.
    heapBuffer = stackBuffer.FalliblyCopyAsOwningBuffer();
    if (!heapBuffer) {
      // Allocation failed. The parser is now broken.
      mExecutor->MarkAsBroken();
      return NS_ERROR_OUT_OF_MEMORY;
    }
  }

  if (heapBuffer) {
    // We have something to insert before the keyholder holding in the non-null
    // aKey case and we have something to swap into firstLevelMarker in the
    // null aKey case.
    if (aKey) {
      NS_ASSERTION(mFirstBuffer != mLastBuffer,
        "Where's the keyholder?");
      // the key holder is still somewhere further down the list from
      // prevSearchBuf (which may be null)
      if (mFirstBuffer->key == aKey) {
        NS_ASSERTION(!prevSearchBuf,
          "Non-null prevSearchBuf when mFirstBuffer is the key holder?");
        heapBuffer->next = mFirstBuffer;
        mFirstBuffer = heapBuffer;
      } else {
        if (!prevSearchBuf) {
          prevSearchBuf = mFirstBuffer;
        }
        // We created a key holder earlier, so we will find it without walking
        // past the end of the list.
        while (prevSearchBuf->next->key != aKey) {
          prevSearchBuf = prevSearchBuf->next;
        }
        heapBuffer->next = prevSearchBuf->next;
        prevSearchBuf->next = heapBuffer;
      }
    } else {
      NS_ASSERTION(firstLevelMarker, "How come we don't have a marker.");
      firstLevelMarker->Swap(heapBuffer);
    }
  }

  if (!mBlocked) { // buffer was tokenized to completion
    NS_ASSERTION(!stackBuffer.hasMore(),
      "Buffer wasn't tokenized to completion?");
    // Scripting semantics require a forced tree builder flush here
    mTreeBuilder->Flush(); // Move ops to the executor
    mExecutor->FlushDocumentWrite(); // run the ops
  } else if (stackBuffer.hasMore()) {
    // The buffer wasn't tokenized to completion. Tokenize the untokenized
    // content in order to preload stuff. This content will be retokenized
    // later for normal parsing.
    if (!mDocWriteSpeculatorActive) {
      mDocWriteSpeculatorActive = true;
      if (!mDocWriteSpeculativeTreeBuilder) {
        // Lazily initialize if uninitialized
        mDocWriteSpeculativeTreeBuilder =
            new nsHtml5TreeBuilder(nsnull, mExecutor->GetStage());
        mDocWriteSpeculativeTreeBuilder->setScriptingEnabled(
            mTreeBuilder->isScriptingEnabled());
        mDocWriteSpeculativeTokenizer =
            new nsHtml5Tokenizer(mDocWriteSpeculativeTreeBuilder, false);
        mDocWriteSpeculativeTokenizer->setInterner(&mAtomTable);
        mDocWriteSpeculativeTokenizer->start();
      }
      mDocWriteSpeculativeTokenizer->resetToDataState();
      mDocWriteSpeculativeTreeBuilder->loadState(mTreeBuilder, &mAtomTable);
      mDocWriteSpeculativeLastWasCR = false;
    }

    // Note that with multilevel document.write if we didn't just activate the
    // speculator, it's possible that the speculator is now in the wrong state.
    // That's OK for the sake of simplicity. The worst that can happen is
    // that the speculative loads aren't exactly right. The content will be
    // reparsed anyway for non-preload purposes.

    // The buffer position for subsequent non-speculative parsing now lives
    // in heapBuffer, so it's ok to let the buffer position of stackBuffer
    // to be overwritten and not restored below.
    while (stackBuffer.hasMore()) {
      stackBuffer.adjust(mDocWriteSpeculativeLastWasCR);
      if (stackBuffer.hasMore()) {
        mDocWriteSpeculativeLastWasCR =
            mDocWriteSpeculativeTokenizer->tokenizeBuffer(&stackBuffer);
      }
    }

    mDocWriteSpeculativeTreeBuilder->Flush();
    mDocWriteSpeculativeTreeBuilder->DropHandles();
    mExecutor->FlushSpeculativeLoads();
  }

  return NS_OK;
}
Beispiel #5
0
ret_ CXMLLoaderActions::Load(XercesDOMParser *pParser,
							 const ch_1 *pszEnvironmentPath)
{
#ifdef _DEBUG_
	if (!pParser)
		return PARAMETER_NULL | PARAMETER_1;

	if (!pszEnvironmentPath)
		return PARAMETER_NULL | PARAMETER_2;

	if (null_v == pszEnvironmentPath[0])
		return PARAMETER_EMPTY | PARAMETER_2;
#endif

	SetParser(pParser);

	ch_1 sActions[ENVIRONMENT_PATH_LENGTH];

	memset(sActions, 0, ENVIRONMENT_PATH_LENGTH);
	sprintf(sActions, "%s%s", pszEnvironmentPath, ACTIONS_XML_FILE);

	DOMDocument *pActionsDoc = null_v;

	try
	{
		GetParser()->parse(sActions);
        pActionsDoc = GetParser()->getDocument();
	}
    catch (const OutOfMemoryException &err)
    {
		auto_xerces_str sErr(err.getMessage());

		printf("%s\n", (const ch_1 *)sErr);

 		return XML_LOADER_ERROR;
    }
	catch (const XMLException &err)
    {
		auto_xerces_str sErr(err.getMessage());

		printf("%s\n", (const ch_1 *)sErr);

 		return XML_LOADER_ERROR;
	}
    catch (const DOMException &err)
    {
		auto_xerces_str sErr(err.msg);

		printf("%s\n", (const ch_1 *)sErr);

 		return XML_LOADER_ERROR;
	}
	catch (...)
    {
		printf("Unexpected error during parsing.\n");

		return XML_LOADER_ERROR;
    }

	if (!pActionsDoc)
		return XML_LOADER_ERROR;
	
	DOMElement *pRoot = pActionsDoc->getDocumentElement();

	if (!pRoot)
		return XML_LOADER_ERROR;

	DOMElement *pChild = (DOMElement *)pRoot->getFirstChild();

	if (!pChild)
		return XML_LOADER_ERROR;

	auto_xerces_str wsDataBlock("data_block");
	auto_xerces_str wsStart("start");
	auto_xerces_str wsProcessor("processor");
	auto_xerces_str wsEnd("end");

	while (pChild)
	{
		if (0 == XMLString::compareString(pChild->getNodeName(),
										  wsDataBlock))
		{
			if (SUCCESS != LoadDataBlock(CUIManager::Instance()->Data(),
										 pChild))
			{
				return XML_LOADER_ERROR;
			}
		}
		else if (0 == XMLString::compareString(pChild->getNodeName(),
											   wsStart))
		{
			if (SUCCESS != LoadProgram(&CUIManager::Instance()->Data(),
									   CUIManager::Instance()->StartProgram(),
									   pChild))
			{
				return XML_LOADER_ERROR;
			}
		}
		else if (0 == XMLString::compareString(pChild->getNodeName(),
											   wsProcessor))
		{
			if (SUCCESS != LoadProcessor(pChild))
				return XML_LOADER_ERROR;

			m_pTmpContainer = null_v;
		}
		else if (0 == XMLString::compareString(pChild->getNodeName(),
											   wsEnd))
		{
			if (SUCCESS != LoadProgram(&CUIManager::Instance()->Data(),
									   CUIManager::Instance()->EndProgram(),
									   pChild))
			{
				return XML_LOADER_ERROR;
			}
		}

		pChild = (DOMElement *)pChild->getNextSibling();
	}

	return SUCCESS;
}
Beispiel #6
0
nsresult
nsHtml5Parser::ParseHtml5Fragment(const nsAString& aSourceBuffer,
                                  nsIContent* aTargetNode,
                                  nsIAtom* aContextLocalName,
                                  PRInt32 aContextNamespace,
                                  bool aQuirks,
                                  bool aPreventScriptExecution)
{
  NS_ENSURE_TRUE(aSourceBuffer.Length() <= PR_INT32_MAX,
      NS_ERROR_OUT_OF_MEMORY);
  nsIDocument* doc = aTargetNode->OwnerDoc();
  
  nsIURI* uri = doc->GetDocumentURI();
  NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE);

  mExecutor->EnableFragmentMode(aPreventScriptExecution);

  Initialize(doc, uri, nsnull, nsnull);

  mExecutor->SetParser(this);
  mExecutor->SetNodeInfoManager(doc->NodeInfoManager());

  nsIContent* target = aTargetNode;
  mTreeBuilder->setFragmentContext(aContextLocalName,
                                   aContextNamespace,
                                   &target,
                                   aQuirks);

#ifdef DEBUG
  if (!aPreventScriptExecution) {
    NS_ASSERTION(!aTargetNode->IsInDoc(),
        "If script execution isn't prevented, "
        "the target node must not be in doc.");
    nsCOMPtr<nsIDOMDocumentFragment> domFrag = do_QueryInterface(aTargetNode);
    NS_ASSERTION(domFrag,
        "If script execution isn't prevented, must parse to DOM fragment.");
  }
#endif

  NS_PRECONDITION(!mExecutor->HasStarted(),
                  "Tried to start parse without initializing the parser.");
  mTreeBuilder->setScriptingEnabled(mExecutor->IsScriptEnabled());
  mTokenizer->start();
  mExecutor->Start(); // Don't call WillBuildModel in fragment case
  if (!aSourceBuffer.IsEmpty()) {
    bool lastWasCR = false;
    nsHtml5DependentUTF16Buffer buffer(aSourceBuffer);    
    while (buffer.hasMore()) {
      buffer.adjust(lastWasCR);
      lastWasCR = false;
      if (buffer.hasMore()) {
        lastWasCR = mTokenizer->tokenizeBuffer(&buffer);
        if (mTreeBuilder->HasScript()) {
          // Flush on each script, because the execution prevention code
          // can handle at most one script per flush.
          mTreeBuilder->Flush(); // Move ops to the executor
          mExecutor->FlushDocumentWrite(); // run the ops
        }
      }
    }
  }
  mTokenizer->eof();
  mTreeBuilder->StreamEnded();
  mTreeBuilder->Flush();
  mExecutor->FlushDocumentWrite();
  mTokenizer->end();
  mExecutor->DropParserAndPerfHint();
  mExecutor->DropHeldElements();
  mTreeBuilder->DropHandles();
  mAtomTable.Clear();
  return NS_OK;
}
Beispiel #7
0
NS_IMETHODIMP
nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
                     void* aKey,
                     const nsACString& aContentType, // ignored
                     bool aLastCall,
                     nsDTDMode aMode) // ignored
{
  NS_PRECONDITION(!mExecutor->IsFragmentMode(),
                  "Document.write called in fragment mode!");
  if (mExecutor->IsBroken()) {
    return NS_ERROR_OUT_OF_MEMORY;
  }
  if (aSourceBuffer.Length() > PR_INT32_MAX) {
    mExecutor->MarkAsBroken();
    return NS_ERROR_OUT_OF_MEMORY;
  }

  // Maintain a reference to ourselves so we don't go away
  // till we're completely done. The old parser grips itself in this method.
  nsCOMPtr<nsIParser> kungFuDeathGrip(this);
  
  // Gripping the other objects just in case, since the other old grip
  // required grips to these, too.
  nsRefPtr<nsHtml5StreamParser> streamKungFuDeathGrip(mStreamParser);
  nsRefPtr<nsHtml5TreeOpExecutor> treeOpKungFuDeathGrip(mExecutor);

  if (!mExecutor->HasStarted()) {
    NS_ASSERTION(!mStreamParser,
                 "Had stream parser but document.write started life cycle.");
    // This is the first document.write() on a document.open()ed document
    mExecutor->SetParser(this);
    mTreeBuilder->setScriptingEnabled(mExecutor->IsScriptEnabled());
    mTokenizer->start();
    mExecutor->Start();
    /*
     * If you move the following line, be very careful not to cause 
     * WillBuildModel to be called before the document has had its 
     * script global object set.
     */
    mExecutor->WillBuildModel(eDTDMode_unknown);
  }

  // Return early if the parser has processed EOF
  if (mExecutor->IsComplete()) {
    return NS_OK;
  }

  if (aLastCall && aSourceBuffer.IsEmpty() && aKey == GetRootContextKey()) {
    // document.close()
    NS_ASSERTION(!mStreamParser,
                 "Had stream parser but got document.close().");
    mDocumentClosed = true;
    if (!mBlocked) {
      ParseUntilBlocked();
    }
    return NS_OK;
  }

  NS_ASSERTION(IsInsertionPointDefined(),
               "Doc.write reached parser with undefined insertion point.");

  NS_ASSERTION(!(mStreamParser && !aKey),
               "Got a null key in a non-script-created parser");

  if (aSourceBuffer.IsEmpty()) {
    return NS_OK;
  }

  nsHtml5DependentUTF16Buffer stackBuffer(aSourceBuffer);

  while (!mBlocked && stackBuffer.hasMore()) {
    stackBuffer.adjust(mLastWasCR);
    mLastWasCR = false;
    if (stackBuffer.hasMore()) {
      PRInt32 lineNumberSave;
      bool inRootContext = (!mStreamParser && (aKey == mRootContextKey));
      if (inRootContext) {
        mTokenizer->setLineNumber(mRootContextLineNumber);
      } else {
        // we aren't the root context, so save the line number on the
        // *stack* so that we can restore it.
        lineNumberSave = mTokenizer->getLineNumber();
      }

      mLastWasCR = mTokenizer->tokenizeBuffer(&stackBuffer);

      if (inRootContext) {
        mRootContextLineNumber = mTokenizer->getLineNumber();
      } else {
        mTokenizer->setLineNumber(lineNumberSave);
      }

      if (mTreeBuilder->HasScript()) {
        mTreeBuilder->Flush(); // Move ops to the executor
        mExecutor->FlushDocumentWrite(); // run the ops
      }
      // Ignore suspension requests
    }
  }

  nsRefPtr<nsHtml5OwningUTF16Buffer> heapBuffer;
  if (stackBuffer.hasMore()) {
    // The buffer wasn't tokenized to completion. Create a copy of the tail
    // on the heap.
    heapBuffer = stackBuffer.FalliblyCopyAsOwningBuffer();
    if (!heapBuffer) {
      // Allocation failed. The parser is now broken.
      mExecutor->MarkAsBroken();
      return NS_ERROR_OUT_OF_MEMORY;
    }
  }

  // The buffer is inserted to the stream here in case it won't be parsed
  // to completion.
  // The script is identified by aKey. If there's nothing in the buffer
  // chain for that key, we'll insert at the head of the queue.
  // When the script leaves something in the queue, a zero-length
  // key-holder "buffer" is inserted in the queue. If the same script
  // leaves something in the chain again, it will be inserted immediately
  // before the old key holder belonging to the same script.
  nsHtml5OwningUTF16Buffer* prevSearchBuf = nsnull;
  nsHtml5OwningUTF16Buffer* searchBuf = mFirstBuffer;

  // after document.open, the first level of document.write has null key
  if (aKey) {
    while (searchBuf != mLastBuffer) {
      if (searchBuf->key == aKey) {
        // found a key holder
        // now insert the new buffer between the previous buffer
        // and the key holder if we have a buffer left.
        if (heapBuffer) {
          heapBuffer->next = searchBuf;
          if (prevSearchBuf) {
            prevSearchBuf->next = heapBuffer;
          } else {
            mFirstBuffer = heapBuffer;
          }
        }
        break;
      }
      prevSearchBuf = searchBuf;
      searchBuf = searchBuf->next;
    }
    if (searchBuf == mLastBuffer) {
      // key was not found
      nsHtml5OwningUTF16Buffer* keyHolder = new nsHtml5OwningUTF16Buffer(aKey);
      keyHolder->next = mFirstBuffer;
      if (heapBuffer) {
        heapBuffer->next = keyHolder;
        mFirstBuffer = heapBuffer;
      } else {
        mFirstBuffer = keyHolder;
      }
    }
  } else if (heapBuffer) {
    // we have a first level document.write after document.open()
    // insert immediately before mLastBuffer
    while (searchBuf != mLastBuffer) {
      prevSearchBuf = searchBuf;
      searchBuf = searchBuf->next;
    }
    heapBuffer->next = mLastBuffer;
    if (prevSearchBuf) {
      prevSearchBuf->next = heapBuffer;
    } else {
      mFirstBuffer = heapBuffer;
    }
  }

  if (!mBlocked) { // buffer was tokenized to completion
    NS_ASSERTION(!stackBuffer.hasMore(),
      "Buffer wasn't tokenized to completion?");
    // Scripting semantics require a forced tree builder flush here
    mTreeBuilder->Flush(); // Move ops to the executor
    mExecutor->FlushDocumentWrite(); // run the ops
  } else if (stackBuffer.hasMore()) {
    // The buffer wasn't tokenized to completion. Tokenize the untokenized
    // content in order to preload stuff. This content will be retokenized
    // later for normal parsing.
    if (!mDocWriteSpeculatorActive) {
      mDocWriteSpeculatorActive = true;
      if (!mDocWriteSpeculativeTreeBuilder) {
        // Lazily initialize if uninitialized
        mDocWriteSpeculativeTreeBuilder =
            new nsHtml5TreeBuilder(nsnull, mExecutor->GetStage());
        mDocWriteSpeculativeTreeBuilder->setScriptingEnabled(
            mTreeBuilder->isScriptingEnabled());
        mDocWriteSpeculativeTokenizer =
            new nsHtml5Tokenizer(mDocWriteSpeculativeTreeBuilder);
        mDocWriteSpeculativeTokenizer->setInterner(&mAtomTable);
        mDocWriteSpeculativeTokenizer->start();
      }
      mDocWriteSpeculativeTokenizer->resetToDataState();
      mDocWriteSpeculativeTreeBuilder->loadState(mTreeBuilder, &mAtomTable);
      mDocWriteSpeculativeLastWasCR = false;
    }

    // Note that with multilevel document.write if we didn't just activate the
    // speculator, it's possible that the speculator is now in the wrong state.
    // That's OK for the sake of simplicity. The worst that can happen is
    // that the speculative loads aren't exactly right. The content will be
    // reparsed anyway for non-preload purposes.

    // The buffer position for subsequent non-speculative parsing now lives
    // in heapBuffer, so it's ok to let the buffer position of stackBuffer
    // to be overwritten and not restored below.
    while (stackBuffer.hasMore()) {
      stackBuffer.adjust(mDocWriteSpeculativeLastWasCR);
      if (stackBuffer.hasMore()) {
        mDocWriteSpeculativeLastWasCR =
            mDocWriteSpeculativeTokenizer->tokenizeBuffer(&stackBuffer);
      }
    }

    mDocWriteSpeculativeTreeBuilder->Flush();
    mDocWriteSpeculativeTreeBuilder->DropHandles();
    mExecutor->FlushSpeculativeLoads();
  }

  return NS_OK;
}
Beispiel #8
0
ret_ CXMLLoaderNetwork::Load(XercesDOMParser *pParser,
							 const ch_1 *pszEnvironmentPath)
{
	_START(LOAD);

#ifdef _DEBUG_
	if (!pParser)
		_RET(PARAMETER_NULL | PARAMETER_1);

	if (!pszEnvironmentPath)
		_RET(PARAMETER_NULL | PARAMETER_2);

	if (null_v == pszEnvironmentPath[0])
		_RET(PARAMETER_EMPTY | PARAMETER_2);
#endif

	SetParser(pParser);

	ch_1 sNetwork[ENVIRONMENT_PATH_LENGTH];

	memset(sNetwork, 0, ENVIRONMENT_PATH_LENGTH);
	strncpy(sNetwork, pszEnvironmentPath, ENVIRONMENT_PATH_LENGTH);
	strncat(sNetwork, NETWORK_XML_FILE, ENVIRONMENT_PATH_LENGTH);

	DOMDocument *pNetworkDoc = null_v;

	try
	{
		GetParser()->parse(sNetwork);
        pNetworkDoc = GetParser()->getDocument();
	}
    catch (const OutOfMemoryException &err)
    {
		auto_xerces_str sErr(err.getMessage());

		printf("%s\n", (const ch_1 *)sErr);

 		_RET(XML_LOADER_ERROR);
    }
	catch (const XMLException &err)
    {
		auto_xerces_str sErr(err.getMessage());

		printf("%s\n", (const ch_1 *)sErr);

 		_RET(XML_LOADER_ERROR);
	}
    catch (const DOMException &err)
    {
        auto_xerces_str sErr(err.getMessage());

		printf("%s\n", (const ch_1 *)sErr);

 		_RET(XML_LOADER_ERROR);
	}
	catch (...)
    {
		printf("Unexpected error during parsing.\n");

		_RET(XML_LOADER_ERROR);
    }

	DOMElement *pRoot = pNetworkDoc->getDocumentElement();

	if (!pRoot)
		_RET(XML_LOADER_ERROR);

	DOMElement *pChild = (DOMElement *)pRoot->getFirstChild();

	if (!pChild)
		_RET(XML_LOADER_ERROR);

	auto_xerces_str wsIdentity		("identity");
	auto_xerces_str wsPDU			("pdu");
	auto_xerces_str wsDirection		("direction");
	auto_xerces_str	wsName			("name");
	auto_xerces_str	wsProtocolName	("protocol");
	auto_xerces_str wsCommandID		("command_id");
	auto_xerces_str wsSizeID		("size_id");
	auto_xerces_str	wsLocalPort		("local_port");
	auto_xerces_str wsAuto			("auto");

	auto_xerces_str wsFilter		("filter");
	auto_xerces_str wsMaxConnections("max_connections");
	auto_xerces_str wsRemoteIP		("remote_ip");
	auto_xerces_str	wsRemotePort	("remote_port");
	auto_xerces_str wsReconnect		("reconnect");

	auto_xerces_str wsAcceptorName	("acceptor");
	auto_xerces_str	wsConnectorName	("connector");
 	auto_xerces_str wsReceiverName	("receiver");
	auto_xerces_str wsSenderName	("sender");

	auto_xerces_str wsType			("type");


	while (pChild)
    {
		ENetworkType NetworkType = NETWORK_NONE;
		CProtocolInfo *pProtocol = null_v;
		CField *pCommandIDField	= null_v;
		CField *pSizeIDField = null_v;
		bool_ bIsAutoStart = true_v;

		if (0 == XMLString::compareString(pChild->getNodeName(),
										  wsAcceptorName))
		{
			NetworkType = NETWORK_ACCEPTOR;
		}
		else if (0 == XMLString::compareString(pChild->getNodeName(),
											   wsConnectorName))
		{
			NetworkType = NETWORK_CONNECTOR;
		}
		else if (0 == XMLString::compareString(pChild->getNodeName(),
											   wsReceiverName))
		{
			NetworkType = NETWORK_RECEIVER;
		}
		else if (0 == XMLString::compareString(pChild->getNodeName(),
											   wsSenderName))
		{
			NetworkType = NETWORK_SENDER;
		}
		else
		{
			pChild = (DOMElement *)pChild->getNextSibling();

			continue;
		}

		auto_xerces_str sProtocolName(pChild->getAttribute(wsProtocolName));

		if (SUCCESS != _ERR(
				CXMLLoaderProtocol::Instance()->Load(pParser,
													 pszEnvironmentPath,
													 sProtocolName)))
		{
			_RET(XML_LOADER_ERROR);
		}

		//
		if (SUCCESS != _ERR(
                CProtocolManager::instance()->getProtocol(sProtocolName,
                        pProtocol)))
		{
			_RET(XML_LOADER_ERROR);
		}

		//
		auto_xerces_str sCommandID(pChild->getAttribute(wsCommandID));

        if (SUCCESS != _ERR(pProtocol->getHeadField(sCommandID,
                pCommandIDField))
			|| FIELD_NORMAL_STYLE !=
                (pCommandIDField->type() & FIELD_NORMAL_STYLE)
                || 4 < _LEN(pCommandIDField->type()))
		{
			_RET(XML_LOADER_ERROR);
		}

		//
		auto_xerces_str sSizeID(pChild->getAttribute(wsSizeID));

        if (SUCCESS != _ERR(pProtocol->getHeadField(sSizeID,
                pSizeIDField))
			|| FIELD_NORMAL_STYLE !=
                (pSizeIDField->type() & FIELD_NORMAL_STYLE)
                || 4 < _LEN(pSizeIDField->type()))
		{
			_RET(XML_LOADER_ERROR);
		}

		//
		auto_xerces_str wsAutoFalse("false");

		if (0 == XMLString::compareString(wsAutoFalse,
										  pChild->getAttribute(wsAuto)))
		{
			bIsAutoStart = false_v;
		}

        CNode *pNetwork = null_v;
		auto_xerces_str sName(pChild->getAttribute(wsName));

		switch (NetworkType)
		{
		case NETWORK_NONE:
			_RET(XML_LOADER_ERROR);
		case NETWORK_ACCEPTOR:
			{
				auto_xerces_str	sLocalPort(pChild->getAttribute(wsLocalPort));
				auto_xerces_str
					sMaxConnections(pChild->getAttribute(wsMaxConnections));

				pNetwork = new CAcceptor(pProtocol,
										 pCommandIDField,
										 pSizeIDField,
										 (ub_2)atoi(sLocalPort),
										 (size_)atoi(sMaxConnections),
										 bIsAutoStart);
			}

			break;
		case NETWORK_CONNECTOR:
			{
				//
				auto_xerces_str	nLocalPort	(pChild->getAttribute(wsLocalPort));
				auto_xerces_str	sRemoteIP	(pChild->getAttribute(wsRemoteIP));
				auto_xerces_str	nRemotePort
					(pChild->getAttribute(wsRemotePort));
				auto_xerces_str	sReconnect	(pChild->getAttribute(wsReconnect));

				pNetwork = new CConnector(pProtocol,
										  pCommandIDField,
										  pSizeIDField,
										  (ub_2)atoi(nLocalPort),
										  (const ch_1 *)sRemoteIP,
										  (ub_2)atoi(nRemotePort),
										  (b_4)atoi(sReconnect),
										  bIsAutoStart);
			}

			break;
		case NETWORK_RECEIVER:
			{
				//
				auto_xerces_str sLocalPort(pChild->getAttribute(wsLocalPort));


				pNetwork = new CReceiver(pProtocol,
										 pCommandIDField,
										 pSizeIDField,
										 (ub_2)atoi(sLocalPort),
										 bIsAutoStart);
			}

			break;
		case NETWORK_SENDER:
			{
				//
				auto_xerces_str sLocalPort(pChild->getAttribute(wsLocalPort));

				pNetwork = new CSender(pProtocol,
									   pCommandIDField,
									   pSizeIDField,
									   (ub_2)atoi(sLocalPort),
									   bIsAutoStart);
			}
		}

        CNodeConf *pNetworkConf = (CNodeConf *) pNetwork->getConf();

		//
		DOMElement *pSub = (DOMElement *)pChild->getFirstChild();

		if (!pSub)
			_RET(XML_LOADER_ERROR);

		while (pSub)
		{
			if (0 == XMLString::compareString(pSub->getNodeName(),
											  wsIdentity))
			{
				//
				auto_xerces_str sIdentity(pSub->getAttribute(wsIdentity));
				ch_1 			*sIdentityName = null_v;

				if (SUCCESS != _ERR(GetLastName(sIdentity, sIdentityName)))
					_RET(XML_LOADER_ERROR);

                v_ *pV = pProtocol->data().value(sIdentityName);

				if (!pV)
					_RET(XML_LOADER_ERROR);

				//
				auto_xerces_str	sPDU(pSub->getAttribute(wsPDU));
                CPduInfo *pPDU = null_v;

                if (SUCCESS != _ERR(pProtocol->getPdu(sPDU, pPDU)))
					_RET(XML_LOADER_ERROR);

				//
				auto_xerces_str sDirection(pSub->getAttribute(wsDirection));
				EDirection		Direction;

				if (SUCCESS != _ERR(GetDirection(sDirection, Direction)))
					_RET(XML_LOADER_ERROR);

				//
				if (SUCCESS != _ERR(pNetworkConf->ConfigPDU(*pV,
															pPDU,
															Direction)))
				{
					_RET(XML_LOADER_ERROR);
				}
			}
			else if (0 == XMLString::compareString(pSub->getNodeName(),
												   wsFilter))
			{
				CIPFilter *pIPFilter = null_v;

				if (NETWORK_ACCEPTOR == NetworkType)
				{
					pIPFilter =
						&((CAcceptorConf *)pNetworkConf)->IPFilter();
				}
				else if (NETWORK_RECEIVER == NetworkType)
				{
					pIPFilter =
						&((CReceiverConf *)pNetworkConf)->IPFilter();
				}
				else
				{
					_RET(XML_LOADER_ERROR);
				}

				auto_xerces_str sType(pSub->getAttribute(wsType));

				if (0 == strcmp(sType, "forbid")) {
                    pIPFilter->setForbid(true_v);
                } else if (0 == strcmp(sType, "permit")) {
                    pIPFilter->setForbid(false_v);
                }

                auto_xerces_str sIPGroup(pSub->getTextContent());

                if (false_v == pIPFilter->addIpGroup((const ch_1 *) sIPGroup))
					_RET(XML_LOADER_ERROR);
			}

			pSub = (DOMElement *)pSub->getNextSibling();
		}

        if (SUCCESS != _ERR(CNetworkManager::instance()->AddNetwork(
														(const char *)sName,
														NetworkType,
														pNetwork)))
		{
			_RET(XML_LOADER_ERROR);
		}

		pChild = (DOMElement *)pChild->getNextSibling();
	}

	_RET(SUCCESS);
}
Beispiel #9
0
NS_IMETHODIMP
nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
                     void* aKey,
                     const nsACString& aContentType, // ignored
                     PRBool aLastCall,
                     nsDTDMode aMode) // ignored
{
  NS_PRECONDITION(!mExecutor->IsFragmentMode(),
                  "Document.write called in fragment mode!");

  // Maintain a reference to ourselves so we don't go away
  // till we're completely done. The old parser grips itself in this method.
  nsCOMPtr<nsIParser> kungFuDeathGrip(this);
  
  // Gripping the other objects just in case, since the other old grip
  // required grips to these, too.
  nsRefPtr<nsHtml5StreamParser> streamKungFuDeathGrip(mStreamParser);
  nsRefPtr<nsHtml5TreeOpExecutor> treeOpKungFuDeathGrip(mExecutor);

  if (!mExecutor->HasStarted()) {
    NS_ASSERTION(!mStreamParser,
                 "Had stream parser but document.write started life cycle.");
    // This is the first document.write() on a document.open()ed document
    mExecutor->SetParser(this);
    mTreeBuilder->setScriptingEnabled(mExecutor->IsScriptEnabled());
    mTokenizer->start();
    mExecutor->Start();
    /*
     * If you move the following line, be very careful not to cause 
     * WillBuildModel to be called before the document has had its 
     * script global object set.
     */
    mExecutor->WillBuildModel(eDTDMode_unknown);
  }

  // Return early if the parser has processed EOF
  if (mExecutor->IsComplete()) {
    return NS_OK;
  }

  if (aLastCall && aSourceBuffer.IsEmpty() && aKey == GetRootContextKey()) {
    // document.close()
    NS_ASSERTION(!mStreamParser,
                 "Had stream parser but got document.close().");
    mDocumentClosed = PR_TRUE;
    if (!mBlocked) {
      ParseUntilBlocked();
    }
    return NS_OK;
  }

  NS_ASSERTION(IsInsertionPointDefined(),
               "Doc.write reached parser with undefined insertion point.");

  NS_ASSERTION(!(mStreamParser && !aKey),
               "Got a null key in a non-script-created parser");

  if (aSourceBuffer.IsEmpty()) {
    return NS_OK;
  }

  nsRefPtr<nsHtml5UTF16Buffer> buffer =
    new nsHtml5UTF16Buffer(aSourceBuffer.Length());
  memcpy(buffer->getBuffer(),
         aSourceBuffer.BeginReading(),
         aSourceBuffer.Length() * sizeof(PRUnichar));
  buffer->setEnd(aSourceBuffer.Length());

  // The buffer is inserted to the stream here in case it won't be parsed
  // to completion.
  // The script is identified by aKey. If there's nothing in the buffer
  // chain for that key, we'll insert at the head of the queue.
  // When the script leaves something in the queue, a zero-length
  // key-holder "buffer" is inserted in the queue. If the same script
  // leaves something in the chain again, it will be inserted immediately
  // before the old key holder belonging to the same script.
  nsHtml5UTF16Buffer* prevSearchBuf = nsnull;
  nsHtml5UTF16Buffer* searchBuf = mFirstBuffer;

  // after document.open, the first level of document.write has null key
  if (aKey) {
    while (searchBuf != mLastBuffer) {
      if (searchBuf->key == aKey) {
        // found a key holder
        // now insert the new buffer between the previous buffer
        // and the key holder.
        buffer->next = searchBuf;
        if (prevSearchBuf) {
          prevSearchBuf->next = buffer;
        } else {
          mFirstBuffer = buffer;
        }
        break;
      }
      prevSearchBuf = searchBuf;
      searchBuf = searchBuf->next;
    }
    if (searchBuf == mLastBuffer) {
      // key was not found
      nsHtml5UTF16Buffer* keyHolder = new nsHtml5UTF16Buffer(aKey);
      keyHolder->next = mFirstBuffer;
      buffer->next = keyHolder;
      mFirstBuffer = buffer;
    }
  } else {
    // we have a first level document.write after document.open()
    // insert immediately before mLastBuffer
    while (searchBuf != mLastBuffer) {
      prevSearchBuf = searchBuf;
      searchBuf = searchBuf->next;
    }
    buffer->next = mLastBuffer;
    if (prevSearchBuf) {
      prevSearchBuf->next = buffer;
    } else {
      mFirstBuffer = buffer;
    }
  }

  while (!mBlocked && buffer->hasMore()) {
    buffer->adjust(mLastWasCR);
    mLastWasCR = PR_FALSE;
    if (buffer->hasMore()) {
      PRInt32 lineNumberSave;
      PRBool inRootContext = (!mStreamParser && (aKey == mRootContextKey));
      if (inRootContext) {
        mTokenizer->setLineNumber(mRootContextLineNumber);
      } else {
        // we aren't the root context, so save the line number on the
        // *stack* so that we can restore it.
        lineNumberSave = mTokenizer->getLineNumber();
      }

      mLastWasCR = mTokenizer->tokenizeBuffer(buffer);

      if (inRootContext) {
        mRootContextLineNumber = mTokenizer->getLineNumber();
      } else {
        mTokenizer->setLineNumber(lineNumberSave);
      }

      if (mTreeBuilder->HasScript()) {
        mTreeBuilder->Flush(); // Move ops to the executor
        mExecutor->FlushDocumentWrite(); // run the ops
      }
      // Ignore suspension requests
    }
  }

  if (!mBlocked) { // buffer was tokenized to completion
    NS_ASSERTION(!buffer->hasMore(), "Buffer wasn't tokenized to completion?");  
    // Scripting semantics require a forced tree builder flush here
    mTreeBuilder->Flush(); // Move ops to the executor
    mExecutor->FlushDocumentWrite(); // run the ops    
  }

  return NS_OK;
}