]>
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_
<< ')';
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 {
509 std::ostringstream str
;
510 CYNumerify(str
, Value());
511 out
<< str
.str().c_str();
514 void CYNumber::PropertyName(CYOutput
&out
) const {
515 Output(out
, CYNoFlags
);
518 void CYObject::Output(CYOutput
&out
, CYFlags flags
) const {
519 bool protect((flags
& CYNoBrace
) != 0);
531 void CYPostfix::Output(CYOutput
&out
, CYFlags flags
) const {
532 lhs_
->Output(out
, Precedence(), CYLeft(flags
));
536 void CYPrefix::Output(CYOutput
&out
, CYFlags flags
) const {
537 const char *name(Operator());
541 rhs_
->Output(out
, Precedence(), CYRight(flags
));
544 void CYProgram::Output(CYOutput
&out
) const {
545 if (statements_
!= NULL
)
546 statements_
->Multiple(out
);
549 void CYProperty::Output(CYOutput
&out
) const {
551 name_
->PropertyName(out
);
553 value_
->Output(out
, CYPA
, CYNoFlags
);
555 out
<< ',' << '\n' << *next_
;
560 void CYRegEx::Output(CYOutput
&out
, CYFlags flags
) const {
564 void CYReturn::Output(CYOutput
&out
, CYFlags flags
) const {
567 out
<< ' ' << *value_
;
571 void CYStatement::Multiple(CYOutput
&out
, CYFlags flags
) const {
573 for (const CYStatement
*next(this); next
!= NULL
; next
= next
->next_
) {
574 bool last(next
->next_
== NULL
);
575 CYFlags
jacks(first
? last
? flags
: CYLeft(flags
) : last
? CYCenter(flags
) : CYRight(flags
));
578 next
->Output(out
, jacks
);
583 void CYStatement::Single(CYOutput
&out
, CYFlags flags
) const {
584 _assert(next_
== NULL
);
593 void CYString::Output(CYOutput
&out
, CYFlags flags
) const {
594 std::ostringstream str
;
595 CYStringify(str
, value_
, size_
);
596 out
<< str
.str().c_str();
599 void CYString::PropertyName(CYOutput
&out
) const {
600 if (const char *word
= Word())
606 static const char *Reserved_
[] = {
607 "false", "null", "true",
609 "break", "case", "catch", "continue", "default",
610 "delete", "do", "else", "finally", "for", "function",
611 "if", "in", "instanceof", "new", "return", "switch",
612 "this", "throw", "try", "typeof", "var", "void",
617 "class", "enum", "export", "extends", "import", "super",
619 "abstract", "boolean", "byte", "char", "double", "final",
620 "float", "goto", "int", "long", "native", "short",
621 "synchronized", "throws", "transient", "volatile",
630 const char *CYString::Word() const {
631 if (size_
== 0 || !WordStartRange_
[value_
[0]])
633 for (size_t i(1); i
!= size_
; ++i
)
634 if (!WordEndRange_
[value_
[i
]])
636 const char *value(Value());
637 for (const char **reserved(Reserved_
); *reserved
!= NULL
; ++reserved
)
638 if (strcmp(*reserved
, value
) == 0)
643 void CYSwitch::Output(CYOutput
&out
, CYFlags flags
) const {
644 out
<< "switch" << ' ' << '(' << *value_
<< ')' << ' ' << '{';
649 void CYThis::Output(CYOutput
&out
, CYFlags flags
) const {
653 void CYThrow::Output(CYOutput
&out
, CYFlags flags
) const {
656 out
<< ' ' << *value_
;
660 void CYTry::Output(CYOutput
&out
, CYFlags flags
) const {
661 out
<< "try" << ' ' << code_
<< catch_
<< finally_
;
664 void CYVar::Output(CYOutput
&out
, CYFlags flags
) const {
666 declarations_
->Output(out
, flags
);
670 void CYVariable::Output(CYOutput
&out
, CYFlags flags
) const {
674 void CYWhile::Output(CYOutput
&out
, CYFlags flags
) const {
675 out
<< "while" << '(' << *test_
<< ')';
676 code_
->Single(out
, CYRight(flags
));
679 void CYWith::Output(CYOutput
&out
, CYFlags flags
) const {
680 out
<< "with" << '(' << *scope_
<< ')';
681 code_
->Single(out
, CYRight(flags
));
684 void CYWord::ClassName(CYOutput
&out
, bool object
) const {
686 out
<< "objc_getClass(";
687 out
<< '"' << Value() << '"';
692 void CYWord::Output(CYOutput
&out
) const {
696 void CYWord::PropertyName(CYOutput
&out
) const {