void PlotZoomer::loadSettings(QSettings &settings) { settings.beginGroup("zoom"); int zoomMode = settings.value("mode", int(PlotZoomer::ZoomBoth)).toInt(); setZoomMode(PlotZoomer::ZoomMode(zoomMode)); int zoomIndex = settings.value("index", -1).toInt(); int stackSize = settings.beginReadArray("stack"); QStack<QRectF> stack; stack.resize(stackSize); for (int i = 0; i < stackSize; ++i) { settings.setArrayIndex(i); read(settings, stack[i]); } settings.endArray(); setZoomStack(stack, zoomIndex); if (stackSize <= 1) { zoomToFit(true); } settings.endGroup(); }
bool QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar grammar) { m_proFile = pro; m_lineNo = line; // Final precompiled token stream buffer QString tokBuff; // Worst-case size calculations: // - line marker adds 1 (2-nl) to 1st token of each line // - empty assignment "A=":2 => // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokAssign(1) + 0(1) + // TokValueTerminator(1) == 8 (9) // - non-empty assignment "A=B C":5 => // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokAssign(1) + 2(1) + // TokLiteral(1) + len(1) + "B"(1) + // TokLiteral(1) + len(1) + "C"(1) + TokValueTerminator(1) == 14 (15) // - variable expansion: "$$f":3 => // TokVariable(1) + hash(2) + len(1) + "f"(1) = 5 // - function expansion: "$$f()":5 => // TokFuncName(1) + hash(2) + len(1) + "f"(1) + TokFuncTerminator(1) = 6 // - scope: "X:":2 => // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokCondition(1) + // TokBranch(1) + len(2) + ... + len(2) + ... == 10 // - test: "X():":4 => // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokTestCall(1) + TokFuncTerminator(1) + // TokBranch(1) + len(2) + ... + len(2) + ... == 11 // - "for(A,B):":9 => // TokForLoop(1) + hash(2) + len(1) + "A"(1) + // len(2) + TokLiteral(1) + len(1) + "B"(1) + TokValueTerminator(1) + // len(2) + ... + TokTerminator(1) == 14 (15) tokBuff.reserve((in.size() + 1) * 5); ushort *tokPtr = (ushort *)tokBuff.constData(); // Current writing position // Expression precompiler buffer. QString xprBuff; xprBuff.reserve(tokBuff.capacity()); // Excessive, but simple ushort *buf = (ushort *)xprBuff.constData(); // Parser state m_blockstack.clear(); m_blockstack.resize(1); QStack<ParseCtx> xprStack; xprStack.reserve(10); // We rely on QStrings being null-terminated, so don't maintain a global end pointer. const ushort *cur = (const ushort *)in.unicode(); m_canElse = false; freshLine: m_state = StNew; m_invert = false; m_operator = NoOperator; m_markLine = m_lineNo; m_inError = false; int parens = 0; // Braces in value context int argc = 0; int wordCount = 0; // Number of words in currently accumulated expression int lastIndent = 0; // Previous line's indentation, to detect accidental continuation abuse bool lineMarked = true; // For in-expression markers ushort needSep = TokNewStr; // Met unquoted whitespace ushort quote = 0; ushort term = 0; Context context; ushort *ptr; if (grammar == ValueGrammar) { context = CtxPureValue; ptr = tokPtr + 2; } else { context = CtxTest; ptr = buf + 4; } ushort *xprPtr = ptr; #define FLUSH_LHS_LITERAL() \ do { \ if ((tlen = ptr - xprPtr)) { \ finalizeHashStr(xprPtr, tlen); \ if (needSep) { \ wordCount++; \ needSep = 0; \ } \ } else { \ ptr -= 4; \ } \ } while (0) #define FLUSH_RHS_LITERAL() \ do { \ if ((tlen = ptr - xprPtr)) { \ xprPtr[-2] = TokLiteral | needSep; \ xprPtr[-1] = tlen; \ if (needSep) { \ wordCount++; \ needSep = 0; \ } \ } else { \ ptr -= 2; \ } \ } while (0) #define FLUSH_LITERAL() \ do { \ if (context == CtxTest) \ FLUSH_LHS_LITERAL(); \ else \ FLUSH_RHS_LITERAL(); \ } while (0) #define FLUSH_VALUE_LIST() \ do { \ if (wordCount > 1) { \ xprPtr = tokPtr; \ if (*xprPtr == TokLine) \ xprPtr += 2; \ tokPtr[-1] = ((*xprPtr & TokMask) == TokLiteral) ? wordCount : 0; \ } else { \ tokPtr[-1] = 0; \ } \ tokPtr = ptr; \ putTok(tokPtr, TokValueTerminator); \ } while (0) const ushort *end; // End of this line const ushort *cptr; // Start of next line bool lineCont; int indent; if (context == CtxPureValue) { end = (const ushort *)in.unicode() + in.length(); cptr = 0; lineCont = false; indent = 0; // just gcc being stupid goto nextChr; } forever { ushort c; // First, skip leading whitespace for (indent = 0; ; ++cur, ++indent) { c = *cur; if (c == '\n') { ++cur; goto flushLine; } else if (!c) { cur = 0; goto flushLine; } else if (c != ' ' && c != '\t' && c != '\r') { break; } } // Then strip comments. Yep - no escaping is possible. for (cptr = cur;; ++cptr) { c = *cptr; if (c == '#') { for (end = cptr; (c = *++cptr);) { if (c == '\n') { ++cptr; break; } } if (end == cur) { // Line with only a comment (sans whitespace) if (m_markLine == m_lineNo) m_markLine++; // Qmake bizarreness: such lines do not affect line continuations goto ignore; } break; } if (!c) { end = cptr; break; } if (c == '\n') { end = cptr++; break; } } // Then look for line continuations. Yep - no escaping here as well. forever { // We don't have to check for underrun here, as we already determined // that the line is non-empty. ushort ec = *(end - 1); if (ec == '\\') { --end; lineCont = true; break; } if (ec != ' ' && ec != '\t' && ec != '\r') { lineCont = false; break; } --end; } // Finally, do the tokenization ushort tok, rtok; int tlen; newWord: do { if (cur == end) goto lineEnd; c = *cur++; } while (c == ' ' || c == '\t'); forever { if (c == '$') { if (*cur == '$') { // may be EOF, EOL, WS, '#' or '\\' if past end cur++; FLUSH_LITERAL(); if (!lineMarked) { lineMarked = true; *ptr++ = TokLine; *ptr++ = (ushort)m_lineNo; } term = 0; tok = TokVariable; c = *cur; if (c == '[') { ptr += 4; tok = TokProperty; term = ']'; c = *++cur; } else if (c == '{') { ptr += 4; term = '}'; c = *++cur; } else if (c == '(') { ptr += 2; tok = TokEnvVar; term = ')'; c = *++cur; } else { ptr += 4; } xprPtr = ptr; rtok = tok; while ((c & 0xFF00) || c == '.' || c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '/' && term)) { *ptr++ = c; if (++cur == end) { c = 0; goto notfunc; } c = *cur; } if (tok == TokVariable && c == '(') tok = TokFuncName; notfunc: if (ptr == xprPtr) languageWarning(fL1S("Missing name in expansion")); if (quote) tok |= TokQuoted; if (needSep) { tok |= needSep; wordCount++; } tlen = ptr - xprPtr; if (rtok != TokVariable || !resolveVariable(xprPtr, tlen, needSep, &ptr, &buf, &xprBuff, &tokPtr, &tokBuff, cur, in)) { if (rtok == TokVariable || rtok == TokProperty) { xprPtr[-4] = tok; uint hash = ProString::hash((const QChar *)xprPtr, tlen); xprPtr[-3] = (ushort)hash; xprPtr[-2] = (ushort)(hash >> 16); xprPtr[-1] = tlen; } else { xprPtr[-2] = tok; xprPtr[-1] = tlen; } } if ((tok & TokMask) == TokFuncName) { cur++; funcCall: { xprStack.resize(xprStack.size() + 1); ParseCtx &top = xprStack.top(); top.parens = parens; top.quote = quote; top.terminator = term; top.context = context; top.argc = argc; top.wordCount = wordCount; } parens = 0; quote = 0; term = 0; argc = 1; context = CtxArgs; nextToken: wordCount = 0; nextWord: ptr += (context == CtxTest) ? 4 : 2; xprPtr = ptr; needSep = TokNewStr; goto newWord; } if (term) { checkTerm: if (c != term) { parseError(fL1S("Missing %1 terminator [found %2]") .arg(QChar(term)) .arg(c ? QString(c) : QString::fromLatin1("end-of-line"))); pro->setOk(false); m_inError = true; // Just parse on, as if there was a terminator ... } else { cur++; } } joinToken: ptr += (context == CtxTest) ? 4 : 2; xprPtr = ptr; needSep = 0; goto nextChr; } } else if (c == '\\') {