]>
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 {
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 std::ostringstream str
;
596 CYStringify(str
, value_
, size_
);
597 out
<< str
.str().c_str();
600 void CYString::PropertyName(CYOutput
&out
) const {
601 if (const char *word
= Word())
607 static const char *Reserved_
[] = {
608 "false", "null", "true",
610 "break", "case", "catch", "continue", "default",
611 "delete", "do", "else", "finally", "for", "function",
612 "if", "in", "instanceof", "new", "return", "switch",
613 "this", "throw", "try", "typeof", "var", "void",
618 "class", "enum", "export", "extends", "import", "super",
620 "abstract", "boolean", "byte", "char", "double", "final",
621 "float", "goto", "int", "long", "native", "short",
622 "synchronized", "throws", "transient", "volatile",
631 const char *CYString::Word() const {
632 if (size_
== 0 || !WordStartRange_
[value_
[0]])
634 for (size_t i(1); i
!= size_
; ++i
)
635 if (!WordEndRange_
[value_
[i
]])
637 const char *value(Value());
638 for (const char **reserved(Reserved_
); *reserved
!= NULL
; ++reserved
)
639 if (strcmp(*reserved
, value
) == 0)
644 void CYSwitch::Output(CYOutput
&out
, CYFlags flags
) const {
645 out
<< "switch" << ' ' << '(' << *value_
<< ')' << ' ' << '{';
650 void CYThis::Output(CYOutput
&out
, CYFlags flags
) const {
654 void CYThrow::Output(CYOutput
&out
, CYFlags flags
) const {
657 out
<< ' ' << *value_
;
661 void CYTry::Output(CYOutput
&out
, CYFlags flags
) const {
662 out
<< "try" << ' ' << code_
<< catch_
<< finally_
;
665 void CYVar::Output(CYOutput
&out
, CYFlags flags
) const {
667 declarations_
->Output(out
, flags
);
671 void CYVariable::Output(CYOutput
&out
, CYFlags flags
) const {
675 void CYWhile::Output(CYOutput
&out
, CYFlags flags
) const {
676 out
<< "while" << '(' << *test_
<< ')';
677 code_
->Single(out
, CYRight(flags
));
680 void CYWith::Output(CYOutput
&out
, CYFlags flags
) const {
681 out
<< "with" << '(' << *scope_
<< ')';
682 code_
->Single(out
, CYRight(flags
));
685 void CYWord::ClassName(CYOutput
&out
, bool object
) const {
687 out
<< "objc_getClass(";
688 out
<< '"' << Value() << '"';
693 void CYWord::Output(CYOutput
&out
) const {
697 void CYWord::PropertyName(CYOutput
&out
) const {