📄 htmltokenizer.cpp
字号:
skipLF = false;
}
if (skipLF)
{
skipLF = false;
++list;
}
else if (( *list == '\n' ) || ( *list == '\r' ))
{
if (discard == LFDiscard)
{
// Ignore this LF
discard = NoneDiscard; // We have discarded 1 LF
}
else
{
// Process this LF
if (pending)
addPending();
pending = LFPending;
}
/* Check for MS-DOS CRLF sequence */
if (*list == '\r')
{
skipLF = true;
}
++list;
}
else if (( *list == ' ' ) || ( *list == '\t'))
{
if (pending)
addPending();
if (*list == ' ')
pending = SpacePending;
else
pending = TabPending;
++list;
}
else
{
discard = NoneDiscard;
if (pending)
addPending();
prePos++;
*dest++ = *list;
++list;
}
}
if (pending)
addPending();
prePos = 0;
pre = old_pre;
}
void HTMLTokenizer::parseSpecial(TokenizerString &src)
{
assert( textarea || title || !Entity );
assert( !tag );
assert( xmp+textarea+title+style+script == 1 );
if (script)
scriptStartLineno = lineno+src.lineCount();
if ( comment ) parseComment( src );
while ( !src.isEmpty() ) {
RETURN_IF_OOM( checkScriptBuffer( ) );
unsigned char ch = src->latin1();
if ( !scriptCodeResync && !brokenComments && !textarea && !xmp && !title && ch == '-' && scriptCodeSize >= 3 && !src.escaped() && scriptCode[scriptCodeSize-3] == '<' && scriptCode[scriptCodeSize-2] == '!' && scriptCode[scriptCodeSize-1] == '-' ) {
comment = true;
parseComment( src );
continue;
}
if ( scriptCodeResync && !tquote && ( ch == '>' ) ) {
++src;
scriptCodeSize = scriptCodeResync-1;
scriptCodeResync = 0;
scriptCode[ scriptCodeSize ] = scriptCode[ scriptCodeSize + 1 ] = 0;
if ( script )
scriptHandler();
else {
processListing(TokenizerString(scriptCode, scriptCodeSize));
processToken();
if ( style ) { currToken.id = ID_STYLE + ID_CLOSE_TAG; }
else if ( textarea ) { currToken.id = ID_TEXTAREA + ID_CLOSE_TAG; }
else if ( title ) { currToken.id = ID_TITLE + ID_CLOSE_TAG; }
else if ( xmp ) { currToken.id = ID_XMP + ID_CLOSE_TAG; }
processToken();
style = script = style = textarea = title = xmp = false;
tquote = NoQuote;
scriptCodeSize = scriptCodeResync = 0;
}
return;
}
// possible end of tagname, lets check.
if ( !scriptCodeResync && !escaped && !src.escaped() && ( ch == '>' || ch == '/' || ch <= ' ' ) && ch &&
scriptCodeSize >= searchStopperLen &&
tagMatch( searchStopper, scriptCode+scriptCodeSize-searchStopperLen, searchStopperLen )) {
scriptCodeResync = scriptCodeSize-searchStopperLen+1;
tquote = NoQuote;
continue;
}
if ( scriptCodeResync && !escaped ) {
if(ch == '\"')
tquote = (tquote == NoQuote) ? DoubleQuote : ((tquote == SingleQuote) ? SingleQuote : NoQuote);
else if(ch == '\'')
tquote = (tquote == NoQuote) ? SingleQuote : (tquote == DoubleQuote) ? DoubleQuote : NoQuote;
else if (tquote != NoQuote && (ch == '\r' || ch == '\n'))
tquote = NoQuote;
}
escaped = ( !escaped && ch == '\\' );
if (!scriptCodeResync && (textarea||title) && !src.escaped() && ch == '&') {
QChar *scriptCodeDest = scriptCode+scriptCodeSize;
++src;
parseEntity(src,scriptCodeDest,true);
scriptCodeSize = scriptCodeDest-scriptCode;
}
else {
scriptCode[scriptCodeSize] = *src;
fixUpChar(scriptCode[scriptCodeSize]);
++scriptCodeSize;
++src;
}
}
}
void HTMLTokenizer::scriptHandler()
{
// We are inside a <script>
bool doScriptExec = false;
CachedScript* cs = 0;
// don't load external scripts for standalone documents (for now)
if (!scriptSrc.isEmpty() && parser->doc()->part()) {
// forget what we just got; load from src url instead
if ( !parser->skipMode() ) {
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
if (!parser->doc()->ownerElement())
printf("Requesting script at time %d\n", parser->doc()->elapsedTime());
#endif
if ( (cs = parser->doc()->docLoader()->requestScript(scriptSrc, scriptSrcCharset) )
#if NOKIA_CHANGES
&& !parser->doc()->fastDisplayMode()
#endif
)
cachedScript.enqueue(cs);
}
scriptSrc=QString::null;
}
else {
#ifdef TOKEN_DEBUG
kdDebug( 6036 ) << "---START SCRIPT---" << endl;
kdDebug( 6036 ) << QString(scriptCode, scriptCodeSize) << endl;
kdDebug( 6036 ) << "---END SCRIPT---" << endl;
#endif
// Parse scriptCode containing <script> info
#if NOKIA_CHANGES
if (!parser->doc()->fastDisplayMode())
#endif
doScriptExec = true;
}
processListing(TokenizerString(scriptCode, scriptCodeSize));
QString exScript( buffer, dest-buffer );
processToken();
currToken.id = ID_SCRIPT + ID_CLOSE_TAG;
processToken();
TokenizerString *savedPrependingSrc = currentPrependingSrc;
TokenizerString prependingSrc;
currentPrependingSrc = &prependingSrc;
if ( !parser->skipMode() ) {
if (cs) {
//kdDebug( 6036 ) << "cachedscript extern!" << endl;
//kdDebug( 6036 ) << "src: *" << QString( src.current(), src.length() ).latin1() << "*" << endl;
//kdDebug( 6036 ) << "pending: *" << pendingSrc.latin1() << "*" << endl;
#if NOKIA_CHANGES
if (!parser->doc()->fastDisplayMode()) {
#endif
if (savedPrependingSrc) {
savedPrependingSrc->append(src);
} else {
pendingSrc.prepend(src);
}
setSrc(TokenizerString());
scriptCodeSize = scriptCodeResync = 0;
cs->ref(this);
// will be 0 if script was already loaded and ref() executed it
if (!cachedScript.isEmpty())
loadingExtScript = true;
#if NOKIA_CHANGES
}
#endif
}
else if (view && doScriptExec && javascript ) {
if (!m_executingScript)
pendingSrc.prepend(src);
else
prependingSrc = src;
setSrc(TokenizerString());
scriptCodeSize = scriptCodeResync = 0;
//QTime dt;
//dt.start();
scriptExecution( exScript, QString::null, scriptStartLineno );
//kdDebug( 6036 ) << "script execution time:" << dt.elapsed() << endl;
}
}
script = false;
scriptCodeSize = scriptCodeResync = 0;
if ( !m_executingScript && !loadingExtScript ) {
// kdDebug( 6036 ) << "adding pending Output to parsed string" << endl;
src.append(pendingSrc);
pendingSrc.clear();
} else if (!prependingSrc.isEmpty()) {
// restore first so that the write appends in the right place
// (does not hurt to do it again below)
currentPrependingSrc = savedPrependingSrc;
// we need to do this slightly modified bit of one of the write() cases
// because we want to prepend to pendingSrc rather than appending
// if there's no previous prependingSrc
if (loadingExtScript) {
if (currentPrependingSrc) {
currentPrependingSrc->append(prependingSrc);
} else {
pendingSrc.prepend(prependingSrc);
}
} else {
write(prependingSrc, false);
}
}
currentPrependingSrc = savedPrependingSrc;
}
void HTMLTokenizer::scriptExecution( const QString& str, QString scriptURL,
int baseLine)
{
#if APPLE_CHANGES
if (!view || !view->part())
return;
#endif
bool oldscript = script;
m_executingScript++;
script = false;
QString url;
if (scriptURL.isNull())
url = static_cast<DocumentImpl*>(view->part()->document().handle())->URL();
else
url = scriptURL;
TokenizerString *savedPrependingSrc = currentPrependingSrc;
TokenizerString prependingSrc;
currentPrependingSrc = &prependingSrc;
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
if (!parser->doc()->ownerElement())
printf("beginning script execution at %d\n", parser->doc()->elapsedTime());
#endif
view->part()->executeScript(url,baseLine,Node(),str);
allowYield = true;
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
if (!parser->doc()->ownerElement())
printf("ending script execution at %d\n", parser->doc()->elapsedTime());
#endif
m_executingScript--;
script = oldscript;
if ( !m_executingScript && !loadingExtScript ) {
// kdDebug( 6036 ) << "adding pending Output to parsed string" << endl;
src.append(pendingSrc);
pendingSrc.clear();
} else if (!prependingSrc.isEmpty()) {
// restore first so that the write appends in the right place
// (does not hurt to do it again below)
currentPrependingSrc = savedPrependingSrc;
// we need to do this slightly modified bit of one of the write() cases
// because we want to prepend to pendingSrc rather than appending
// if there's no previous prependingSrc
if (loadingExtScript) {
if (currentPrependingSrc) {
currentPrependingSrc->append(prependingSrc);
} else {
pendingSrc.prepend(prependingSrc);
}
} else {
write(prependingSrc, false);
}
}
currentPrependingSrc = savedPrependingSrc;
}
void HTMLTokenizer::parseComment(TokenizerString &src)
{
RETURN_IF_OOM( checkScriptBuffer(src.length()) );
while ( !src.isEmpty() ) {
scriptCode[ scriptCodeSize++ ] = *src;
#if defined(TOKEN_DEBUG) && TOKEN_DEBUG > 1
qDebug("comment is now: *%s*",
QConstString((QChar*)src.current(), QMIN(16, src.length())).string().latin1());
#endif
if (src->unicode() == '>') {
bool handleBrokenComments = brokenComments && !(script || style);
int endCharsCount = 1; // start off with one for the '>' character
if (scriptCodeSize > 2 && scriptCode[scriptCodeSize-3] == '-' && scriptCode[scriptCodeSize-2] == '-') {
endCharsCount = 3;
}
else if (scriptCodeSize > 3 && scriptCode[scriptCodeSize-4] == '-' && scriptCode[scriptCodeSize-3] == '-' &&
scriptCode[scriptCodeSize-2] == '!') {
// Other browsers will accept --!> as a close comment, even though it's
// not technically valid.
endCharsCount = 4;
}
if (handleBrokenComments || endCharsCount > 1) {
++src;
if (!( script || xmp || textarea || style)) {
if (includesCommentsInDOM) {
RETURN_IF_OOM( checkScriptBuffer() );
scriptCode[ scriptCodeSize ] = 0;
scriptCode[ scriptCodeSize + 1 ] = 0;
currToken.id = ID_COMMENT;
processListing(TokenizerString(scriptCode, scriptCodeSize - endCharsCount));
processToken();
currToken.id = ID_COMMENT + ID_CLOSE_TAG;
processToken();
}
scriptCodeSize = 0;
}
comment = false;
return; // Finished parsing comment
}
}
++src;
}
}
void HTMLTokenizer::parseServer(TokenizerString &src)
{
RETURN_IF_OOM( checkScriptBuffer(src.length()) );
while ( !src.isEmpty() ) {
scriptCode[ scriptCodeSize++ ] = *src;
if (src->unicode() == '>' &&
scriptCodeSize > 1 && scriptCode[scriptCodeSize-2] == '%') {
++src;
server = false;
scriptCodeSize = 0;
return; // Finished parsing server include
}
++src;
}
}
void HTMLTokenizer::parseProcessingInstruction(TokenizerString &src)
{
char oldchar = 0;
while ( !src.isEmpty() )
{
unsigned char chbegin = src->latin1();
if(chbegin == '\'') {
tquote = tquote == SingleQuote ? NoQuote : SingleQuote;
}
else if(chbegin == '\"') {
tquote = tquote == DoubleQuote ? NoQuote : DoubleQuote;
}
// Look for '?>'
// some crappy sites omit the "?" before it, so
// we look for an unquoted '>' instead. (IE compatible)
else if ( chbegin == '>' && ( !tquote || oldchar == '?' ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -