]>
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.
40 #include "cycript.hpp"
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_
<< ')';
219 void Catch::Output(CYOutput
&out
) const {
220 out
<< ' ' << "catch" << ' ' << '(' << *name_
<< ')' << ' ' << code_
;
225 void CYCompound::Output(CYOutput
&out
, CYFlags flags
) const {
226 if (CYExpression
*expression
= expressions_
)
227 if (CYExpression
*next
= expression
->next_
) {
228 expression
->Output(out
, CYLeft(flags
));
229 CYFlags
center(CYCenter(flags
));
230 while (next
!= NULL
) {
233 next
= expression
->next_
;
234 CYFlags
right(next
!= NULL
? center
: CYRight(flags
));
235 expression
->Output(out
, right
);
238 expression
->Output(out
, flags
);
241 void CYCondition::Output(CYOutput
&out
, CYFlags flags
) const {
242 test_
->Output(out
, Precedence() - 1, CYLeft(flags
));
243 out
<< ' ' << '?' << ' ';
245 true_
->Output(out
, CYPA
, CYNoFlags
);
246 out
<< ' ' << ':' << ' ';
247 false_
->Output(out
, CYPA
, CYRight(flags
));
250 void CYContinue::Output(CYOutput
&out
, CYFlags flags
) const {
253 out
<< ' ' << *label_
;
257 void CYClause::Output(CYOutput
&out
) const {
259 out
<< "case" << ' ' << *case_
;
263 if (statements_
!= NULL
)
264 statements_
->Multiple(out
);
268 const char *CYDeclaration::ForEachIn() const {
269 return identifier_
->Value();
272 void CYDeclaration::ForIn(CYOutput
&out
, CYFlags flags
) const {
274 Output(out
, CYRight(flags
));
277 void CYDeclaration::Output(CYOutput
&out
, CYFlags flags
) const {
279 if (initialiser_
!= NULL
) {
280 out
<< ' ' << '=' << ' ';
281 initialiser_
->Output(out
, CYPA
, CYRight(flags
));
285 void CYDeclarations::For(CYOutput
&out
) const {
290 void CYDeclarations::Output(CYOutput
&out
) const {
291 Output(out
, CYNoFlags
);
294 void CYDeclarations::Output(CYOutput
&out
, CYFlags flags
) const {
295 const CYDeclarations
*declaration(this);
298 CYDeclarations
*next(declaration
->next_
);
299 CYFlags
jacks(first
? CYLeft(flags
) : next
== NULL
? CYRight(flags
) : CYCenter(flags
));
301 declaration
->declaration_
->Output(out
, jacks
);
310 void CYDirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
311 object_
->Output(out
, Precedence(), CYLeft(flags
));
312 if (const char *word
= property_
->Word())
315 out
<< '[' << *property_
<< ']';
318 void CYDoWhile::Output(CYOutput
&out
, CYFlags flags
) const {
320 code_
->Single(out
, CYCenter(flags
));
321 out
<< "while" << ' ' << '(' << *test_
<< ')';
324 void CYElement::Output(CYOutput
&out
) const {
326 value_
->Output(out
, CYPA
, CYNoFlags
);
327 if (next_
!= NULL
|| value_
== NULL
) {
329 if (next_
!= NULL
&& next_
->value_
!= NULL
)
336 void CYEmpty::Output(CYOutput
&out
, CYFlags flags
) const {
340 void CYExpress::Output(CYOutput
&out
, CYFlags flags
) const {
341 expression_
->Output(out
, flags
| CYNoBF
);
345 void CYExpression::ClassName(CYOutput
&out
, bool object
) const {
346 Output(out
, CYPA
, CYNoFlags
);
349 const char *CYExpression::ForEachIn() const {
353 void CYExpression::For(CYOutput
&out
) const {
357 void CYExpression::ForIn(CYOutput
&out
, CYFlags flags
) const {
358 Output(out
, flags
| CYNoRightHand
);
361 void CYExpression::Output(CYOutput
&out
) const {
362 Output(out
, CYNoFlags
);
365 void CYExpression::Output(CYOutput
&out
, unsigned precedence
, CYFlags flags
) const {
366 if (precedence
< Precedence() || (flags
& CYNoRightHand
) != 0 && RightHand())
367 out
<< '(' << *this << ')';
372 void CYFinally::Output(CYOutput
&out
) const {
373 out
<< ' ' << "finally" << ' ' << code_
;
376 void CYFor::Output(CYOutput
&out
, CYFlags flags
) const {
377 out
<< "for" << ' ' << '(';
378 if (initialiser_
!= NULL
)
379 initialiser_
->For(out
);
385 code_
->Single(out
, CYRight(flags
));
388 void CYForEachIn::Output(CYOutput
&out
, CYFlags flags
) const {
389 out
<< "for" << ' ' << "each" << ' ' << '(';
390 initialiser_
->ForIn(out
, CYNoIn
);
391 out
<< "in" << *set_
<< ')';
392 code_
->Single(out
, CYRight(flags
));
395 void CYForEachInComprehension::Output(CYOutput
&out
) const {
396 out
<< "for" << ' ' << "each" << ' ' << '(' << *name_
<< ' ' << "in" << ' ' << *set_
<< ')' << next_
;
399 void CYForIn::Output(CYOutput
&out
, CYFlags flags
) const {
400 out
<< "for" << ' ' << '(';
401 initialiser_
->ForIn(out
, CYNoIn
);
402 out
<< "in" << *set_
<< ')';
403 code_
->Single(out
, CYRight(flags
));
406 void CYForInComprehension::Output(CYOutput
&out
) const {
407 out
<< "for" << ' ' << '(' << *name_
<< ' ' << "in" << ' ' << *set_
<< ')';
410 void CYFunction::Output(CYOutput
&out
, CYFlags flags
) const {
411 // XXX: one could imagine using + here to save a byte
412 bool protect((flags
& CYNoFunction
) != 0);
417 out
<< ' ' << *name_
;
418 out
<< '(' << parameters_
<< ')';
424 void CYFunctionExpression::Output(CYOutput
&out
, CYFlags flags
) const {
425 CYFunction::Output(out
, flags
);
428 void CYFunctionStatement::Output(CYOutput
&out
, CYFlags flags
) const {
429 CYFunction::Output(out
, flags
);
432 void CYFunctionParameter::Output(CYOutput
&out
) const {
435 out
<< ',' << ' ' << *next_
;
438 void CYIf::Output(CYOutput
&out
, CYFlags flags
) const {
440 if (false_
== NULL
&& (flags
& CYNoDangle
) != 0) {
445 out
<< "if" << ' ' << '(' << *test_
<< ')';
447 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
449 CYFlags
jacks(CYNoDangle
);
453 jacks
|= protect
? CYNoFlags
: CYCenter(flags
);
455 true_
->Single(out
, jacks
);
457 if (false_
!= NULL
) {
459 false_
->Single(out
, right
);
466 void CYIfComprehension::Output(CYOutput
&out
) const {
467 out
<< "if" << ' ' << '(' << *test_
<< ')' << next_
;
470 void CYIndirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
471 object_
->Output(out
, Precedence(), CYLeft(flags
));
472 if (const char *word
= property_
->Word())
475 out
<< "->" << '[' << *property_
<< ']';
478 void CYInfix::Output(CYOutput
&out
, CYFlags flags
) const {
479 const char *name(Operator());
480 bool protect((flags
& CYNoIn
) != 0 && strcmp(name
, "in") == 0);
483 CYFlags
left(protect
? CYNoFlags
: CYLeft(flags
));
484 lhs_
->Output(out
, Precedence(), left
);
485 out
<< ' ' << name
<< ' ';
486 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
487 rhs_
->Output(out
, Precedence() - 1, right
);
492 void CYLabel::Output(CYOutput
&out
, CYFlags flags
) const {
493 out
<< *name_
<< ':' << ' ';
494 statement_
->Single(out
, CYRight(flags
));
497 void CYLet::Output(CYOutput
&out
, CYFlags flags
) const {
498 out
<< "let" << ' ' << '(' << *declarations_
<< ')' << ' ' << code_
;
501 void CYNew::Output(CYOutput
&out
, CYFlags flags
) const {
503 CYFlags
jacks(CYNoCall
| CYCenter(flags
));
504 constructor_
->Output(out
, Precedence(), jacks
);
505 if (arguments_
!= NULL
)
506 out
<< '(' << *arguments_
<< ')';
509 void CYNull::Output(CYOutput
&out
, CYFlags flags
) const {
513 void CYNumber::Output(CYOutput
&out
, CYFlags flags
) const {
514 std::ostringstream str
;
515 CYNumerify(str
, Value());
516 out
<< str
.str().c_str();
519 void CYNumber::PropertyName(CYOutput
&out
) const {
520 Output(out
, CYNoFlags
);
523 void CYObject::Output(CYOutput
&out
, CYFlags flags
) const {
524 bool protect((flags
& CYNoBrace
) != 0);
536 void CYPostfix::Output(CYOutput
&out
, CYFlags flags
) const {
537 lhs_
->Output(out
, Precedence(), CYLeft(flags
));
541 void CYPrefix::Output(CYOutput
&out
, CYFlags flags
) const {
542 const char *name(Operator());
546 rhs_
->Output(out
, Precedence(), CYRight(flags
));
549 void CYProgram::Output(CYOutput
&out
) const {
550 if (statements_
!= NULL
)
551 statements_
->Multiple(out
);
554 void CYProperty::Output(CYOutput
&out
) const {
556 name_
->PropertyName(out
);
558 value_
->Output(out
, CYPA
, CYNoFlags
);
560 out
<< ',' << '\n' << *next_
;
565 void CYRegEx::Output(CYOutput
&out
, CYFlags flags
) const {
569 void CYReturn::Output(CYOutput
&out
, CYFlags flags
) const {
572 out
<< ' ' << *value_
;
576 void CYStatement::Multiple(CYOutput
&out
, CYFlags flags
) const {
578 for (const CYStatement
*next(this); next
!= NULL
; next
= next
->next_
) {
579 bool last(next
->next_
== NULL
);
580 CYFlags
jacks(first
? last
? flags
: CYLeft(flags
) : last
? CYCenter(flags
) : CYRight(flags
));
583 next
->Output(out
, jacks
);
588 void CYStatement::Single(CYOutput
&out
, CYFlags flags
) const {
589 _assert(next_
== NULL
);
598 void CYString::Output(CYOutput
&out
, CYFlags flags
) const {
599 std::ostringstream str
;
600 CYStringify(str
, value_
, size_
);
601 out
<< str
.str().c_str();
604 void CYString::PropertyName(CYOutput
&out
) const {
605 if (const char *word
= Word())
611 static const char *Reserved_
[] = {
612 "false", "null", "true",
614 "break", "case", "catch", "continue", "default",
615 "delete", "do", "else", "finally", "for", "function",
616 "if", "in", "instanceof", "new", "return", "switch",
617 "this", "throw", "try", "typeof", "var", "void",
622 "class", "enum", "export", "extends", "import", "super",
624 "abstract", "boolean", "byte", "char", "double", "final",
625 "float", "goto", "int", "long", "native", "short",
626 "synchronized", "throws", "transient", "volatile",
635 const char *CYString::Word() const {
636 if (size_
== 0 || !WordStartRange_
[value_
[0]])
638 for (size_t i(1); i
!= size_
; ++i
)
639 if (!WordEndRange_
[value_
[i
]])
641 const char *value(Value());
642 for (const char **reserved(Reserved_
); *reserved
!= NULL
; ++reserved
)
643 if (strcmp(*reserved
, value
) == 0)
648 void CYSwitch::Output(CYOutput
&out
, CYFlags flags
) const {
649 out
<< "switch" << ' ' << '(' << *value_
<< ')' << ' ' << '{';
654 void CYThis::Output(CYOutput
&out
, CYFlags flags
) const {
661 void Throw::Output(CYOutput
&out
, CYFlags flags
) const {
664 out
<< ' ' << *value_
;
668 void Try::Output(CYOutput
&out
, CYFlags flags
) const {
669 out
<< "try" << ' ' << code_
<< catch_
<< finally_
;
674 void CYVar::Output(CYOutput
&out
, CYFlags flags
) const {
676 declarations_
->Output(out
, flags
);
680 void CYVariable::Output(CYOutput
&out
, CYFlags flags
) const {
684 void CYWhile::Output(CYOutput
&out
, CYFlags flags
) const {
685 out
<< "while" << '(' << *test_
<< ')';
686 code_
->Single(out
, CYRight(flags
));
689 void CYWith::Output(CYOutput
&out
, CYFlags flags
) const {
690 out
<< "with" << '(' << *scope_
<< ')';
691 code_
->Single(out
, CYRight(flags
));
694 void CYWord::ClassName(CYOutput
&out
, bool object
) const {
696 out
<< "objc_getClass(";
697 out
<< '"' << Value() << '"';
702 void CYWord::Output(CYOutput
&out
) const {
706 void CYWord::PropertyName(CYOutput
&out
) const {