]>
git.saurik.com Git - cycript.git/blob - Output.cpp
1 /* Cycript - Remove Execution Server and Disassembler
2 * Copyright (C) 2009 Jay Freeman (saurik)
5 /* Modified BSD License {{{ */
7 * Redistribution and use in source and binary
8 * forms, with or without modification, are permitted
9 * provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the
12 * above copyright notice, this list of conditions
13 * and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the
15 * above copyright notice, this list of conditions
16 * and the following disclaimer in the documentation
17 * and/or other materials provided with the
19 * 3. The name of the author may not be used to endorse
20 * or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
25 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 _finline CYFlags
operator ~(CYFlags rhs
) {
46 return static_cast<CYFlags
>(~static_cast<unsigned>(rhs
));
49 _finline CYFlags
operator &(CYFlags lhs
, CYFlags rhs
) {
50 return static_cast<CYFlags
>(static_cast<unsigned>(lhs
) & static_cast<unsigned>(rhs
));
53 _finline CYFlags
operator |(CYFlags lhs
, CYFlags rhs
) {
54 return static_cast<CYFlags
>(static_cast<unsigned>(lhs
) | static_cast<unsigned>(rhs
));
57 _finline CYFlags
&operator |=(CYFlags
&lhs
, CYFlags rhs
) {
58 return lhs
= lhs
| rhs
;
61 _finline CYFlags
CYLeft(CYFlags flags
) {
62 return flags
& ~CYNoDangle
;
65 _finline CYFlags
CYRight(CYFlags flags
) {
66 return flags
& ~CYNoBF
;
69 _finline CYFlags
CYCenter(CYFlags flags
) {
70 return CYLeft(CYRight(flags
));
73 void CYOutput::Terminate() {
78 CYOutput
&CYOutput::operator <<(char rhs
) {
79 if (rhs
== ' ' || rhs
== '\n')
85 for (unsigned i(0); i
!= indent_
; ++i
)
94 if (mode_
== Terminated
&& rhs
!= '}')
104 } else if (rhs
== '+') {
108 } else if (rhs
== '-') {
109 if (mode_
== NoHyphen
)
112 } else if (WordEndRange_
[rhs
]) {
113 if (mode_
== NoLetter
)
124 CYOutput
&CYOutput::operator <<(const char *rhs
) {
125 size_t size(strlen(rhs
));
128 return *this << *rhs
;
130 if (mode_
== Terminated
)
133 mode_
== NoPlus
&& *rhs
== '+' ||
134 mode_
== NoHyphen
&& *rhs
== '-' ||
135 mode_
== NoLetter
&& WordEndRange_
[*rhs
]
139 if (WordEndRange_
[rhs
[size
- 1]])
148 void CYArgument::Output(CYOutput
&out
) const {
155 value_
->Output(out
, CYPA
, CYNoFlags
);
157 if (next_
->name_
== NULL
)
159 out
<< ' ' << *next_
;
163 void CYArray::Output(CYOutput
&out
, CYFlags flags
) const {
164 out
<< '[' << elements_
<< ']';
167 void CYArrayComprehension::Output(CYOutput
&out
, CYFlags flags
) const {
168 out
<< '[' << *expression_
<< ' ' << *comprehensions_
<< ']';
171 void CYAssignment::Output(CYOutput
&out
, CYFlags flags
) const {
172 lhs_
->Output(out
, Precedence() - 1, CYLeft(flags
) | CYNoRightHand
);
173 out
<< ' ' << Operator() << ' ';
174 rhs_
->Output(out
, Precedence(), CYRight(flags
));
177 void CYBlock::Output(CYOutput
&out
) const {
180 if (statements_
!= NULL
)
181 statements_
->Multiple(out
);
186 void CYBlock::Output(CYOutput
&out
, CYFlags flags
) const {
187 if (statements_
== NULL
)
189 else if (statements_
->next_
== NULL
)
190 statements_
->Single(out
, flags
);
195 void CYBoolean::Output(CYOutput
&out
, CYFlags flags
) const {
196 out
<< (Value() ? "true" : "false");
199 void CYBreak::Output(CYOutput
&out
, CYFlags flags
) const {
202 out
<< ' ' << *label_
;
206 void CYCall::Output(CYOutput
&out
, CYFlags flags
) const {
207 bool protect((flags
& CYNoCall
) != 0);
210 function_
->Output(out
, Precedence(), protect
? CYNoFlags
: flags
);
211 out
<< '(' << arguments_
<< ')';
216 void CYCatch::Output(CYOutput
&out
) const {
217 out
<< ' ' << "catch" << ' ' << '(' << *name_
<< ')' << ' ' << code_
;
220 void CYCompound::Output(CYOutput
&out
, CYFlags flags
) const {
221 if (CYExpression
*expression
= expressions_
)
222 if (CYExpression
*next
= expression
->next_
) {
223 expression
->Output(out
, CYLeft(flags
));
224 CYFlags
center(CYCenter(flags
));
225 while (next
!= NULL
) {
228 next
= expression
->next_
;
229 CYFlags
right(next
!= NULL
? center
: CYRight(flags
));
230 expression
->Output(out
, right
);
233 expression
->Output(out
, flags
);
236 void CYCondition::Output(CYOutput
&out
, CYFlags flags
) const {
237 test_
->Output(out
, Precedence() - 1, CYLeft(flags
));
238 out
<< ' ' << '?' << ' ';
240 true_
->Output(out
, CYPA
, CYNoFlags
);
241 out
<< ' ' << ':' << ' ';
242 false_
->Output(out
, CYPA
, CYRight(flags
));
245 void CYContinue::Output(CYOutput
&out
, CYFlags flags
) const {
248 out
<< ' ' << *label_
;
252 void CYClause::Output(CYOutput
&out
) const {
254 out
<< "case" << ' ' << *case_
;
258 if (statements_
!= NULL
)
259 statements_
->Multiple(out
);
263 const char *CYDeclaration::ForEachIn() const {
264 return identifier_
->Value();
267 void CYDeclaration::ForIn(CYOutput
&out
, CYFlags flags
) const {
269 Output(out
, CYRight(flags
));
272 void CYDeclaration::Output(CYOutput
&out
, CYFlags flags
) const {
274 if (initialiser_
!= NULL
) {
275 out
<< ' ' << '=' << ' ';
276 initialiser_
->Output(out
, CYPA
, CYRight(flags
));
280 void CYDeclarations::For(CYOutput
&out
) const {
285 void CYDeclarations::Output(CYOutput
&out
) const {
286 Output(out
, CYNoFlags
);
289 void CYDeclarations::Output(CYOutput
&out
, CYFlags flags
) const {
290 const CYDeclarations
*declaration(this);
293 CYDeclarations
*next(declaration
->next_
);
294 CYFlags
jacks(first
? CYLeft(flags
) : next
== NULL
? CYRight(flags
) : CYCenter(flags
));
296 declaration
->declaration_
->Output(out
, jacks
);
305 void CYDirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
306 object_
->Output(out
, Precedence(), CYLeft(flags
));
307 if (const char *word
= property_
->Word())
310 out
<< '[' << *property_
<< ']';
313 void CYDoWhile::Output(CYOutput
&out
, CYFlags flags
) const {
315 code_
->Single(out
, CYCenter(flags
));
316 out
<< "while" << ' ' << '(' << *test_
<< ')';
319 void CYElement::Output(CYOutput
&out
) const {
321 value_
->Output(out
, CYPA
, CYNoFlags
);
322 if (next_
!= NULL
|| value_
== NULL
) {
324 if (next_
!= NULL
&& next_
->value_
!= NULL
)
331 void CYEmpty::Output(CYOutput
&out
, CYFlags flags
) const {
335 void CYExpress::Output(CYOutput
&out
, CYFlags flags
) const {
336 expression_
->Output(out
, flags
| CYNoBF
);
340 void CYExpression::ClassName(CYOutput
&out
, bool object
) const {
341 Output(out
, CYPA
, CYNoFlags
);
344 const char *CYExpression::ForEachIn() const {
348 void CYExpression::For(CYOutput
&out
) const {
352 void CYExpression::ForIn(CYOutput
&out
, CYFlags flags
) const {
353 Output(out
, flags
| CYNoRightHand
);
356 void CYExpression::Output(CYOutput
&out
) const {
357 Output(out
, CYNoFlags
);
360 void CYExpression::Output(CYOutput
&out
, unsigned precedence
, CYFlags flags
) const {
361 if (precedence
< Precedence() || (flags
& CYNoRightHand
) != 0 && RightHand())
362 out
<< '(' << *this << ')';
367 void CYFinally::Output(CYOutput
&out
) const {
368 out
<< ' ' << "finally" << ' ' << code_
;
371 void CYFor::Output(CYOutput
&out
, CYFlags flags
) const {
372 out
<< "for" << ' ' << '(';
373 if (initialiser_
!= NULL
)
374 initialiser_
->For(out
);
380 code_
->Single(out
, CYRight(flags
));
383 void CYForEachIn::Output(CYOutput
&out
, CYFlags flags
) const {
384 out
<< "for" << ' ' << "each" << ' ' << '(';
385 initialiser_
->ForIn(out
, CYNoIn
);
386 out
<< "in" << *set_
<< ')';
387 code_
->Single(out
, CYRight(flags
));
390 void CYForEachInComprehension::Output(CYOutput
&out
) const {
391 out
<< "for" << ' ' << "each" << ' ' << '(' << *name_
<< ' ' << "in" << ' ' << *set_
<< ')' << next_
;
394 void CYForIn::Output(CYOutput
&out
, CYFlags flags
) const {
395 out
<< "for" << ' ' << '(';
396 initialiser_
->ForIn(out
, CYNoIn
);
397 out
<< "in" << *set_
<< ')';
398 code_
->Single(out
, CYRight(flags
));
401 void CYForInComprehension::Output(CYOutput
&out
) const {
402 out
<< "for" << ' ' << '(' << *name_
<< ' ' << "in" << ' ' << *set_
<< ')';
405 void CYFunction::Output(CYOutput
&out
, CYFlags flags
) const {
406 // XXX: one could imagine using + here to save a byte
407 bool protect((flags
& CYNoFunction
) != 0);
412 out
<< ' ' << *name_
;
413 out
<< '(' << parameters_
<< ')';
419 void CYFunctionExpression::Output(CYOutput
&out
, CYFlags flags
) const {
420 CYFunction::Output(out
, flags
);
423 void CYFunctionStatement::Output(CYOutput
&out
, CYFlags flags
) const {
424 CYFunction::Output(out
, flags
);
427 void CYFunctionParameter::Output(CYOutput
&out
) const {
430 out
<< ',' << ' ' << *next_
;
433 void CYIf::Output(CYOutput
&out
, CYFlags flags
) const {
435 if (false_
== NULL
&& (flags
& CYNoDangle
) != 0) {
440 out
<< "if" << ' ' << '(' << *test_
<< ')';
442 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
444 CYFlags
jacks(CYNoDangle
);
448 jacks
|= protect
? CYNoFlags
: CYCenter(flags
);
450 true_
->Single(out
, jacks
);
452 if (false_
!= NULL
) {
454 false_
->Single(out
, right
);
461 void CYIfComprehension::Output(CYOutput
&out
) const {
462 out
<< "if" << ' ' << '(' << *test_
<< ')' << next_
;
465 void CYIndirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
466 object_
->Output(out
, Precedence(), CYLeft(flags
));
467 if (const char *word
= property_
->Word())
470 out
<< "->" << '[' << *property_
<< ']';
473 void CYInfix::Output(CYOutput
&out
, CYFlags flags
) const {
474 const char *name(Operator());
475 bool protect((flags
& CYNoIn
) != 0 && strcmp(name
, "in") == 0);
478 CYFlags
left(protect
? CYNoFlags
: CYLeft(flags
));
479 lhs_
->Output(out
, Precedence(), left
);
480 out
<< ' ' << name
<< ' ';
481 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
482 rhs_
->Output(out
, Precedence() - 1, right
);
487 void CYLabel::Output(CYOutput
&out
, CYFlags flags
) const {
488 out
<< *name_
<< ':' << ' ';
489 statement_
->Single(out
, CYRight(flags
));
492 void CYLet::Output(CYOutput
&out
, CYFlags flags
) const {
493 out
<< "let" << ' ' << '(' << *declarations_
<< ')' << ' ' << code_
;
496 void CYNew::Output(CYOutput
&out
, CYFlags flags
) const {
498 CYFlags
jacks(CYNoCall
| CYCenter(flags
));
499 constructor_
->Output(out
, Precedence(), jacks
);
500 if (arguments_
!= NULL
)
501 out
<< '(' << *arguments_
<< ')';
504 void CYNull::Output(CYOutput
&out
, CYFlags flags
) const {
508 void CYNumber::Output(CYOutput
&out
, CYFlags flags
) const {
510 // XXX: I want this to print 1e3 rather than 1000
511 sprintf(value
, "%.17g", Value());
515 void CYNumber::PropertyName(CYOutput
&out
) const {
516 Output(out
, CYNoFlags
);
519 void CYObject::Output(CYOutput
&out
, CYFlags flags
) const {
520 bool protect((flags
& CYNoBrace
) != 0);
532 void CYPostfix::Output(CYOutput
&out
, CYFlags flags
) const {
533 lhs_
->Output(out
, Precedence(), CYLeft(flags
));
537 void CYPrefix::Output(CYOutput
&out
, CYFlags flags
) const {
538 const char *name(Operator());
542 rhs_
->Output(out
, Precedence(), CYRight(flags
));
545 void CYProgram::Output(CYOutput
&out
) const {
546 if (statements_
!= NULL
)
547 statements_
->Multiple(out
);
550 void CYProperty::Output(CYOutput
&out
) const {
552 name_
->PropertyName(out
);
554 value_
->Output(out
, CYPA
, CYNoFlags
);
556 out
<< ',' << '\n' << *next_
;
561 void CYRegEx::Output(CYOutput
&out
, CYFlags flags
) const {
565 void CYReturn::Output(CYOutput
&out
, CYFlags flags
) const {
568 out
<< ' ' << *value_
;
572 void CYStatement::Multiple(CYOutput
&out
, CYFlags flags
) const {
574 for (const CYStatement
*next(this); next
!= NULL
; next
= next
->next_
) {
575 bool last(next
->next_
== NULL
);
576 CYFlags
jacks(first
? last
? flags
: CYLeft(flags
) : last
? CYCenter(flags
) : CYRight(flags
));
579 next
->Output(out
, jacks
);
584 void CYStatement::Single(CYOutput
&out
, CYFlags flags
) const {
585 _assert(next_
== NULL
);
594 void CYString::Output(CYOutput
&out
, CYFlags flags
) const {
595 unsigned quot(0), apos(0);
596 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
599 else if (*value
== '\'')
602 bool single(quot
> apos
);
604 std::ostringstream str
;
606 str
<< (single
? '\'' : '"');
607 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
609 case '\\': str
<< "\\\\"; break;
610 case '\b': str
<< "\\b"; break;
611 case '\f': str
<< "\\f"; break;
612 case '\n': str
<< "\\n"; break;
613 case '\r': str
<< "\\r"; break;
614 case '\t': str
<< "\\t"; break;
615 case '\v': str
<< "\\v"; break;
630 if (*value
< 0x20 || *value
>= 0x7f)
631 str
<< "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value
);
635 str
<< (single
? '\'' : '"');
637 out
<< str
.str().c_str();
640 void CYString::PropertyName(CYOutput
&out
) const {
641 if (const char *word
= Word())
647 static const char *Reserved_
[] = {
648 "false", "null", "true",
650 "break", "case", "catch", "continue", "default",
651 "delete", "do", "else", "finally", "for", "function",
652 "if", "in", "instanceof", "new", "return", "switch",
653 "this", "throw", "try", "typeof", "var", "void",
658 "class", "enum", "export", "extends", "import", "super",
660 "abstract", "boolean", "byte", "char", "double", "final",
661 "float", "goto", "int", "long", "native", "short",
662 "synchronized", "throws", "transient", "volatile",
671 const char *CYString::Word() const {
672 if (size_
== 0 || !WordStartRange_
[value_
[0]])
674 for (size_t i(1); i
!= size_
; ++i
)
675 if (!WordEndRange_
[value_
[i
]])
677 const char *value(Value());
678 for (const char **reserved(Reserved_
); *reserved
!= NULL
; ++reserved
)
679 if (strcmp(*reserved
, value
) == 0)
684 void CYSwitch::Output(CYOutput
&out
, CYFlags flags
) const {
685 out
<< "switch" << ' ' << '(' << *value_
<< ')' << ' ' << '{';
690 void CYThis::Output(CYOutput
&out
, CYFlags flags
) const {
694 void CYThrow::Output(CYOutput
&out
, CYFlags flags
) const {
697 out
<< ' ' << *value_
;
701 void CYTry::Output(CYOutput
&out
, CYFlags flags
) const {
702 out
<< "try" << ' ' << code_
<< catch_
<< finally_
;
705 void CYVar::Output(CYOutput
&out
, CYFlags flags
) const {
707 declarations_
->Output(out
, flags
);
711 void CYVariable::Output(CYOutput
&out
, CYFlags flags
) const {
715 void CYWhile::Output(CYOutput
&out
, CYFlags flags
) const {
716 out
<< "while" << '(' << *test_
<< ')';
717 code_
->Single(out
, CYRight(flags
));
720 void CYWith::Output(CYOutput
&out
, CYFlags flags
) const {
721 out
<< "with" << '(' << *scope_
<< ')';
722 code_
->Single(out
, CYRight(flags
));
725 void CYWord::ClassName(CYOutput
&out
, bool object
) const {
727 out
<< "objc_getClass(";
728 out
<< '"' << Value() << '"';
733 void CYWord::Output(CYOutput
&out
) const {
737 void CYWord::PropertyName(CYOutput
&out
) const {