]> git.saurik.com Git - cycript.git/blame - Output.cpp
Solve a corner case of dealloc hooking on JS derived class objects using MobileSubstrate.
[cycript.git] / Output.cpp
CommitLineData
5999c315
JF
1#include "Parser.hpp"
2
3#include <iostream>
4#include <iomanip>
5
4afefdd9
JF
6#include <objc/runtime.h>
7#include <sstream>
8
b09da87b
JF
9_finline CYFlags operator ~(CYFlags rhs) {
10 return static_cast<CYFlags>(~static_cast<unsigned>(rhs));
11}
12
13_finline CYFlags operator &(CYFlags lhs, CYFlags rhs) {
14 return static_cast<CYFlags>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs));
15}
16
17_finline CYFlags operator |(CYFlags lhs, CYFlags rhs) {
18 return static_cast<CYFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs));
19}
20
21_finline CYFlags &operator |=(CYFlags &lhs, CYFlags rhs) {
22 return lhs = lhs | rhs;
23}
24
25_finline CYFlags CYLeft(CYFlags flags) {
26 return flags & ~CYNoTrailer;
27}
28
29_finline CYFlags CYCenter(CYFlags flags) {
30 return flags & CYNoIn;
31}
32
33_finline CYFlags CYRight(CYFlags flags) {
34 return flags & (CYNoIn | CYNoTrailer);
35}
36
37bool CYFalse::Value() const {
38 return false;
39}
40
41bool CYTrue::Value() const {
42 return true;
43}
44
d35a3b07
JF
45#define CYPA 16
46
b09da87b
JF
47void CYAddressOf::Output(std::ostream &out, CYFlags flags) const {
48 rhs_->Output(out, 1, CYLeft(flags));
283e7e33 49 out << ".addressOf()";
5999c315
JF
50}
51
d35a3b07
JF
52void CYArgument::Output(std::ostream &out) const {
53 if (name_ != NULL) {
5999c315
JF
54 out << *name_;
55 if (value_ != NULL)
56 out << ":";
57 }
d35a3b07 58 if (value_ != NULL)
b09da87b 59 value_->Output(out, CYPA, CYNoFlags);
5999c315 60 if (next_ != NULL) {
d35a3b07
JF
61 if (next_->name_ == NULL)
62 out << ',';
63 else
64 out << ' ';
65 next_->Output(out);
5999c315
JF
66 }
67}
68
b09da87b 69void CYArray::Output(std::ostream &out, CYFlags flags) const {
5befe15e
JF
70 out << '[';
71 if (elements_ != NULL)
72 elements_->Output(out);
73 out << ']';
74}
75
b09da87b
JF
76void CYAssignment::Output(std::ostream &out, CYFlags flags) const {
77 lhs_->Output(out, Precedence() - 1, CYLeft(flags));
d35a3b07 78 out << Operator();
b09da87b 79 rhs_->Output(out, Precedence(), CYRight(flags));
d35a3b07
JF
80}
81
b09da87b
JF
82void CYBoolean::Output(std::ostream &out, CYFlags flags) const {
83 if ((flags & CYNoLeader) != 0)
84 out << ' ';
5999c315 85 out << (Value() ? "true" : "false");
b09da87b
JF
86 if ((flags & CYNoTrailer) != 0)
87 out << ' ';
5999c315
JF
88}
89
90void CYBreak::Output(std::ostream &out) const {
91 out << "break";
92 if (label_ != NULL)
93 out << ' ' << *label_;
94 out << ';';
95}
96
b09da87b
JF
97void CYCall::Output(std::ostream &out, CYFlags flags) const {
98 function_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 99 out << '(';
5999c315 100 if (arguments_ != NULL)
d35a3b07 101 arguments_->Output(out);
5999c315
JF
102 out << ')';
103}
104
105void CYCatch::Output(std::ostream &out) const {
106 out << "catch(" << *name_ << ')';
107 code_->Output(out, true);
108}
109
b09da87b
JF
110void CYClass::Output(std::ostream &out) const {
111 out << "(function($cys,$cyc,$cym,$cyn,$cyt){";
112 out << "$cyc=objc_allocateClassPair($cys,\"" << *name_ << "\",0);";
113 out << "$cym=object_getClass($cyc);";
114 if (fields_ != NULL)
115 fields_->Output(out);
116 if (messages_ != NULL)
117 messages_->Output(out);
118 out << "objc_registerClassPair($cyc);";
119 out << "})(";
120 if (super_ != NULL)
121 super_->Output(out, CYPA, CYNoFlags);
122 else
123 out << "null";
124 out << ");";
125}
126
127void CYCondition::Output(std::ostream &out, CYFlags flags) const {
128 test_->Output(out, Precedence() - 1, CYLeft(flags));
d35a3b07 129 out << '?';
5999c315 130 if (true_ != NULL)
b09da87b 131 true_->Output(out, CYPA, CYNoFlags);
d35a3b07 132 out << ':';
b09da87b 133 false_->Output(out, CYPA, CYRight(flags));
5999c315
JF
134}
135
136void CYContinue::Output(std::ostream &out) const {
137 out << "continue";
138 if (label_ != NULL)
139 out << ' ' << *label_;
140 out << ';';
141}
142
143void CYClause::Output(std::ostream &out) const {
d35a3b07
JF
144 if (case_ != NULL) {
145 out << "case";
b09da87b 146 case_->Output(out, CYNoFlags);
d35a3b07 147 } else
5999c315
JF
148 out << "default";
149 out << ':';
150 if (code_ != NULL)
151 code_->Output(out, false);
152 out << *next_;
153}
154
b09da87b 155// XXX: deal with NoIn
5999c315
JF
156void CYDeclaration::Part(std::ostream &out) const {
157 out << "var ";
158 Output(out);
159}
160
161void CYDeclaration::Output(std::ostream &out) const {
162 out << *identifier_;
d35a3b07
JF
163 if (initialiser_ != NULL) {
164 out << '=';
b09da87b 165 initialiser_->Output(out, CYPA, CYNoFlags);
d35a3b07 166 }
5999c315
JF
167}
168
b09da87b 169// XXX: deal with NoIn
5999c315
JF
170void CYDeclarations::Part(std::ostream &out) const {
171 out << "var ";
d35a3b07 172
5999c315 173 const CYDeclarations *declaration(this);
d35a3b07
JF
174 output:
175 out << *declaration->declaration_;
176 declaration = declaration->next_;
177
178 if (declaration != NULL) {
179 out << ',';
180 goto output;
181 }
5999c315
JF
182}
183
184void CYDeclarations::Output(std::ostream &out) const {
185 Part(out);
186 out << ';';
187}
188
189void CYDoWhile::Output(std::ostream &out) const {
b09da87b 190 // XXX: extra space character!
5999c315
JF
191 out << "do ";
192 code_->Output(out, false);
d35a3b07 193 out << "while(";
b09da87b
JF
194 test_->Output(out, CYNoFlags);
195 out << ')';
5999c315
JF
196}
197
5befe15e 198void CYElement::Output(std::ostream &out) const {
5999c315 199 if (value_ != NULL)
b09da87b 200 value_->Output(out, CYPA, CYNoFlags);
5befe15e 201 if (next_ != NULL || value_ == NULL)
5999c315 202 out << ',';
5befe15e
JF
203 if (next_ != NULL)
204 next_->Output(out);
5999c315
JF
205}
206
207void CYEmpty::Output(std::ostream &out) const {
208 out << ';';
209}
210
211void CYEmpty::Output(std::ostream &out, bool block) const {
212 if (next_ != NULL)
213 CYSource::Output(out, block);
214 else
215 out << "{}";
216}
217
218void CYExpress::Output(std::ostream &out) const {
b09da87b 219 expression_->Output(out, CYNoFunction | CYNoBrace);
5999c315
JF
220 out << ';';
221}
222
223void CYExpression::Part(std::ostream &out) const {
d35a3b07 224 // XXX: this should handle LeftHandSideExpression
b09da87b 225 Output(out, CYNoIn);
d35a3b07
JF
226}
227
b09da87b 228void CYCompound::Output(std::ostream &out, CYFlags flags) const {
d35a3b07 229 if (CYExpression *expression = expressions_)
478d4ed0 230 if (CYExpression *next = expression->next_) {
b09da87b
JF
231 expression->Output(out, CYLeft(flags));
232 CYFlags center(CYCenter(flags));
233 while (next != NULL) {
478d4ed0 234 expression = next;
b09da87b
JF
235 out << ',';
236 next = expression->next_;
237 CYFlags right(next != NULL ? center : CYRight(flags));
238 expression->Output(out, right);
239 }
478d4ed0
JF
240 } else
241 expression->Output(out, flags);
5999c315
JF
242}
243
b09da87b
JF
244void CYExpression::Output(std::ostream &out, unsigned precedence, CYFlags flags) const {
245 if (precedence < Precedence()) {
5999c315 246 out << '(';
b09da87b 247 Output(out, CYNoFlags);
5999c315 248 out << ')';
b09da87b
JF
249 } else
250 Output(out, flags);
251}
252
253void CYField::Output(std::ostream &out) const {
254 // XXX: implement!
5999c315
JF
255}
256
257void CYFor::Output(std::ostream &out) const {
258 out << "for(";
259 if (initialiser_ != NULL)
260 initialiser_->Part(out);
261 out << ';';
262 if (test_ != NULL)
b09da87b 263 test_->Output(out, CYNoFlags);
5999c315
JF
264 out << ';';
265 if (increment_ != NULL)
b09da87b 266 increment_->Output(out, CYNoFlags);
5999c315
JF
267 out << ')';
268 code_->Output(out, false);
269}
270
271void CYForIn::Output(std::ostream &out) const {
272 out << "for(";
273 initialiser_->Part(out);
b09da87b
JF
274 // XXX: deal with this space character!
275 out << ' ';
276 out << "in";
277 set_->Output(out, CYNoLeader);
5999c315
JF
278 out << ')';
279 code_->Output(out, false);
280}
281
282void CYFunction::Output(std::ostream &out) const {
b09da87b
JF
283 CYLambda::Output(out, CYNoFlags);
284}
285
286void CYFunctionParameter::Output(std::ostream &out) const {
287 out << *name_;
288 if (next_ != NULL) {
289 out << ',';
290 out << *next_;
291 }
5999c315
JF
292}
293
294void CYIf::Output(std::ostream &out) const {
d35a3b07 295 out << "if(";
b09da87b 296 test_->Output(out, CYNoFlags);
d35a3b07 297 out << ')';
5999c315
JF
298 true_->Output(out, true);
299 if (false_ != NULL) {
300 out << "else ";
301 false_->Output(out, false);
302 }
303}
304
b09da87b
JF
305void CYIndirect::Output(std::ostream &out, CYFlags flags) const {
306 rhs_->Output(out, 1, CYLeft(flags));
d35a3b07 307 out << "[0]";
5999c315
JF
308}
309
b09da87b
JF
310void CYInfix::Output(std::ostream &out, CYFlags flags) const {
311 const char *name(Operator());
312 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in"));
313 if (protect)
314 out << '(';
315 bool alphabetic(Alphabetic());
316 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
317 if (alphabetic)
318 left |= CYNoTrailer;
319 lhs_->Output(out, Precedence(), left);
320 out << name;
321 CYFlags right(protect ? CYNoFlags : CYRight(flags));
322 if (alphabetic)
323 right |= CYNoLeader;
324 rhs_->Output(out, Precedence() - 1, right);
325 if (protect)
326 out << ')';
5999c315
JF
327}
328
b09da87b
JF
329void CYLambda::Output(std::ostream &out, CYFlags flags) const {
330 bool protect((flags & CYNoFunction) != 0);
331 if (protect)
332 out << '(';
5999c315
JF
333 out << "function";
334 if (name_ != NULL)
335 out << ' ' << *name_;
336 out << '(';
337 if (parameters_ != NULL)
338 out << *parameters_;
b09da87b
JF
339 out << "){";
340 if (body_ != NULL)
341 body_->Show(out);
342 out << '}';
343 if (protect)
344 out << ')';
5999c315
JF
345}
346
b09da87b
JF
347void CYMember::Output(std::ostream &out, CYFlags flags) const {
348 object_->Output(out, Precedence(), CYLeft(flags));
dea834b0
JF
349 if (const char *word = property_->Word())
350 out << '.' << word;
351 else {
352 out << '[';
b09da87b 353 property_->Output(out, CYNoFlags);
dea834b0
JF
354 out << ']';
355 }
5999c315
JF
356}
357
358void CYMessage::Output(std::ostream &out) const {
4e8c99fb
JF
359 if (next_ != NULL)
360 next_->Output(out);
b09da87b
JF
361 out << "$cyn=new Selector(\"";
362 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
363 if (parameter->tag_ != NULL) {
364 out << *parameter->tag_;
365 if (parameter->name_ != NULL)
5999c315
JF
366 out << ':';
367 }
b09da87b
JF
368 out << "\");";
369 out << "$cyt=$cyn.type($cys," << (instance_ ? "true" : "false") << ");";
370 out << "class_addMethod($cy" << (instance_ ? 'c' : 'm') << ",$cyn,";
478d4ed0 371 out << "new Functor(function(self,_cmd";
b09da87b 372 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
478d4ed0
JF
373 if (parameter->name_ != NULL)
374 out << ',' << *parameter->name_;
375 out << "){return function(){";
b09da87b
JF
376 if (body_ != NULL)
377 body_->Show(out);
478d4ed0 378 out << "}.call(self);},$cyt),$cyt);";
5999c315
JF
379}
380
b09da87b 381void CYNew::Output(std::ostream &out, CYFlags flags) const {
d35a3b07 382 out << "new";
b09da87b 383 constructor_->Output(out, Precedence(), CYCenter(flags) | CYNoLeader);
d35a3b07 384 out << '(';
5999c315 385 if (arguments_ != NULL)
d35a3b07 386 arguments_->Output(out);
5999c315
JF
387 out << ')';
388}
389
b09da87b
JF
390void CYNull::Output(std::ostream &out, CYFlags flags) const {
391 if ((flags & CYNoLeader) != 0)
392 out << ' ';
5999c315 393 CYWord::Output(out);
b09da87b
JF
394 if ((flags & CYNoTrailer) != 0)
395 out << ' ';
5999c315
JF
396}
397
b09da87b
JF
398void CYNumber::Output(std::ostream &out, CYFlags flags) const {
399 if ((flags & CYNoLeader) != 0)
400 out << ' ';
5999c315
JF
401 // XXX: this is not a useful formatting
402 out << Value();
b09da87b
JF
403 if ((flags & CYNoTrailer) != 0)
404 out << ' ';
5999c315
JF
405}
406
b09da87b
JF
407void CYObject::Output(std::ostream &out, CYFlags flags) const {
408 bool protect((flags & CYNoBrace) != 0);
409 if (protect)
410 out << '(';
693d501b
JF
411 out << '{';
412 if (property_ != NULL)
413 property_->Output(out);
414 out << '}';
b09da87b
JF
415 if (protect)
416 out << ')';
693d501b
JF
417}
418
b09da87b
JF
419void CYPostfix::Output(std::ostream &out, CYFlags flags) const {
420 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 421 out << Operator();
5999c315
JF
422}
423
b09da87b
JF
424void CYPrefix::Output(std::ostream &out, CYFlags flags) const {
425 bool alphabetic(Alphabetic());
d35a3b07 426 out << Operator();
b09da87b
JF
427 CYFlags right(CYRight(flags));
428 if (alphabetic)
429 right |= CYNoLeader;
430 rhs_->Output(out, Precedence(), right);
5999c315
JF
431}
432
693d501b 433void CYProperty::Output(std::ostream &out) const {
579ed526
JF
434 out << *name_;
435 out << ':';
b09da87b 436 value_->Output(out, CYPA, CYNoFlags);
5999c315
JF
437 if (next_ != NULL) {
438 out << ',';
693d501b 439 next_->Output(out);
5999c315 440 }
5999c315
JF
441}
442
443void CYReturn::Output(std::ostream &out) const {
444 out << "return";
b09da87b
JF
445 if (value_ != NULL)
446 value_->Output(out, CYNoLeader);
5999c315
JF
447 out << ';';
448}
449
b09da87b
JF
450void CYSelector::Output(std::ostream &out, CYFlags flags) const {
451 out << "new Selector(\"";
62014ea9
JF
452 if (name_ != NULL)
453 name_->Output(out);
dea834b0 454 out << "\")";
e7ed5354
JF
455}
456
62014ea9
JF
457void CYSelectorPart::Output(std::ostream &out) const {
458 if (name_ != NULL)
459 out << *name_;
460 if (value_)
461 out << ':';
462 if (next_ != NULL)
463 next_->Output(out);
464}
465
b09da87b
JF
466void CYSend::Output(std::ostream &out, CYFlags flags) const {
467 out << "objc_msgSend(";
468 self_->Output(out, CYPA, CYNoFlags);
4afefdd9
JF
469 out << ",";
470 std::ostringstream name;
b09da87b
JF
471 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
472 if (argument->name_ != NULL) {
4afefdd9 473 name << *argument->name_;
b09da87b 474 if (argument->value_ != NULL)
4afefdd9 475 name << ':';
b09da87b 476 }
4afefdd9 477 out << reinterpret_cast<void *>(sel_registerName(name.str().c_str()));
b09da87b
JF
478 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
479 if (argument->value_ != NULL) {
480 out << ",";
481 argument->value_->Output(out, CYPA, CYNoFlags);
482 }
483 out << ')';
484}
485
b1ff2d78 486void CYSource::Show(std::ostream &out) const {
5999c315 487 for (const CYSource *next(this); next != NULL; next = next->next_)
b09da87b 488 next->Output(out);
5999c315
JF
489}
490
491void CYSource::Output(std::ostream &out, bool block) const {
492 if (!block && next_ == NULL)
493 Output(out);
494 else {
495 out << '{';
b1ff2d78 496 Show(out);
5999c315
JF
497 out << '}';
498 }
499}
500
b09da87b 501void CYString::Output(std::ostream &out, CYFlags flags) const {
b4aa79af
JF
502 unsigned quot(0), apos(0);
503 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
504 if (*value == '"')
505 ++quot;
506 else if (*value == '\'')
507 ++apos;
508
509 bool single(quot > apos);
510
511 out << (single ? '\'' : '"');
5999c315
JF
512 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
513 switch (*value) {
5999c315
JF
514 case '\\': out << "\\\\"; break;
515 case '\b': out << "\\b"; break;
516 case '\f': out << "\\f"; break;
517 case '\n': out << "\\n"; break;
518 case '\r': out << "\\r"; break;
519 case '\t': out << "\\t"; break;
520 case '\v': out << "\\v"; break;
521
b4aa79af
JF
522 case '"':
523 if (!single)
524 out << "\\\"";
525 else goto simple;
526 break;
527
528 case '\'':
529 if (single)
530 out << "\\'";
531 else goto simple;
532 break;
533
5999c315
JF
534 default:
535 if (*value < 0x20 || *value >= 0x7f)
536 out << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value);
b4aa79af 537 else simple:
5999c315
JF
538 out << *value;
539 }
b4aa79af 540 out << (single ? '\'' : '"');
5999c315
JF
541}
542
543void CYSwitch::Output(std::ostream &out) const {
d35a3b07 544 out << "switch(";
b09da87b 545 value_->Output(out, CYNoFlags);
d35a3b07 546 out << "){";
5999c315
JF
547 if (clauses_ != NULL)
548 out << *clauses_;
549 out << '}';
550}
551
b09da87b
JF
552void CYThis::Output(std::ostream &out, CYFlags flags) const {
553 if ((flags & CYNoLeader) != 0)
554 out << ' ';
5999c315 555 CYWord::Output(out);
b09da87b
JF
556 if ((flags & CYNoTrailer) != 0)
557 out << ' ';
5999c315
JF
558}
559
560void CYThrow::Output(std::ostream &out) const {
d35a3b07 561 out << "throw";
b09da87b
JF
562 if (value_ != NULL)
563 value_->Output(out, CYNoLeader);
5999c315
JF
564 out << ';';
565}
566
567void CYTry::Output(std::ostream &out) const {
568 out << "try";
569 try_->Output(out, true);
570 if (catch_ != NULL)
571 out << catch_;
572 if (finally_ != NULL) {
573 out << "finally";
574 finally_->Output(out, true);
575 }
576}
577
b09da87b 578void CYVariable::Output(std::ostream &out, CYFlags flags) const {
478d4ed0
JF
579 if ((flags & CYNoLeader) != 0)
580 out << ' ';
5999c315 581 out << *name_;
478d4ed0
JF
582 if ((flags & CYNoTrailer) != 0)
583 out << ' ';
5999c315
JF
584}
585
586void CYWhile::Output(std::ostream &out) const {
d35a3b07 587 out << "while(";
b09da87b 588 test_->Output(out, CYNoFlags);
d35a3b07 589 out << ')';
5999c315
JF
590 code_->Output(out, false);
591}
592
593void CYWith::Output(std::ostream &out) const {
d35a3b07 594 out << "with(";
b09da87b 595 scope_->Output(out, CYNoFlags);
d35a3b07 596 out << ')';
5999c315
JF
597 code_->Output(out, false);
598}
599
600void CYWord::Output(std::ostream &out) const {
601 out << Value();
602}