X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/4e8c99fb09f51a009d1091d0a1a01ca73d7d4c85..b6d0605d27499279414e2433fae470302c99c110:/Output.cpp diff --git a/Output.cpp b/Output.cpp index 7eee678..a10705a 100644 --- a/Output.cpp +++ b/Output.cpp @@ -3,6 +3,9 @@ #include #include +#include +#include + _finline CYFlags operator ~(CYFlags rhs) { return static_cast(~static_cast(rhs)); } @@ -43,7 +46,7 @@ bool CYTrue::Value() const { void CYAddressOf::Output(std::ostream &out, CYFlags flags) const { rhs_->Output(out, 1, CYLeft(flags)); - out << ".$()"; + out << ".$cya()"; } void CYArgument::Output(std::ostream &out) const { @@ -104,14 +107,26 @@ void CYCatch::Output(std::ostream &out) const { code_->Output(out, true); } +void CYCategory::Output(std::ostream &out) const { + out << "(function($cys,$cyp,$cyc,$cyn,$cyt){"; + out << "$cyp=object_getClass($cys);"; + out << "$cyc=$cys;"; + if (messages_ != NULL) + messages_->Output(out, true); + out << "})("; + name_->ClassName(out); + out << ");"; +} + void CYClass::Output(std::ostream &out) const { - out << "(function($cys,$cyc,$cym,$cyn,$cyt){"; + out << "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){"; + out << "$cyp=object_getClass($cys);"; out << "$cyc=objc_allocateClassPair($cys,\"" << *name_ << "\",0);"; out << "$cym=object_getClass($cyc);"; if (fields_ != NULL) fields_->Output(out); if (messages_ != NULL) - messages_->Output(out); + messages_->Output(out, false); out << "objc_registerClassPair($cyc);"; out << "})("; if (super_ != NULL) @@ -121,6 +136,22 @@ void CYClass::Output(std::ostream &out) const { out << ");"; } +void CYCompound::Output(std::ostream &out, CYFlags flags) const { + if (CYExpression *expression = expressions_) + if (CYExpression *next = expression->next_) { + expression->Output(out, CYLeft(flags)); + CYFlags center(CYCenter(flags)); + while (next != NULL) { + expression = next; + out << ','; + next = expression->next_; + CYFlags right(next != NULL ? center : CYRight(flags)); + expression->Output(out, right); + } + } else + expression->Output(out, flags); +} + void CYCondition::Output(std::ostream &out, CYFlags flags) const { test_->Output(out, Precedence() - 1, CYLeft(flags)); out << '?'; @@ -183,6 +214,17 @@ void CYDeclarations::Output(std::ostream &out) const { out << ';'; } +void CYDirectMember::Output(std::ostream &out, CYFlags flags) const { + object_->Output(out, Precedence(), CYLeft(flags)); + if (const char *word = property_->Word()) + out << '.' << word; + else { + out << '['; + property_->Output(out, CYNoFlags); + out << ']'; + } +} + void CYDoWhile::Output(std::ostream &out) const { // XXX: extra space character! out << "do "; @@ -217,27 +259,15 @@ void CYExpress::Output(std::ostream &out) const { out << ';'; } +void CYExpression::ClassName(std::ostream &out) const { + Output(out, CYPA, CYNoFlags); +} + void CYExpression::Part(std::ostream &out) const { // XXX: this should handle LeftHandSideExpression Output(out, CYNoIn); } -void CYCompound::Output(std::ostream &out, CYFlags flags) const { - if (CYExpression *expression = expressions_) - if (CYExpression *next = expression->next_) { - expression->Output(out, CYLeft(flags)); - CYFlags center(CYCenter(flags)); - while (next != NULL) { - expression = next; - out << ','; - next = expression->next_; - CYFlags right(next != NULL ? center : CYRight(flags)); - expression->Output(out, right); - } - } else - expression->Output(out, flags); -} - void CYExpression::Output(std::ostream &out, unsigned precedence, CYFlags flags) const { if (precedence < Precedence()) { out << '('; @@ -301,7 +331,19 @@ void CYIf::Output(std::ostream &out) const { void CYIndirect::Output(std::ostream &out, CYFlags flags) const { rhs_->Output(out, 1, CYLeft(flags)); - out << "[0]"; + out << ".$cyi"; +} + +void CYIndirectMember::Output(std::ostream &out, CYFlags flags) const { + object_->Output(out, Precedence(), CYLeft(flags)); + out << ".$cyi"; + if (const char *word = property_->Word()) + out << '.' << word; + else { + out << '['; + property_->Output(out, CYNoFlags); + out << ']'; + } } void CYInfix::Output(std::ostream &out, CYFlags flags) const { @@ -341,20 +383,9 @@ void CYLambda::Output(std::ostream &out, CYFlags flags) const { out << ')'; } -void CYMember::Output(std::ostream &out, CYFlags flags) const { - object_->Output(out, Precedence(), CYLeft(flags)); - if (const char *word = property_->Word()) - out << '.' << word; - else { - out << '['; - property_->Output(out, CYNoFlags); - out << ']'; - } -} - -void CYMessage::Output(std::ostream &out) const { +void CYMessage::Output(std::ostream &out, bool replace) const { if (next_ != NULL) - next_->Output(out); + next_->Output(out, replace); out << "$cyn=new Selector(\""; for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_) if (parameter->tag_ != NULL) { @@ -363,8 +394,8 @@ void CYMessage::Output(std::ostream &out) const { out << ':'; } out << "\");"; - out << "$cyt=$cyn.type($cys," << (instance_ ? "true" : "false") << ");"; - out << "class_addMethod($cy" << (instance_ ? 'c' : 'm') << ",$cyn,"; + out << "$cyt=$cyn.type($cy" << (instance_ ? 's' : 'p') << ");"; + out << "class_" << (replace ? "replace" : "add") << "Method($cy" << (instance_ ? 'c' : 'm') << ",$cyn,"; out << "new Functor(function(self,_cmd"; for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_) if (parameter->name_ != NULL) @@ -376,6 +407,8 @@ void CYMessage::Output(std::ostream &out) const { } void CYNew::Output(std::ostream &out, CYFlags flags) const { + if ((flags & CYNoLeader) != 0) + out << ' '; out << "new"; constructor_->Output(out, Precedence(), CYCenter(flags) | CYNoLeader); out << '('; @@ -395,12 +428,16 @@ void CYNull::Output(std::ostream &out, CYFlags flags) const { void CYNumber::Output(std::ostream &out, CYFlags flags) const { if ((flags & CYNoLeader) != 0) out << ' '; - // XXX: this is not a useful formatting - out << Value(); + // XXX: decide on correct precision + out << std::setprecision(9) << Value(); if ((flags & CYNoTrailer) != 0) out << ' '; } +void CYNumber::PropertyName(std::ostream &out) const { + Output(out); +} + void CYObject::Output(std::ostream &out, CYFlags flags) const { bool protect((flags & CYNoBrace) != 0); if (protect) @@ -428,7 +465,8 @@ void CYPrefix::Output(std::ostream &out, CYFlags flags) const { } void CYProperty::Output(std::ostream &out) const { - out << *name_ << ':'; + name_->PropertyName(out); + out << ':'; value_->Output(out, CYPA, CYNoFlags); if (next_ != NULL) { out << ','; @@ -444,6 +482,8 @@ void CYReturn::Output(std::ostream &out) const { } void CYSelector::Output(std::ostream &out, CYFlags flags) const { + if ((flags & CYNoLeader) != 0) + out << ' '; out << "new Selector(\""; if (name_ != NULL) name_->Output(out); @@ -460,16 +500,19 @@ void CYSelectorPart::Output(std::ostream &out) const { } void CYSend::Output(std::ostream &out, CYFlags flags) const { + if ((flags & CYNoLeader) != 0) + out << ' '; out << "objc_msgSend("; self_->Output(out, CYPA, CYNoFlags); - out << ",\""; + out << ","; + std::ostringstream name; for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_) if (argument->name_ != NULL) { - out << *argument->name_; + name << *argument->name_; if (argument->value_ != NULL) - out << ':'; + name << ':'; } - out << "\""; + out << reinterpret_cast(sel_registerName(name.str().c_str())); for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_) if (argument->value_ != NULL) { out << ","; @@ -494,10 +537,18 @@ void CYSource::Output(std::ostream &out, bool block) const { } void CYString::Output(std::ostream &out, CYFlags flags) const { - out << '\"'; + unsigned quot(0), apos(0); + for (const char *value(value_), *end(value_ + size_); value != end; ++value) + if (*value == '"') + ++quot; + else if (*value == '\'') + ++apos; + + bool single(quot > apos); + + out << (single ? '\'' : '"'); for (const char *value(value_), *end(value_ + size_); value != end; ++value) switch (*value) { - case '"': out << "\\\""; break; case '\\': out << "\\\\"; break; case '\b': out << "\\b"; break; case '\f': out << "\\f"; break; @@ -506,13 +557,32 @@ void CYString::Output(std::ostream &out, CYFlags flags) const { case '\t': out << "\\t"; break; case '\v': out << "\\v"; break; + case '"': + if (!single) + out << "\\\""; + else goto simple; + break; + + case '\'': + if (single) + out << "\\'"; + else goto simple; + break; + default: if (*value < 0x20 || *value >= 0x7f) out << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value); - else + else simple: out << *value; } - out << '\"'; + out << (single ? '\'' : '"'); +} + +void CYString::PropertyName(std::ostream &out) const { + if (const char *word = Word()) + out << word; + else + Output(out); } void CYSwitch::Output(std::ostream &out) const { @@ -543,7 +613,7 @@ void CYTry::Output(std::ostream &out) const { out << "try"; try_->Output(out, true); if (catch_ != NULL) - out << catch_; + catch_->Output(out); if (finally_ != NULL) { out << "finally"; finally_->Output(out, true); @@ -572,6 +642,14 @@ void CYWith::Output(std::ostream &out) const { code_->Output(out, false); } +void CYWord::ClassName(std::ostream &out) const { + out << "objc_getClass(\"" << Value() << "\")"; +} + void CYWord::Output(std::ostream &out) const { out << Value(); } + +void CYWord::PropertyName(std::ostream &out) const { + Output(out); +}