static void parse_string_arg(ExpressionPtr exp, string &var, string &lit) { if (exp->is(Expression::KindOfUnaryOpExpression)) { UnaryOpExpressionPtr u(static_pointer_cast<UnaryOpExpression>(exp)); if (u->getOp() == '(') { parse_string_arg(u->getExpression(), var, lit); return; } } else if (exp->is(Expression::KindOfBinaryOpExpression)) { BinaryOpExpressionPtr b(static_pointer_cast<BinaryOpExpression>(exp)); if (b->getOp() == '.') { string v, l; parse_string_arg(b->getExp2(), v, l); if (v.empty()) { parse_string_arg(b->getExp1(), var, lit); lit += l; return; } } } if (exp->isLiteralString()) { var = ""; lit = exp->getLiteralString(); return; } var = exp->getText(); lit = ""; return; }
string DependencyGraph::parseInclude(const string &source, ExpressionPtr parentExp, bool documentRoot /* = false */) { string included = parentExp->getText(); string parent = getIncludeFilePath(source, included, documentRoot); return Util::canonicalize(parent); }
void FunctionScope::setParamCounts(AnalysisResultPtr ar, int minParam, int maxParam) { m_minParam = minParam; m_maxParam = maxParam; ASSERT(m_minParam >= 0 && m_maxParam >= m_minParam); if (m_maxParam > 0) { m_paramNames.resize(m_maxParam); m_paramTypes.resize(m_maxParam); m_paramTypeSpecs.resize(m_maxParam); m_paramDefaults.resize(m_maxParam); m_paramDefaultTexts.resize(m_maxParam); m_refs.resize(m_maxParam); if (m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); ExpressionListPtr params = stmt->getParams(); for (int i = 0; i < m_maxParam; i++) { if (stmt->isRef(i)) m_refs[i] = true; ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); m_paramNames[i] = param->getName(); m_paramTypeSpecs[i] = param->getTypeSpec(ar); ExpressionPtr exp = param->defaultValue(); if (exp) { m_paramDefaults[i] = exp->getText(false, false, ar); } } } } }
bool Option::GetArrayElements(ExpressionPtr value, ExpressionListPtr &out) { UnaryOpExpressionPtr v = dynamic_pointer_cast<UnaryOpExpression>(value); if (!v || v->getOp() != T_ARRAY) { Logger::Error("Line %d: invalid array: %s", value->getLocation()->line1, value->getText().c_str()); return false; } ExpressionPtr exp = v->getExpression(); out = dynamic_pointer_cast<ExpressionList>(exp); if (!out) { Logger::Error("Line %d: invalid array: %s", value->getLocation()->line1, value->getText().c_str()); return false; } return true; }
bool Option::Load(string &option, ExpressionPtr value) { ScalarExpressionPtr v = dynamic_pointer_cast<ScalarExpression>(value); if (!v || !v->isLiteralString()) { Logger::Error("Line %d: invalid string: %s", value->getLocation()->line1, value->getText().c_str()); return false; } option = v->getLiteralString(); return true; }
bool Option::Load(bool &option, ExpressionPtr value) { ConstantExpressionPtr v = dynamic_pointer_cast<ConstantExpression>(value); if (!v || !v->isBoolean()) { Logger::Error("Line %d: invalid boolean: %s", value->getLocation()->line1, value->getText().c_str()); return false; } option = v->getBooleanValue(); return true; }
bool Option::Load(map<string, int> &option, ExpressionPtr value) { ExpressionListPtr elements; if (!GetArrayElements(value, elements)) return false; for (int i = 0; i < elements->getCount(); i++) { ExpressionPtr e = (*elements)[i]; ArrayPairExpressionPtr pair = dynamic_pointer_cast<ArrayPairExpression>(e); bool negative = false; ScalarExpressionPtr n, v; if (pair) n = dynamic_pointer_cast<ScalarExpression>(pair->getName()); if (pair) { if (pair->getValue()->is(Expression::KindOfUnaryOpExpression)) { UnaryOpExpressionPtr una = dynamic_pointer_cast<UnaryOpExpression>(pair->getValue()); if (una->getOp() != '+' && una->getOp() != '-') { Logger::Error("Line %d: invalid integer: %s", una->getLocation()->line1, una->getText().c_str()); return false; } v = dynamic_pointer_cast<ScalarExpression>(una->getExpression()); if (una->getOp() == '-') { negative = true; } } else { v = dynamic_pointer_cast<ScalarExpression>(pair->getValue()); } } if (!pair || !n || !v || !n->isLiteralString() || !v->isLiteralInteger()) { Logger::Error("Line %d: invalid element: %s", e->getLocation()->line1, e->getText().c_str()); return false; } if (negative) { option[n->getLiteralString()] = - v->getLiteralInteger(); } else { option[n->getLiteralString()] = v->getLiteralInteger(); } } return true; }
static inline std::string ExtractInitializer(AnalysisResultPtr ar, ExpressionPtr e) { switch (e->getKindOf()) { case Expression::KindOfParameterExpression: { auto p = static_pointer_cast<ParameterExpression>(e); if (!p->defaultValue()) return ""; return p->defaultValue()->getText(ar); } default: // TODO(stephentu): this doesn't allow us to tell the difference between // something like: // class X { public $x; } versus // class X { public $x = null; } // we'll just end up treating both cases like the latter return e->getText(ar); } return ""; }
bool DependencyGraph::checkInclude(ConstructPtr childExp, ExpressionPtr parentExp, CodeErrorPtr codeError, bool documentRoot, string &child, string &parent) { child = childExp->getLocation()->file; parent = parseInclude(child, parentExp, documentRoot); if ((parent.empty() || parent == child) && Option::AllowedBadPHPIncludes.find(parentExp->getText()) == Option::AllowedBadPHPIncludes.end()) { if (codeError) { codeError->record(CodeError::BadPHPIncludeFile, childExp); } return false; } if (parent.empty()) return false; return true; }
void FunctionScope::setParamSpecs(AnalysisResultPtr ar) { if (m_maxParam > 0 && m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); ExpressionListPtr params = stmt->getParams(); for (int i = 0; i < m_maxParam; i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); TypePtr specType = param->getTypeSpec(ar, false); if (specType && !specType->is(Type::KindOfSome) && !specType->is(Type::KindOfVariant)) { m_paramTypeSpecs[i] = specType; } ExpressionPtr exp = param->defaultValue(); if (exp) { m_paramDefaults[i] = exp->getText(false, false, ar); } } } }
bool Option::Load(vector<string> &option, ExpressionPtr value) { ExpressionListPtr elements; if (!GetArrayElements(value, elements)) return false; for (int i = 0; i < elements->getCount(); i++) { ExpressionPtr e = (*elements)[i]; ArrayPairExpressionPtr pair = dynamic_pointer_cast<ArrayPairExpression>(e); ScalarExpressionPtr v; if (pair) v = dynamic_pointer_cast<ScalarExpression>(pair->getValue()); if (!pair || !v || !v->isLiteralString()) { Logger::Error("Line %d: invalid element: %s", e->getLocation()->line1, e->getText().c_str()); return false; } option.push_back(v->getLiteralString()); } return true; }
static bool isEquivRedecl(const std::string &name, ExpressionPtr exp, ModifierExpressionPtr modif, Symbol * symbol) { assert(exp); assert(modif); assert(symbol); if (symbol->getName() != name || symbol->isProtected() != modif->isProtected() || symbol->isPrivate() != modif->isPrivate() || symbol->isPublic() != modif->isPublic() || symbol->isStatic() != modif->isStatic()) return false; auto symDeclExp = dynamic_pointer_cast<Expression>(symbol->getDeclaration()); if (!exp) return !symDeclExp; Variant v1, v2; auto s1 = exp->getScalarValue(v1); auto s2 = symDeclExp->getScalarValue(v2); if (s1 != s2) return false; if (s1) return same(v1, v2); return exp->getText() == symDeclExp->getText(); }
bool StatementList::mergeConcatAssign() { if (Option::LocalCopyProp) { return false; } else { // check for vector string concat assignment such as // $space = " "; // $a .= "hello"; // $a .= $space; // $a .= "world!"; // turn into (for constant folding and concat sequence) // $a .= " " . "hello " . $space . "world!"; unsigned int i = 0; bool merged = false; do { std::string lhsName; int length = 0; for (; i < m_stmts.size(); i++) { StatementPtr stmt = m_stmts[i]; if (!stmt->is(Statement::KindOfExpStatement)) break; ExpStatementPtr expStmt = dynamic_pointer_cast<ExpStatement>(stmt); ExpressionPtr exp = expStmt->getExpression(); // check the first assignment if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment_exp = dynamic_pointer_cast<AssignmentExpression>(exp); ExpressionPtr variable = assignment_exp->getVariable(); ExpressionPtr value = assignment_exp->getValue(); std::string variableName = variable->getText(); if (variableName.find("->") != std::string::npos) break; if (value->hasEffect()) break; // cannot turn $a .= $b; a .= $a into $a .= $b . $a; if (value->getText().find(variableName) != std::string::npos) break; if (lhsName.empty()) { lhsName = variable->getText(); length++; continue; } else { break; } } else if (!exp->is(Expression::KindOfBinaryOpExpression)) { break; } BinaryOpExpressionPtr binaryOpExp = dynamic_pointer_cast<BinaryOpExpression>(exp); if (binaryOpExp->getOp() != T_CONCAT_EQUAL) break; ExpressionPtr exp1 = binaryOpExp->getExp1(); std::string exp1Text = exp1->getText(); if (exp1Text.find("->") != std::string::npos) break; ExpressionPtr exp2 = binaryOpExp->getExp2(); if (exp2->hasEffect()) break; if (exp2->getText().find(exp1Text) != std::string::npos) break; if (lhsName.empty()) { lhsName = exp1Text; length++; } else if (lhsName == exp1Text) { length++; } else { break; } } if (length > 1) { // replace m_stmts[j] to m_stmts[i - 1] with a new statement unsigned j = i - length; ExpStatementPtr expStmt; ExpressionPtr exp; BinaryOpExpressionPtr binaryOpExp; ExpressionPtr var; ExpressionPtr exp1; ExpressionPtr exp2; bool isAssignment = false; expStmt = dynamic_pointer_cast<ExpStatement>(m_stmts[j++]); exp = expStmt->getExpression(); if (exp->is(Expression::KindOfAssignmentExpression)) { isAssignment = true; AssignmentExpressionPtr assignment_exp = dynamic_pointer_cast<AssignmentExpression>(exp); var = assignment_exp->getVariable(); exp1 = assignment_exp->getValue(); } else { binaryOpExp = dynamic_pointer_cast<BinaryOpExpression>(exp); var = binaryOpExp->getExp1(); exp1 = binaryOpExp->getExp2(); } for (; j < i; j++) { expStmt = dynamic_pointer_cast<ExpStatement>(m_stmts[j]); exp = expStmt->getExpression(); binaryOpExp = dynamic_pointer_cast<BinaryOpExpression>(exp); exp2 = binaryOpExp->getExp2(); exp1 = BinaryOpExpressionPtr (new BinaryOpExpression(getScope(), getLocation(), Expression::KindOfBinaryOpExpression, exp1, exp2, '.')); } if (isAssignment) { exp = AssignmentExpressionPtr (new AssignmentExpression(exp->getScope(), exp->getLocation(), Expression::KindOfAssignmentExpression, var, exp1, false)); } else { exp = BinaryOpExpressionPtr (new BinaryOpExpression(getScope(), getLocation(), Expression::KindOfBinaryOpExpression, var, exp1, T_CONCAT_EQUAL)); } expStmt = ExpStatementPtr (new ExpStatement(getScope(), getLocation(), Statement::KindOfExpStatement, exp)); m_stmts[i - length] = expStmt; for (j = i - (length - 1); i > j; i--) removeElement(j); merged = true; } else if (length == 0) { i++; } } while (i < m_stmts.size()); return merged; } }
void FunctionScope::outputCPPClassMap(CodeGenerator &cg, AnalysisResultPtr ar) { int attribute = ClassInfo::IsNothing; if (!isUserFunction()) attribute |= ClassInfo::IsSystem; if (isRedeclaring()) attribute |= ClassInfo::IsRedeclared; if (isVolatile()) attribute |= ClassInfo::IsVolatile; if (isRefReturn()) attribute |= ClassInfo::IsReference; if (isProtected()) { attribute |= ClassInfo::IsProtected; } else if (isPrivate()) { attribute |= ClassInfo::IsPrivate; } else { attribute |= ClassInfo::IsPublic; } if (isAbstract()) attribute |= ClassInfo::IsAbstract; if (isStatic()) { attribute |= ClassInfo::IsStatic; } if (isFinal()) attribute |= ClassInfo::IsFinal; if (isVariableArgument()) { attribute |= ClassInfo::VariableArguments; } if (isReferenceVariableArgument()) { attribute |= ClassInfo::RefVariableArguments; } if (isMixedVariableArgument()) { attribute |= ClassInfo::MixedVariableArguments; } attribute |= m_attributeClassInfo; if (!m_docComment.empty() && Option::GenerateDocComments) { attribute |= ClassInfo::HasDocComment; } else { attribute &= ~ClassInfo::HasDocComment; } // Use the original cased name, for reflection to work correctly. cg_printf("(const char *)0x%04X, \"%s\", \"%s\", (const char *)%d, " "(const char *)%d, NULL, NULL,\n", attribute, getOriginalName().c_str(), m_stmt ? m_stmt->getLocation()->file : "", m_stmt ? m_stmt->getLocation()->line0 : 0, m_stmt ? m_stmt->getLocation()->line1 : 0); if (!m_docComment.empty() && Option::GenerateDocComments) { char *dc = string_cplus_escape(m_docComment.c_str(), m_docComment.size()); cg_printf("\"%s\",\n", dc); free(dc); } Variant defArg; for (int i = 0; i < m_maxParam; i++) { int attr = ClassInfo::IsNothing; if (i >= m_minParam) attr |= ClassInfo::IsOptional; if (isRefParam(i)) attr |= ClassInfo::IsReference; const std::string &tname = m_paramTypeSpecs[i] ? m_paramTypeSpecs[i]->getPHPName() : ""; cg_printf("(const char *)0x%04X, \"%s\", \"%s\", ", attr, m_paramNames[i].c_str(), Util::toLower(tname).c_str()); if (i >= m_minParam) { MethodStatementPtr m = dynamic_pointer_cast<MethodStatement>(getStmt()); if (m) { ExpressionListPtr params = m->getParams(); assert(i < params->getCount()); ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); assert(param); ExpressionPtr def = param->defaultValue(); string sdef = def->getText(); char *esdef = string_cplus_escape(sdef.data(), sdef.size()); if (!def->isScalar() || !def->getScalarValue(defArg)) { /** * Special value runtime/ext/ext_reflection.cpp can check and throw. * If we want to avoid seeing this so to make getDefaultValue() * work better for reflections, we will have to implement * getScalarValue() to greater extent under compiler/expressions. */ cg_printf("\"\x01\", \"%s\",\n", esdef); } else { String str = f_serialize(defArg); char *s = string_cplus_escape(str.data(), str.size()); cg_printf("\"%s\", \"%s\",\n", s, esdef); free(s); } free(esdef); } else { char *def = string_cplus_escape(m_paramDefaults[i].data(), m_paramDefaults[i].size()); char *defText = string_cplus_escape(m_paramDefaultTexts[i].data(), m_paramDefaultTexts[i].size()); cg_printf("\"%s\", \"%s\",\n", def, defText); free(def); free(defText); } } else { cg_printf("\"\", \"\",\n"); } } cg_printf("NULL,\n"); m_variables->outputCPPStaticVariables(cg, ar); }