QList<ListDigraph::Node> ProcessModel::topolSortReachableFrom(const QList<ListDigraph::Node>& s) { ListDigraph::NodeMap<bool > nodevisited(graph, false); QList<ListDigraph::Node> res; QStack<ListDigraph::Node> stack; ListDigraph::Node curnode; ListDigraph::Node pnode; ListDigraph::Node snode; QList<ListDigraph::Node> reachable = reachableFrom(s); // Reserve memory res.reserve(countNodes(graph)); stack.reserve(countNodes(graph)); for (int i = 0; i < s.size(); i++) { if (s[i] != INVALID) { stack.push(s[i]); } } bool psched; while (!stack.empty()) { curnode = stack.pop(); if (!nodevisited[curnode]) { // This node has not been visited yet // Check whether all predecessors in reachable are scheduled psched = true; for (ListDigraph::InArcIt iait(graph, curnode); iait != INVALID; ++iait) { pnode = graph.source(iait); if (reachable.contains(pnode)) { // Consider only nodes which can be reached from s if (!nodevisited[pnode]) { psched = false; break; } } } if (psched) { // All predecessors have been visited res.append(curnode); nodevisited[curnode] = true; // Push the succeeding nodes for (ListDigraph::OutArcIt oait(graph, curnode); oait != INVALID; ++oait) { snode = graph.target(oait); if (!nodevisited[snode]) { stack.push(snode); } } } else { stack.prepend(curnode); } } // Else ignore the visited node } return res; }
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 == '\\') {
/*! \param points Series of data points \return Curve points */ QPolygonF QwtWeedingCurveFitter::fitCurve( const QPolygonF &points ) const { QStack<Line> stack; stack.reserve( 500 ); const QPointF *p = points.data(); const int nPoints = points.size(); QVector<bool> usePoint( nPoints, false ); double distToSegment; stack.push( Line( 0, nPoints - 1 ) ); while ( !stack.isEmpty() ) { const Line r = stack.pop(); // initialize line segment const double vecX = p[r.to].x() - p[r.from].x(); const double vecY = p[r.to].y() - p[r.from].y(); const double vecLength = qSqrt( vecX * vecX + vecY * vecY ); const double unitVecX = ( vecLength != 0.0 ) ? vecX / vecLength : 0.0; const double unitVecY = ( vecLength != 0.0 ) ? vecY / vecLength : 0.0; double maxDist = 0.0; int nVertexIndexMaxDistance = r.from + 1; for ( int i = r.from + 1; i < r.to; i++ ) { //compare to anchor const double fromVecX = p[i].x() - p[r.from].x(); const double fromVecY = p[i].y() - p[r.from].y(); const double fromVecLength = qSqrt( fromVecX * fromVecX + fromVecY * fromVecY ); if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 ) { distToSegment = fromVecLength; } if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 ) { distToSegment = fromVecLength; } else { const double toVecX = p[i].x() - p[r.to].x(); const double toVecY = p[i].y() - p[r.to].y(); const double toVecLength = qSqrt( toVecX * toVecX + toVecY * toVecY ); const double s = toVecX * ( -unitVecX ) + toVecY * ( -unitVecY ); if ( s < 0.0 ) distToSegment = toVecLength; else { distToSegment = qSqrt( qFabs( toVecLength * toVecLength - s * s ) ); } } if ( maxDist < distToSegment ) { maxDist = distToSegment; nVertexIndexMaxDistance = i; } } if ( maxDist <= d_data->tolerance ) { usePoint[r.from] = true; usePoint[r.to] = true; } else { stack.push( Line( r.from, nVertexIndexMaxDistance ) ); stack.push( Line( nVertexIndexMaxDistance, r.to ) ); } } int cnt = 0; QPolygonF stripped( nPoints ); for ( int i = 0; i < nPoints; i++ ) { if ( usePoint[i] ) stripped[cnt++] = p[i]; } stripped.resize( cnt ); return stripped; }