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