X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/aaa29c28ae45afad21be2891d38744d68d3c907e..2c4a8bb6222b88ff96fbf25372179646ce15f706:/Output.cpp diff --git a/Output.cpp b/Output.cpp index 1552304..26e49fe 100644 --- a/Output.cpp +++ b/Output.cpp @@ -25,47 +25,118 @@ #include "Syntax.hpp" -void CYStringify(std::ostringstream &str, const char *data, size_t size, bool c) { - bool single; - if (c) - single = false; +enum CYStringType { + CYStringTypeSingle, + CYStringTypeDouble, + CYStringTypeTemplate, +}; + +void CYStringify(std::ostringstream &str, const char *data, size_t size, CYStringifyMode mode) { + if (size == 0) { + str << "\"\""; + return; + } + + unsigned quot(0), apos(0), tick(0), line(0); + for (const char *value(data), *end(data + size); value != end; ++value) + switch (*value) { + case '"': ++quot; break; + case '\'': ++apos; break; + case '`': ++tick; break; + case '$': ++tick; break; + case '\n': ++line; break; + } + + bool split; + if (mode != CYStringifyModeCycript) + split = false; else { - unsigned quot(0), apos(0); - for (const char *value(data), *end(data + size); value != end; ++value) - if (*value == '"') - ++quot; - else if (*value == '\'') - ++apos; - - single = quot > apos; + double ratio(double(line) / size); + split = size > 10 && line > 2 && ratio > 0.005 && ratio < 0.10; } - str << (single ? '\'' : '"'); + CYStringType type; + if (mode == CYStringifyModeNative) + type = CYStringTypeDouble; + else if (split) + type = CYStringTypeTemplate; + else if (quot > apos) + type = CYStringTypeSingle; + else + type = CYStringTypeDouble; + + bool parens(split && mode != CYStringifyModeNative && type != CYStringTypeTemplate); + if (parens) + str << '('; + + char border; + switch (type) { + case CYStringTypeSingle: border = '\''; break; + case CYStringTypeDouble: border = '"'; break; + case CYStringTypeTemplate: border = '`'; break; + } + + str << border; + + bool space(false); for (const char *value(data), *end(data + size); value != end; ++value) - switch (uint8_t next = *value) { + if (*value == ' ') { + space = true; + str << ' '; + } else { switch (uint8_t next = *value) { case '\\': str << "\\\\"; break; case '\b': str << "\\b"; break; case '\f': str << "\\f"; break; - case '\n': str << "\\n"; break; case '\r': str << "\\r"; break; case '\t': str << "\\t"; break; case '\v': str << "\\v"; break; + case '\a': + if (mode == CYStringifyModeNative) + str << "\\a"; + else goto simple; + break; + + case '\n': + if (!split) + str << "\\n"; + /*else if (mode == CYStringifyModeNative) + str << border << "\\\n" << border;*/ + else if (type != CYStringTypeTemplate) + str << border << '+' << border; + else if (!space) + str << '\n'; + else + str << "\\n\\\n"; + break; + + case '$': + if (type == CYStringTypeTemplate) + str << "\\$"; + else goto simple; + break; + + case '`': + if (type == CYStringTypeTemplate) + str << "\\`"; + else goto simple; + break; + case '"': - if (!single) + if (type == CYStringTypeDouble) str << "\\\""; else goto simple; break; case '\'': - if (single) + if (type == CYStringTypeSingle) str << "\\'"; else goto simple; break; case '\0': - if (value[1] >= '0' && value[1] <= '9') + if (mode != CYStringifyModeNative && value[1] >= '0' && value[1] <= '9') str << "\\x00"; else str << "\\0"; @@ -74,6 +145,8 @@ void CYStringify(std::ostringstream &str, const char *data, size_t size, bool c) default: if (next >= 0x20 && next < 0x7f) simple: str << *value; + else if (mode == CYStringifyModeNative) + str << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value & 0xff); else { unsigned levels(1); if ((next & 0x80) != 0) @@ -93,9 +166,12 @@ void CYStringify(std::ostringstream &str, const char *data, size_t size, bool c) str << "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << (0xdc00 | point & 0x3ff); } } - } + } space = false; } - str << (single ? '\'' : '"'); + str << border; + + if (parens) + str << ')'; } void CYNumerify(std::ostringstream &str, double value) { @@ -226,6 +302,14 @@ void CYAssignment::Output(CYOutput &out, CYFlags flags) const { rhs_->Output(out, Precedence(), CYRight(flags)); } +void CYAttemptMember::Output(CYOutput &out, CYFlags flags) const { + object_->Output(out, Precedence(), CYLeft(flags) | CYNoInteger); + if (const char *word = property_->Word()) + out << "?." << word; + else + _assert(false); +} + void CYBlock::Output(CYOutput &out, CYFlags flags) const { out << '{' << '\n'; ++out.indent_; @@ -458,12 +542,15 @@ void CYExtend::Output(CYOutput &out, CYFlags flags) const { } void CYExternalDefinition::Output(CYOutput &out, CYFlags flags) const { - out << "extern" << ' ' << abi_ << ' ' << typed_; + out << "extern" << ' ' << abi_ << ' '; + type_->Output(out, name_); out.Terminate(); } void CYExternalExpression::Output(CYOutput &out, CYFlags flags) const { - out << '(' << "extern" << ' ' << abi_ << ' ' << typed_ << ')'; + out << '(' << "extern" << ' ' << abi_ << ' '; + type_->Output(out, name_); + out << ')'; } void CYFatArrow::Output(CYOutput &out, CYFlags flags) const { @@ -668,26 +755,26 @@ void CYTemplate::Output(CYOutput &out, CYFlags flags) const { _assert(false); } -void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const { - next_->Output(out, Precedence(), identifier, false); +void CYTypeArrayOf::Output(CYOutput &out, CYPropertyName *name) const { + next_->Output(out, Precedence(), name, false); out << '['; out << size_; out << ']'; } -void CYTypeBlockWith::Output(CYOutput &out, CYIdentifier *identifier) const { +void CYTypeBlockWith::Output(CYOutput &out, CYPropertyName *name) const { out << '(' << '^'; - next_->Output(out, Precedence(), identifier, false); + next_->Output(out, Precedence(), name, false); out << ')' << '(' << parameters_ << ')'; } -void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const { +void CYTypeConstant::Output(CYOutput &out, CYPropertyName *name) const { out << "const"; - next_->Output(out, Precedence(), identifier, false); + next_->Output(out, Precedence(), name, false); } -void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const { - next_->Output(out, Precedence(), identifier, false); +void CYTypeFunctionWith::Output(CYOutput &out, CYPropertyName *name) const { + next_->Output(out, Precedence(), name, false); out << '(' << parameters_; if (variadic_) { if (parameters_ != NULL) @@ -697,24 +784,24 @@ void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const { out << ')'; } -void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const { +void CYTypePointerTo::Output(CYOutput &out, CYPropertyName *name) const { out << '*'; - next_->Output(out, Precedence(), identifier, false); + next_->Output(out, Precedence(), name, false); } -void CYTypeVolatile::Output(CYOutput &out, CYIdentifier *identifier) const { +void CYTypeVolatile::Output(CYOutput &out, CYPropertyName *name) const { out << "volatile"; - next_->Output(out, Precedence(), identifier, true); + next_->Output(out, Precedence(), name, true); } -void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identifier, bool space) const { - if (this == NULL && identifier == NULL) +void CYTypeModifier::Output(CYOutput &out, int precedence, CYPropertyName *name, bool space) const { + if (this == NULL && name == NULL) return; else if (space) out << ' '; if (this == NULL) { - out << identifier; + name->PropertyName(out); return; } @@ -722,14 +809,18 @@ void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identif if (protect) out << '('; - Output(out, identifier); + Output(out, name); if (protect) out << ')'; } -void CYTypedIdentifier::Output(CYOutput &out) const { +void CYType::Output(CYOutput &out, CYPropertyName *name) const { out << *specifier_; - modifier_->Output(out, 0, identifier_, true); + modifier_->Output(out, 0, name, true); +} + +void CYType::Output(CYOutput &out) const { + Output(out, NULL); } void CYEncodedType::Output(CYOutput &out, CYFlags flags) const { @@ -737,7 +828,7 @@ void CYEncodedType::Output(CYOutput &out, CYFlags flags) const { } void CYTypedParameter::Output(CYOutput &out) const { - out << typed_; + type_->Output(out, name_); if (next_ != NULL) out << ',' << ' ' << next_; } @@ -751,7 +842,8 @@ void CYLambda::Output(CYOutput &out, CYFlags flags) const { } void CYTypeDefinition::Output(CYOutput &out, CYFlags flags) const { - out << "typedef" << ' ' << *typed_; + out << "typedef" << ' '; + type_->Output(out, name_); out.Terminate(); } @@ -940,7 +1032,7 @@ void CYStatement::Single(CYOutput &out, CYFlags flags, CYCompactType request) co void CYString::Output(CYOutput &out, CYFlags flags) const { std::ostringstream str; - CYStringify(str, value_, size_); + CYStringify(str, value_, size_, CYStringifyModeLegacy); out << str.str().c_str(); } @@ -994,7 +1086,8 @@ void CYStructTail::Output(CYOutput &out) const { out << ' ' << '{' << '\n'; ++out.indent_; CYForEach (field, fields_) { - out << '\t' << *field->typed_; + out << '\t'; + field->type_->Output(out, field->name_); out.Terminate(); out << '\n'; } @@ -1100,6 +1193,15 @@ void CYTypeError::Output(CYOutput &out) const { out << "@error"; } +void CYTypeFloating::Output(CYOutput &out) const { + switch (length_) { + case 0: out << "float"; break; + case 1: out << "double"; break; + case 2: out << "long" << ' ' << "double"; break; + default: _assert(false); + } +} + void CYTypeInt128::Output(CYOutput &out) const { switch (signing_) { case CYTypeNeutral: break;