]>
git.saurik.com Git - cycript.git/blob - Output.cpp
6 #include <objc/runtime.h>
9 _finline CYFlags
operator ~(CYFlags rhs
) {
10 return static_cast<CYFlags
>(~static_cast<unsigned>(rhs
));
13 _finline CYFlags
operator &(CYFlags lhs
, CYFlags rhs
) {
14 return static_cast<CYFlags
>(static_cast<unsigned>(lhs
) & static_cast<unsigned>(rhs
));
17 _finline CYFlags
operator |(CYFlags lhs
, CYFlags rhs
) {
18 return static_cast<CYFlags
>(static_cast<unsigned>(lhs
) | static_cast<unsigned>(rhs
));
21 _finline CYFlags
&operator |=(CYFlags
&lhs
, CYFlags rhs
) {
22 return lhs
= lhs
| rhs
;
25 _finline CYFlags
CYLeft(CYFlags flags
) {
26 return flags
& ~CYNoDangle
;
29 _finline CYFlags
CYRight(CYFlags flags
) {
30 return flags
& ~CYNoBF
;
33 _finline CYFlags
CYCenter(CYFlags flags
) {
34 return CYLeft(CYRight(flags
));
39 void CYOutput::Terminate() {
44 CYOutput
&CYOutput::operator <<(char rhs
) {
45 if (rhs
== ' ' || rhs
== '\n')
51 for (unsigned i(0); i
!= indent_
; ++i
)
60 if (mode_
== Terminated
&& rhs
!= '}')
70 } else if (rhs
== '+') {
74 } else if (rhs
== '-') {
75 if (mode_
== NoHyphen
)
78 } else if (WordEndRange_
[rhs
]) {
79 if (mode_
== NoLetter
)
90 CYOutput
&CYOutput::operator <<(const char *rhs
) {
91 size_t size(strlen(rhs
));
96 if (mode_
== Terminated
)
99 mode_
== NoPlus
&& *rhs
== '+' ||
100 mode_
== NoHyphen
&& *rhs
== '-' ||
101 mode_
== NoLetter
&& WordEndRange_
[*rhs
]
105 if (WordEndRange_
[rhs
[size
- 1]])
114 void CYArgument::Output(CYOutput
&out
) const {
121 value_
->Output(out
, CYPA
, CYNoFlags
);
123 if (next_
->name_
== NULL
)
125 out
<< ' ' << *next_
;
129 void CYArray::Output(CYOutput
&out
, CYFlags flags
) const {
130 out
<< '[' << elements_
<< ']';
133 void CYArrayComprehension::Output(CYOutput
&out
, CYFlags flags
) const {
134 // XXX: I don't necc. need the ()s
135 out
<< "(function($cyv";
136 for (CYComprehension
*comprehension(comprehensions_
); comprehension
!= NULL
; comprehension
= comprehension
->next_
)
137 if (const char *name
= comprehension
->Name())
141 comprehensions_
->Output(out
);
143 expression_
->Output(out
, CYPA
, CYNoFlags
);
145 for (CYComprehension
*comprehension(comprehensions_
); comprehension
!= NULL
; comprehension
= comprehension
->next_
)
146 comprehension
->End_(out
);
147 out
<< "return $cyv;";
151 void CYAssignment::Output(CYOutput
&out
, CYFlags flags
) const {
152 lhs_
->Output(out
, Precedence() - 1, CYLeft(flags
) | CYNoRightHand
);
153 out
<< ' ' << Operator() << ' ';
154 rhs_
->Output(out
, Precedence(), CYRight(flags
));
157 void CYBlock::Output(CYOutput
&out
) const {
160 if (statements_
!= NULL
)
161 statements_
->Multiple(out
);
166 void CYBlock::Output(CYOutput
&out
, CYFlags flags
) const {
167 if (statements_
== NULL
)
169 else if (statements_
->next_
== NULL
)
170 statements_
->Single(out
, flags
);
175 void CYBoolean::Output(CYOutput
&out
, CYFlags flags
) const {
176 out
<< (Value() ? "true" : "false");
179 void CYBreak::Output(CYOutput
&out
, CYFlags flags
) const {
182 out
<< ' ' << *label_
;
186 void CYCall::Output(CYOutput
&out
, CYFlags flags
) const {
187 bool protect((flags
& CYNoCall
) != 0);
190 function_
->Output(out
, Precedence(), protect
? CYNoFlags
: flags
);
191 out
<< '(' << arguments_
<< ')';
196 void CYCatch::Output(CYOutput
&out
) const {
197 out
<< ' ' << "catch" << ' ' << '(' << *name_
<< ')' << ' ' << code_
;
200 void CYCategory::Output(CYOutput
&out
, CYFlags flags
) const {
201 out
<< "(function($cys,$cyp,$cyc,$cyn,$cyt){";
202 out
<< "$cyp=object_getClass($cys);";
204 if (messages_
!= NULL
)
205 messages_
->Output(out
, true);
207 name_
->ClassName(out
, true);
212 void CYClass::Output(CYOutput
&out
, CYFlags flags
) const {
213 // XXX: I don't necc. need the ()s
214 out
<< "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){";
215 out
<< "$cyp=object_getClass($cys);";
216 out
<< "$cyc=objc_allocateClassPair($cys,";
218 name_
->ClassName(out
, false);
220 out
<< "$cyq(\"CY$\")";
222 out
<< "$cym=object_getClass($cyc);";
224 fields_
->Output(out
);
225 if (messages_
!= NULL
)
226 messages_
->Output(out
, false);
227 out
<< "objc_registerClassPair($cyc);";
228 out
<< "return $cyc;";
231 super_
->Output(out
, CYPA
, CYNoFlags
);
237 void CYClassExpression::Output(CYOutput
&out
, CYFlags flags
) const {
238 CYClass::Output(out
, flags
);
241 void CYClassStatement::Output(CYOutput
&out
, CYFlags flags
) const {
242 CYClass::Output(out
, flags
);
245 void CYCompound::Output(CYOutput
&out
, CYFlags flags
) const {
246 if (CYExpression
*expression
= expressions_
)
247 if (CYExpression
*next
= expression
->next_
) {
248 expression
->Output(out
, CYLeft(flags
));
249 CYFlags
center(CYCenter(flags
));
250 while (next
!= NULL
) {
253 next
= expression
->next_
;
254 CYFlags
right(next
!= NULL
? center
: CYRight(flags
));
255 expression
->Output(out
, right
);
258 expression
->Output(out
, flags
);
261 void CYComprehension::Output(CYOutput
&out
) const {
266 void CYCondition::Output(CYOutput
&out
, CYFlags flags
) const {
267 test_
->Output(out
, Precedence() - 1, CYLeft(flags
));
268 out
<< ' ' << '?' << ' ';
270 true_
->Output(out
, CYPA
, CYNoFlags
);
271 out
<< ' ' << ':' << ' ';
272 false_
->Output(out
, CYPA
, CYRight(flags
));
275 void CYContinue::Output(CYOutput
&out
, CYFlags flags
) const {
278 out
<< ' ' << *label_
;
282 void CYClause::Output(CYOutput
&out
) const {
284 out
<< "case" << ' ' << *case_
;
288 if (statements_
!= NULL
)
289 statements_
->Multiple(out
);
293 const char *CYDeclaration::ForEachIn() const {
294 return identifier_
->Value();
297 void CYDeclaration::ForIn(CYOutput
&out
, CYFlags flags
) const {
299 Output(out
, CYRight(flags
));
302 void CYDeclaration::ForEachIn(CYOutput
&out
) const {
306 void CYDeclaration::Output(CYOutput
&out
, CYFlags flags
) const {
308 if (initialiser_
!= NULL
) {
309 out
<< ' ' << '=' << ' ';
310 initialiser_
->Output(out
, CYPA
, CYRight(flags
));
314 void CYDeclarations::For(CYOutput
&out
) const {
319 void CYDeclarations::Output(CYOutput
&out
) const {
320 Output(out
, CYNoFlags
);
323 void CYDeclarations::Output(CYOutput
&out
, CYFlags flags
) const {
324 const CYDeclarations
*declaration(this);
327 CYDeclarations
*next(declaration
->next_
);
328 CYFlags
jacks(first
? CYLeft(flags
) : next
== NULL
? CYRight(flags
) : CYCenter(flags
));
330 declaration
->declaration_
->Output(out
, jacks
);
339 void CYDirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
340 object_
->Output(out
, Precedence(), CYLeft(flags
));
341 if (const char *word
= property_
->Word())
344 out
<< '[' << *property_
<< ']';
347 void CYDoWhile::Output(CYOutput
&out
, CYFlags flags
) const {
349 code_
->Single(out
, CYCenter(flags
));
350 out
<< "while" << ' ' << '(' << *test_
<< ')';
353 void CYElement::Output(CYOutput
&out
) const {
355 value_
->Output(out
, CYPA
, CYNoFlags
);
356 if (next_
!= NULL
|| value_
== NULL
) {
358 if (next_
!= NULL
&& next_
->value_
!= NULL
)
365 void CYEmpty::Output(CYOutput
&out
, CYFlags flags
) const {
369 void CYExpress::Output(CYOutput
&out
, CYFlags flags
) const {
370 expression_
->Output(out
, flags
| CYNoBF
);
374 void CYExpression::ClassName(CYOutput
&out
, bool object
) const {
375 Output(out
, CYPA
, CYNoFlags
);
378 const char *CYExpression::ForEachIn() const {
382 void CYExpression::For(CYOutput
&out
) const {
386 void CYExpression::ForEachIn(CYOutput
&out
) const {
387 Output(out
, CYPA
, CYNoRightHand
);
390 void CYExpression::ForIn(CYOutput
&out
, CYFlags flags
) const {
391 Output(out
, flags
| CYNoRightHand
);
394 void CYExpression::Output(CYOutput
&out
) const {
395 Output(out
, CYNoFlags
);
398 void CYExpression::Output(CYOutput
&out
, unsigned precedence
, CYFlags flags
) const {
399 if (precedence
< Precedence() || (flags
& CYNoRightHand
) != 0 && RightHand())
400 out
<< '(' << *this << ')';
405 void CYField::Output(CYOutput
&out
) const {
409 void CYFinally::Output(CYOutput
&out
) const {
410 out
<< ' ' << "finally" << ' ' << code_
;
413 void CYFor::Output(CYOutput
&out
, CYFlags flags
) const {
414 out
<< "for" << ' ' << '(';
415 if (initialiser_
!= NULL
)
416 initialiser_
->For(out
);
422 code_
->Single(out
, CYRight(flags
));
425 void CYForEachIn::Output(CYOutput
&out
, CYFlags flags
) const {
426 out
<< "with({$cys:0,$cyt:0}){";
429 set_
->Output(out
, CYPA
, CYNoFlags
);
432 out
<< "for($cyt in $cys){";
434 initialiser_
->ForEachIn(out
);
435 out
<< "=$cys[$cyt];";
437 code_
->Multiple(out
);
444 void CYForEachInComprehension::Begin_(CYOutput
&out
) const {
445 out
<< "(function($cys){";
447 set_
->Output(out
, CYPA
, CYNoFlags
);
450 out
<< "for(" << *name_
<< " in $cys){";
451 out
<< *name_
<< "=$cys[" << *name_
<< "];";
454 void CYForEachInComprehension::End_(CYOutput
&out
) const {
458 void CYForIn::Output(CYOutput
&out
, CYFlags flags
) const {
459 out
<< "for" << ' ' << '(';
460 initialiser_
->ForIn(out
, CYNoIn
);
461 out
<< "in" << *set_
<< ')';
462 code_
->Single(out
, CYRight(flags
));
465 void CYForInComprehension::Begin_(CYOutput
&out
) const {
466 out
<< "for" << ' ' << '(' << *name_
<< "in" << *set_
<< ')';
469 void CYFunction::Output(CYOutput
&out
, CYFlags flags
) const {
470 // XXX: one could imagine using + here to save a byte
471 bool protect((flags
& CYNoFunction
) != 0);
476 out
<< ' ' << *name_
;
477 out
<< '(' << parameters_
<< ')';
483 void CYFunctionExpression::Output(CYOutput
&out
, CYFlags flags
) const {
484 CYFunction::Output(out
, flags
);
487 void CYFunctionStatement::Output(CYOutput
&out
, CYFlags flags
) const {
488 CYFunction::Output(out
, flags
);
491 void CYFunctionParameter::Output(CYOutput
&out
) const {
494 out
<< ',' << ' ' << *next_
;
497 void CYIf::Output(CYOutput
&out
, CYFlags flags
) const {
499 if (false_
== NULL
&& (flags
& CYNoDangle
) != 0) {
504 out
<< "if" << ' ' << '(' << *test_
<< ')';
506 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
508 CYFlags
jacks(CYNoDangle
);
512 jacks
|= protect
? CYNoFlags
: CYCenter(flags
);
514 true_
->Single(out
, jacks
);
516 if (false_
!= NULL
) {
518 false_
->Single(out
, right
);
525 void CYIfComprehension::Begin_(CYOutput
&out
) const {
526 out
<< "if" << '(' << *test_
<< ')';
529 void CYIndirectMember::Output(CYOutput
&out
, CYFlags flags
) const {
530 object_
->Output(out
, Precedence(), CYLeft(flags
));
531 if (const char *word
= property_
->Word())
534 out
<< "->" << '[' << *property_
<< ']';
537 void CYInfix::Output(CYOutput
&out
, CYFlags flags
) const {
538 const char *name(Operator());
539 bool protect((flags
& CYNoIn
) != 0 && strcmp(name
, "in") == 0);
542 CYFlags
left(protect
? CYNoFlags
: CYLeft(flags
));
543 lhs_
->Output(out
, Precedence(), left
);
544 out
<< ' ' << name
<< ' ';
545 CYFlags
right(protect
? CYNoFlags
: CYRight(flags
));
546 rhs_
->Output(out
, Precedence() - 1, right
);
551 void CYLabel::Output(CYOutput
&out
, CYFlags flags
) const {
552 out
<< *name_
<< ':' << ' ';
553 statement_
->Single(out
, CYRight(flags
));
556 void CYLet::Output(CYOutput
&out
, CYFlags flags
) const {
557 out
<< "let" << ' ' << '(' << *declarations_
<< ')' << ' ' << code_
;
560 void CYMessage::Output(CYOutput
&out
, bool replace
) const {
562 next_
->Output(out
, replace
);
563 out
<< "$cyn=new Selector(\"";
564 for (CYMessageParameter
*parameter(parameters_
); parameter
!= NULL
; parameter
= parameter
->next_
)
565 if (parameter
->tag_
!= NULL
) {
566 out
<< *parameter
->tag_
;
567 if (parameter
->name_
!= NULL
)
571 out
<< "$cyt=$cyn.type($cy" << (instance_
? 's' : 'p') << ')' << ';';
572 out
<< (replace
? "class_replaceMethod" : "class_addMethod") << '(' << (instance_
? "$cyc" : "$cym") << ',' << "$cyn" << ',';
573 out
<< "new Functor(function(self,_cmd";
574 for (CYMessageParameter
*parameter(parameters_
); parameter
!= NULL
; parameter
= parameter
->next_
)
575 if (parameter
->name_
!= NULL
)
576 out
<< ',' << *parameter
->name_
;
577 out
<< "){return function(){";
578 if (statements_
!= NULL
)
579 statements_
->Multiple(out
);
580 out
<< "}.call(self);},$cyt),$cyt);";
583 void CYNew::Output(CYOutput
&out
, CYFlags flags
) const {
585 CYFlags
jacks(CYNoCall
| CYCenter(flags
));
586 constructor_
->Output(out
, Precedence(), jacks
);
587 if (arguments_
!= NULL
)
588 out
<< '(' << *arguments_
<< ')';
591 void CYNull::Output(CYOutput
&out
, CYFlags flags
) const {
595 void CYNumber::Output(CYOutput
&out
, CYFlags flags
) const {
597 sprintf(value
, "%.17g", Value());
601 void CYNumber::PropertyName(CYOutput
&out
) const {
602 Output(out
, CYNoFlags
);
605 void CYObject::Output(CYOutput
&out
, CYFlags flags
) const {
606 bool protect((flags
& CYNoBrace
) != 0);
618 void CYPostfix::Output(CYOutput
&out
, CYFlags flags
) const {
619 lhs_
->Output(out
, Precedence(), CYLeft(flags
));
623 void CYPrefix::Output(CYOutput
&out
, CYFlags flags
) const {
624 const char *name(Operator());
628 rhs_
->Output(out
, Precedence(), CYRight(flags
));
631 void CYProgram::Output(CYOutput
&out
) const {
632 if (statements_
!= NULL
)
633 statements_
->Multiple(out
);
636 void CYProperty::Output(CYOutput
&out
) const {
638 name_
->PropertyName(out
);
640 value_
->Output(out
, CYPA
, CYNoFlags
);
642 out
<< ',' << '\n' << *next_
;
647 void CYRegEx::Output(CYOutput
&out
, CYFlags flags
) const {
651 void CYReturn::Output(CYOutput
&out
, CYFlags flags
) const {
654 out
<< ' ' << *value_
;
658 void CYSelector::Output(CYOutput
&out
, CYFlags flags
) const {
659 out
<< "@selector" << '(' << name_
<< ')';
662 void CYSelectorPart::Output(CYOutput
&out
) const {
669 void CYSend::Output(CYOutput
&out
, CYFlags flags
) const {
671 self_
->Output(out
, CYPA
, CYNoFlags
);
674 std::ostringstream name
;
675 for (CYArgument
*argument(arguments_
); argument
!= NULL
; argument
= argument
->next_
)
676 if (argument
->name_
!= NULL
) {
677 name
<< *argument
->name_
;
678 if (argument
->value_
!= NULL
)
682 out
.out_
<< reinterpret_cast<void *>(sel_registerName(name
.str().c_str()));
683 for (CYArgument
*argument(arguments_
); argument
!= NULL
; argument
= argument
->next_
)
684 if (argument
->value_
!= NULL
) {
686 argument
->value_
->Output(out
, CYPA
, CYNoFlags
);
691 void CYStatement::Multiple(CYOutput
&out
, CYFlags flags
) const {
693 for (const CYStatement
*next(this); next
!= NULL
; next
= next
->next_
) {
694 bool last(next
->next_
== NULL
);
695 CYFlags
jacks(first
? last
? flags
: CYLeft(flags
) : last
? CYCenter(flags
) : CYRight(flags
));
698 next
->Output(out
, jacks
);
703 void CYStatement::Single(CYOutput
&out
, CYFlags flags
) const {
704 _assert(next_
== NULL
);
713 void CYString::Output(CYOutput
&out
, CYFlags flags
) const {
714 unsigned quot(0), apos(0);
715 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
718 else if (*value
== '\'')
721 bool single(quot
> apos
);
723 std::ostringstream str
;
725 str
<< (single
? '\'' : '"');
726 for (const char *value(value_
), *end(value_
+ size_
); value
!= end
; ++value
)
728 case '\\': str
<< "\\\\"; break;
729 case '\b': str
<< "\\b"; break;
730 case '\f': str
<< "\\f"; break;
731 case '\n': str
<< "\\n"; break;
732 case '\r': str
<< "\\r"; break;
733 case '\t': str
<< "\\t"; break;
734 case '\v': str
<< "\\v"; break;
749 if (*value
< 0x20 || *value
>= 0x7f)
750 str
<< "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value
);
754 str
<< (single
? '\'' : '"');
756 out
<< str
.str().c_str();
759 void CYString::PropertyName(CYOutput
&out
) const {
760 if (const char *word
= Word())
766 static const char *Reserved_
[] = {
767 "false", "null", "true",
769 "break", "case", "catch", "continue", "default",
770 "delete", "do", "else", "finally", "for", "function",
771 "if", "in", "instanceof", "new", "return", "switch",
772 "this", "throw", "try", "typeof", "var", "void",
777 "class", "enum", "export", "extends", "import", "super",
779 "abstract", "boolean", "byte", "char", "double", "final",
780 "float", "goto", "int", "long", "native", "short",
781 "synchronized", "throws", "transient", "volatile",
790 const char *CYString::Word() const {
791 if (size_
== 0 || !WordStartRange_
[value_
[0]])
793 for (size_t i(1); i
!= size_
; ++i
)
794 if (!WordEndRange_
[value_
[i
]])
796 const char *value(Value());
797 for (const char **reserved(Reserved_
); *reserved
!= NULL
; ++reserved
)
798 if (strcmp(*reserved
, value
) == 0)
803 void CYSwitch::Output(CYOutput
&out
, CYFlags flags
) const {
804 out
<< "switch" << ' ' << '(' << *value_
<< ')' << ' ' << '{';
809 void CYThis::Output(CYOutput
&out
, CYFlags flags
) const {
813 void CYThrow::Output(CYOutput
&out
, CYFlags flags
) const {
816 out
<< ' ' << *value_
;
820 void CYTry::Output(CYOutput
&out
, CYFlags flags
) const {
821 out
<< "try" << ' ' << code_
<< catch_
<< finally_
;
824 void CYVar::Output(CYOutput
&out
, CYFlags flags
) const {
826 declarations_
->Output(out
, flags
);
830 void CYVariable::Output(CYOutput
&out
, CYFlags flags
) const {
834 void CYWhile::Output(CYOutput
&out
, CYFlags flags
) const {
835 out
<< "while" << '(' << *test_
<< ')';
836 code_
->Single(out
, CYRight(flags
));
839 void CYWith::Output(CYOutput
&out
, CYFlags flags
) const {
840 out
<< "with" << '(' << *scope_
<< ')';
841 code_
->Single(out
, CYRight(flags
));
844 void CYWord::ClassName(CYOutput
&out
, bool object
) const {
846 out
<< "objc_getClass(";
847 out
<< '"' << Value() << '"';
852 void CYWord::Output(CYOutput
&out
) const {
856 void CYWord::PropertyName(CYOutput
&out
) const {