]> git.saurik.com Git - cycript.git/blob - Output.cpp
Moved from plist files to sqlite3 and finalized non-ObjectiveC compile of Library.mm.
[cycript.git] / Output.cpp
1 /* Cycript - Remove Execution Server and Disassembler
2 * Copyright (C) 2009 Jay Freeman (saurik)
3 */
4
5 /* Modified BSD License {{{ */
6 /*
7 * Redistribution and use in source and binary
8 * forms, with or without modification, are permitted
9 * provided that the following conditions are met:
10 *
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
18 * distribution.
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.
22 *
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.
37 */
38 /* }}} */
39
40 #include "cycript.hpp"
41 #include "Parser.hpp"
42
43 #include <sstream>
44
45 _finline CYFlags operator ~(CYFlags rhs) {
46 return static_cast<CYFlags>(~static_cast<unsigned>(rhs));
47 }
48
49 _finline CYFlags operator &(CYFlags lhs, CYFlags rhs) {
50 return static_cast<CYFlags>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs));
51 }
52
53 _finline CYFlags operator |(CYFlags lhs, CYFlags rhs) {
54 return static_cast<CYFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs));
55 }
56
57 _finline CYFlags &operator |=(CYFlags &lhs, CYFlags rhs) {
58 return lhs = lhs | rhs;
59 }
60
61 _finline CYFlags CYLeft(CYFlags flags) {
62 return flags & ~CYNoDangle;
63 }
64
65 _finline CYFlags CYRight(CYFlags flags) {
66 return flags & ~CYNoBF;
67 }
68
69 _finline CYFlags CYCenter(CYFlags flags) {
70 return CYLeft(CYRight(flags));
71 }
72
73 void CYOutput::Terminate() {
74 out_ << ';';
75 mode_ = NoMode;
76 }
77
78 CYOutput &CYOutput::operator <<(char rhs) {
79 if (rhs == ' ' || rhs == '\n')
80 if (pretty_)
81 out_ << rhs;
82 else goto done;
83 else if (rhs == '\t')
84 if (pretty_)
85 for (unsigned i(0); i != indent_; ++i)
86 out_ << " ";
87 else goto done;
88 else goto work;
89
90 mode_ = NoMode;
91 goto done;
92
93 work:
94 if (mode_ == Terminated && rhs != '}')
95 out_ << ';';
96
97 if (rhs == ';') {
98 if (pretty_)
99 goto none;
100 else {
101 mode_ = Terminated;
102 goto done;
103 }
104 } else if (rhs == '+') {
105 if (mode_ == NoPlus)
106 out_ << ' ';
107 mode_ = NoPlus;
108 } else if (rhs == '-') {
109 if (mode_ == NoHyphen)
110 out_ << ' ';
111 mode_ = NoHyphen;
112 } else if (WordEndRange_[rhs]) {
113 if (mode_ == NoLetter)
114 out_ << ' ';
115 mode_ = NoLetter;
116 } else none:
117 mode_ = NoMode;
118
119 out_ << rhs;
120 done:
121 return *this;
122 }
123
124 CYOutput &CYOutput::operator <<(const char *rhs) {
125 size_t size(strlen(rhs));
126
127 if (size == 1)
128 return *this << *rhs;
129
130 if (mode_ == Terminated)
131 out_ << ';';
132 else if (
133 mode_ == NoPlus && *rhs == '+' ||
134 mode_ == NoHyphen && *rhs == '-' ||
135 mode_ == NoLetter && WordEndRange_[*rhs]
136 )
137 out_ << ' ';
138
139 if (WordEndRange_[rhs[size - 1]])
140 mode_ = NoLetter;
141 else
142 mode_ = NoMode;
143
144 out_ << rhs;
145 return *this;
146 }
147
148 void CYArgument::Output(CYOutput &out) const {
149 if (name_ != NULL) {
150 out << *name_;
151 if (value_ != NULL)
152 out << ':' << ' ';
153 }
154 if (value_ != NULL)
155 value_->Output(out, CYPA, CYNoFlags);
156 if (next_ != NULL) {
157 if (next_->name_ == NULL)
158 out << ',';
159 out << ' ' << *next_;
160 }
161 }
162
163 void CYArray::Output(CYOutput &out, CYFlags flags) const {
164 out << '[' << elements_ << ']';
165 }
166
167 void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
168 out << '[' << *expression_ << ' ' << *comprehensions_ << ']';
169 }
170
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));
175 }
176
177 void CYBlock::Output(CYOutput &out) const {
178 out << '{' << '\n';
179 ++out.indent_;
180 if (statements_ != NULL)
181 statements_->Multiple(out);
182 --out.indent_;
183 out << '\t' << '}';
184 }
185
186 void CYBlock::Output(CYOutput &out, CYFlags flags) const {
187 if (statements_ == NULL)
188 out.Terminate();
189 else if (statements_->next_ == NULL)
190 statements_->Single(out, flags);
191 else
192 Output(out);
193 }
194
195 void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
196 out << (Value() ? "true" : "false");
197 }
198
199 void CYBreak::Output(CYOutput &out, CYFlags flags) const {
200 out << "break";
201 if (label_ != NULL)
202 out << ' ' << *label_;
203 out << ';';
204 }
205
206 void CYCall::Output(CYOutput &out, CYFlags flags) const {
207 bool protect((flags & CYNoCall) != 0);
208 if (protect)
209 out << '(';
210 function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
211 out << '(' << arguments_ << ')';
212 if (protect)
213 out << ')';
214 }
215
216 void CYCatch::Output(CYOutput &out) const {
217 out << ' ' << "catch" << ' ' << '(' << *name_ << ')' << ' ' << code_;
218 }
219
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) {
226 expression = next;
227 out << ',' << ' ';
228 next = expression->next_;
229 CYFlags right(next != NULL ? center : CYRight(flags));
230 expression->Output(out, right);
231 }
232 } else
233 expression->Output(out, flags);
234 }
235
236 void CYCondition::Output(CYOutput &out, CYFlags flags) const {
237 test_->Output(out, Precedence() - 1, CYLeft(flags));
238 out << ' ' << '?' << ' ';
239 if (true_ != NULL)
240 true_->Output(out, CYPA, CYNoFlags);
241 out << ' ' << ':' << ' ';
242 false_->Output(out, CYPA, CYRight(flags));
243 }
244
245 void CYContinue::Output(CYOutput &out, CYFlags flags) const {
246 out << "continue";
247 if (label_ != NULL)
248 out << ' ' << *label_;
249 out << ';';
250 }
251
252 void CYClause::Output(CYOutput &out) const {
253 if (case_ != NULL)
254 out << "case" << ' ' << *case_;
255 else
256 out << "default";
257 out << ':' << '\n';
258 if (statements_ != NULL)
259 statements_->Multiple(out);
260 out << next_;
261 }
262
263 const char *CYDeclaration::ForEachIn() const {
264 return identifier_->Value();
265 }
266
267 void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
268 out << "var";
269 Output(out, CYRight(flags));
270 }
271
272 void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
273 out << *identifier_;
274 if (initialiser_ != NULL) {
275 out << ' ' << '=' << ' ';
276 initialiser_->Output(out, CYPA, CYRight(flags));
277 }
278 }
279
280 void CYDeclarations::For(CYOutput &out) const {
281 out << "var";
282 Output(out, CYNoIn);
283 }
284
285 void CYDeclarations::Output(CYOutput &out) const {
286 Output(out, CYNoFlags);
287 }
288
289 void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
290 const CYDeclarations *declaration(this);
291 bool first(true);
292 output:
293 CYDeclarations *next(declaration->next_);
294 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
295 first = false;
296 declaration->declaration_->Output(out, jacks);
297
298 if (next != NULL) {
299 out << ',' << ' ';
300 declaration = next;
301 goto output;
302 }
303 }
304
305 void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
306 object_->Output(out, Precedence(), CYLeft(flags));
307 if (const char *word = property_->Word())
308 out << '.' << word;
309 else
310 out << '[' << *property_ << ']';
311 }
312
313 void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
314 out << "do";
315 code_->Single(out, CYCenter(flags));
316 out << "while" << ' ' << '(' << *test_ << ')';
317 }
318
319 void CYElement::Output(CYOutput &out) const {
320 if (value_ != NULL)
321 value_->Output(out, CYPA, CYNoFlags);
322 if (next_ != NULL || value_ == NULL) {
323 out << ',';
324 if (next_ != NULL && next_->value_ != NULL)
325 out << ' ';
326 }
327 if (next_ != NULL)
328 next_->Output(out);
329 }
330
331 void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
332 out.Terminate();
333 }
334
335 void CYExpress::Output(CYOutput &out, CYFlags flags) const {
336 expression_->Output(out, flags | CYNoBF);
337 out << ';';
338 }
339
340 void CYExpression::ClassName(CYOutput &out, bool object) const {
341 Output(out, CYPA, CYNoFlags);
342 }
343
344 const char *CYExpression::ForEachIn() const {
345 return NULL;
346 }
347
348 void CYExpression::For(CYOutput &out) const {
349 Output(out, CYNoIn);
350 }
351
352 void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
353 Output(out, flags | CYNoRightHand);
354 }
355
356 void CYExpression::Output(CYOutput &out) const {
357 Output(out, CYNoFlags);
358 }
359
360 void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const {
361 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
362 out << '(' << *this << ')';
363 else
364 Output(out, flags);
365 }
366
367 void CYFinally::Output(CYOutput &out) const {
368 out << ' ' << "finally" << ' ' << code_;
369 }
370
371 void CYFor::Output(CYOutput &out, CYFlags flags) const {
372 out << "for" << ' ' << '(';
373 if (initialiser_ != NULL)
374 initialiser_->For(out);
375 out.Terminate();
376 out << test_;
377 out.Terminate();
378 out << increment_;
379 out << ')';
380 code_->Single(out, CYRight(flags));
381 }
382
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));
388 }
389
390 void CYForEachInComprehension::Output(CYOutput &out) const {
391 out << "for" << ' ' << "each" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')' << next_;
392 }
393
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));
399 }
400
401 void CYForInComprehension::Output(CYOutput &out) const {
402 out << "for" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')';
403 }
404
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);
408 if (protect)
409 out << '(';
410 out << "function";
411 if (name_ != NULL)
412 out << ' ' << *name_;
413 out << '(' << parameters_ << ')';
414 out << ' ' << code_;
415 if (protect)
416 out << ')';
417 }
418
419 void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
420 CYFunction::Output(out, flags);
421 }
422
423 void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
424 CYFunction::Output(out, flags);
425 }
426
427 void CYFunctionParameter::Output(CYOutput &out) const {
428 out << *name_;
429 if (next_ != NULL)
430 out << ',' << ' ' << *next_;
431 }
432
433 void CYIf::Output(CYOutput &out, CYFlags flags) const {
434 bool protect(false);
435 if (false_ == NULL && (flags & CYNoDangle) != 0) {
436 protect = true;
437 out << '{';
438 }
439
440 out << "if" << ' ' << '(' << *test_ << ')';
441
442 CYFlags right(protect ? CYNoFlags : CYRight(flags));
443
444 CYFlags jacks(CYNoDangle);
445 if (false_ == NULL)
446 jacks |= right;
447 else
448 jacks |= protect ? CYNoFlags : CYCenter(flags);
449
450 true_->Single(out, jacks);
451
452 if (false_ != NULL) {
453 out << "else";
454 false_->Single(out, right);
455 }
456
457 if (protect)
458 out << '}';
459 }
460
461 void CYIfComprehension::Output(CYOutput &out) const {
462 out << "if" << ' ' << '(' << *test_ << ')' << next_;
463 }
464
465 void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
466 object_->Output(out, Precedence(), CYLeft(flags));
467 if (const char *word = property_->Word())
468 out << "->" << word;
469 else
470 out << "->" << '[' << *property_ << ']';
471 }
472
473 void CYInfix::Output(CYOutput &out, CYFlags flags) const {
474 const char *name(Operator());
475 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
476 if (protect)
477 out << '(';
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);
483 if (protect)
484 out << ')';
485 }
486
487 void CYLabel::Output(CYOutput &out, CYFlags flags) const {
488 out << *name_ << ':' << ' ';
489 statement_->Single(out, CYRight(flags));
490 }
491
492 void CYLet::Output(CYOutput &out, CYFlags flags) const {
493 out << "let" << ' ' << '(' << *declarations_ << ')' << ' ' << code_;
494 }
495
496 void CYNew::Output(CYOutput &out, CYFlags flags) const {
497 out << "new" << ' ';
498 CYFlags jacks(CYNoCall | CYCenter(flags));
499 constructor_->Output(out, Precedence(), jacks);
500 if (arguments_ != NULL)
501 out << '(' << *arguments_ << ')';
502 }
503
504 void CYNull::Output(CYOutput &out, CYFlags flags) const {
505 CYWord::Output(out);
506 }
507
508 void CYNumber::Output(CYOutput &out, CYFlags flags) const {
509 std::ostringstream str;
510 CYNumerify(str, Value());
511 out << str.str().c_str();
512 }
513
514 void CYNumber::PropertyName(CYOutput &out) const {
515 Output(out, CYNoFlags);
516 }
517
518 void CYObject::Output(CYOutput &out, CYFlags flags) const {
519 bool protect((flags & CYNoBrace) != 0);
520 if (protect)
521 out << '(';
522 out << '{' << '\n';
523 ++out.indent_;
524 out << properties_;
525 --out.indent_;
526 out << '\t' << '}';
527 if (protect)
528 out << ')';
529 }
530
531 void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
532 lhs_->Output(out, Precedence(), CYLeft(flags));
533 out << Operator();
534 }
535
536 void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
537 const char *name(Operator());
538 out << name;
539 if (Alphabetic())
540 out << ' ';
541 rhs_->Output(out, Precedence(), CYRight(flags));
542 }
543
544 void CYProgram::Output(CYOutput &out) const {
545 if (statements_ != NULL)
546 statements_->Multiple(out);
547 }
548
549 void CYProperty::Output(CYOutput &out) const {
550 out << '\t';
551 name_->PropertyName(out);
552 out << ':' << ' ';
553 value_->Output(out, CYPA, CYNoFlags);
554 if (next_ != NULL)
555 out << ',' << '\n' << *next_;
556 else
557 out << '\n';
558 }
559
560 void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
561 out << Value();
562 }
563
564 void CYReturn::Output(CYOutput &out, CYFlags flags) const {
565 out << "return";
566 if (value_ != NULL)
567 out << ' ' << *value_;
568 out << ';';
569 }
570
571 void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
572 bool first(true);
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));
576 first = false;
577 out << '\t';
578 next->Output(out, jacks);
579 out << '\n';
580 }
581 }
582
583 void CYStatement::Single(CYOutput &out, CYFlags flags) const {
584 _assert(next_ == NULL);
585 out << '\n';
586 ++out.indent_;
587 out << '\t';
588 Output(out, flags);
589 out << '\n';
590 --out.indent_;
591 }
592
593 void CYString::Output(CYOutput &out, CYFlags flags) const {
594 std::ostringstream str;
595 CYStringify(str, value_, size_);
596 out << str.str().c_str();
597 }
598
599 void CYString::PropertyName(CYOutput &out) const {
600 if (const char *word = Word())
601 out << word;
602 else
603 out << *this;
604 }
605
606 static const char *Reserved_[] = {
607 "false", "null", "true",
608
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",
613 "while", "with",
614
615 "debugger", "const",
616
617 "class", "enum", "export", "extends", "import", "super",
618
619 "abstract", "boolean", "byte", "char", "double", "final",
620 "float", "goto", "int", "long", "native", "short",
621 "synchronized", "throws", "transient", "volatile",
622
623 "let", "yield",
624
625 "each",
626
627 NULL
628 };
629
630 const char *CYString::Word() const {
631 if (size_ == 0 || !WordStartRange_[value_[0]])
632 return NULL;
633 for (size_t i(1); i != size_; ++i)
634 if (!WordEndRange_[value_[i]])
635 return NULL;
636 const char *value(Value());
637 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
638 if (strcmp(*reserved, value) == 0)
639 return NULL;
640 return value;
641 }
642
643 void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
644 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
645 out << clauses_;
646 out << '}';
647 }
648
649 void CYThis::Output(CYOutput &out, CYFlags flags) const {
650 CYWord::Output(out);
651 }
652
653 void CYThrow::Output(CYOutput &out, CYFlags flags) const {
654 out << "throw";
655 if (value_ != NULL)
656 out << ' ' << *value_;
657 out << ';';
658 }
659
660 void CYTry::Output(CYOutput &out, CYFlags flags) const {
661 out << "try" << ' ' << code_ << catch_ << finally_;
662 }
663
664 void CYVar::Output(CYOutput &out, CYFlags flags) const {
665 out << "var";
666 declarations_->Output(out, flags);
667 out << ';';
668 }
669
670 void CYVariable::Output(CYOutput &out, CYFlags flags) const {
671 out << *name_;
672 }
673
674 void CYWhile::Output(CYOutput &out, CYFlags flags) const {
675 out << "while" << '(' << *test_ << ')';
676 code_->Single(out, CYRight(flags));
677 }
678
679 void CYWith::Output(CYOutput &out, CYFlags flags) const {
680 out << "with" << '(' << *scope_ << ')';
681 code_->Single(out, CYRight(flags));
682 }
683
684 void CYWord::ClassName(CYOutput &out, bool object) const {
685 if (object)
686 out << "objc_getClass(";
687 out << '"' << Value() << '"';
688 if (object)
689 out << ')';
690 }
691
692 void CYWord::Output(CYOutput &out) const {
693 out << Value();
694 }
695
696 void CYWord::PropertyName(CYOutput &out) const {
697 Output(out);
698 }