]> git.saurik.com Git - cycript.git/blame - Output.cpp
Improved lexical syntax errors and added not-isatty detection for selecting the parse...
[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));
9b5527f0 49 out << ".$cya()";
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
e5bc40db
JF
110void 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
b09da87b 121void CYClass::Output(std::ostream &out) const {
e5bc40db
JF
122 out << "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){";
123 out << "$cyp=object_getClass($cys);";
b09da87b
JF
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)
e5bc40db 129 messages_->Output(out, false);
b09da87b
JF
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
e5bc40db
JF
139void 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
b09da87b
JF
155void CYCondition::Output(std::ostream &out, CYFlags flags) const {
156 test_->Output(out, Precedence() - 1, CYLeft(flags));
d35a3b07 157 out << '?';
5999c315 158 if (true_ != NULL)
b09da87b 159 true_->Output(out, CYPA, CYNoFlags);
d35a3b07 160 out << ':';
b09da87b 161 false_->Output(out, CYPA, CYRight(flags));
5999c315
JF
162}
163
164void CYContinue::Output(std::ostream &out) const {
165 out << "continue";
166 if (label_ != NULL)
167 out << ' ' << *label_;
168 out << ';';
169}
170
171void CYClause::Output(std::ostream &out) const {
d35a3b07
JF
172 if (case_ != NULL) {
173 out << "case";
b09da87b 174 case_->Output(out, CYNoFlags);
d35a3b07 175 } else
5999c315
JF
176 out << "default";
177 out << ':';
178 if (code_ != NULL)
179 code_->Output(out, false);
180 out << *next_;
181}
182
b09da87b 183// XXX: deal with NoIn
5999c315
JF
184void CYDeclaration::Part(std::ostream &out) const {
185 out << "var ";
186 Output(out);
187}
188
189void CYDeclaration::Output(std::ostream &out) const {
190 out << *identifier_;
d35a3b07
JF
191 if (initialiser_ != NULL) {
192 out << '=';
b09da87b 193 initialiser_->Output(out, CYPA, CYNoFlags);
d35a3b07 194 }
5999c315
JF
195}
196
b09da87b 197// XXX: deal with NoIn
5999c315
JF
198void CYDeclarations::Part(std::ostream &out) const {
199 out << "var ";
d35a3b07 200
5999c315 201 const CYDeclarations *declaration(this);
d35a3b07
JF
202 output:
203 out << *declaration->declaration_;
204 declaration = declaration->next_;
205
206 if (declaration != NULL) {
207 out << ',';
208 goto output;
209 }
5999c315
JF
210}
211
212void CYDeclarations::Output(std::ostream &out) const {
213 Part(out);
214 out << ';';
215}
216
9b5527f0
JF
217void 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
5999c315 228void CYDoWhile::Output(std::ostream &out) const {
b09da87b 229 // XXX: extra space character!
5999c315
JF
230 out << "do ";
231 code_->Output(out, false);
d35a3b07 232 out << "while(";
b09da87b
JF
233 test_->Output(out, CYNoFlags);
234 out << ')';
5999c315
JF
235}
236
5befe15e 237void CYElement::Output(std::ostream &out) const {
5999c315 238 if (value_ != NULL)
b09da87b 239 value_->Output(out, CYPA, CYNoFlags);
5befe15e 240 if (next_ != NULL || value_ == NULL)
5999c315 241 out << ',';
5befe15e
JF
242 if (next_ != NULL)
243 next_->Output(out);
5999c315
JF
244}
245
246void CYEmpty::Output(std::ostream &out) const {
247 out << ';';
248}
249
250void CYEmpty::Output(std::ostream &out, bool block) const {
251 if (next_ != NULL)
252 CYSource::Output(out, block);
253 else
254 out << "{}";
255}
256
257void CYExpress::Output(std::ostream &out) const {
b09da87b 258 expression_->Output(out, CYNoFunction | CYNoBrace);
5999c315
JF
259 out << ';';
260}
261
e5bc40db
JF
262void CYExpression::ClassName(std::ostream &out) const {
263 Output(out, CYPA, CYNoFlags);
264}
265
5999c315 266void CYExpression::Part(std::ostream &out) const {
d35a3b07 267 // XXX: this should handle LeftHandSideExpression
b09da87b 268 Output(out, CYNoIn);
d35a3b07
JF
269}
270
b09da87b
JF
271void CYExpression::Output(std::ostream &out, unsigned precedence, CYFlags flags) const {
272 if (precedence < Precedence()) {
5999c315 273 out << '(';
b09da87b 274 Output(out, CYNoFlags);
5999c315 275 out << ')';
b09da87b
JF
276 } else
277 Output(out, flags);
278}
279
280void CYField::Output(std::ostream &out) const {
281 // XXX: implement!
5999c315
JF
282}
283
284void CYFor::Output(std::ostream &out) const {
285 out << "for(";
286 if (initialiser_ != NULL)
287 initialiser_->Part(out);
288 out << ';';
289 if (test_ != NULL)
b09da87b 290 test_->Output(out, CYNoFlags);
5999c315
JF
291 out << ';';
292 if (increment_ != NULL)
b09da87b 293 increment_->Output(out, CYNoFlags);
5999c315
JF
294 out << ')';
295 code_->Output(out, false);
296}
297
298void CYForIn::Output(std::ostream &out) const {
299 out << "for(";
300 initialiser_->Part(out);
b09da87b
JF
301 // XXX: deal with this space character!
302 out << ' ';
303 out << "in";
304 set_->Output(out, CYNoLeader);
5999c315
JF
305 out << ')';
306 code_->Output(out, false);
307}
308
309void CYFunction::Output(std::ostream &out) const {
b09da87b
JF
310 CYLambda::Output(out, CYNoFlags);
311}
312
313void CYFunctionParameter::Output(std::ostream &out) const {
314 out << *name_;
315 if (next_ != NULL) {
316 out << ',';
317 out << *next_;
318 }
5999c315
JF
319}
320
321void CYIf::Output(std::ostream &out) const {
d35a3b07 322 out << "if(";
b09da87b 323 test_->Output(out, CYNoFlags);
d35a3b07 324 out << ')';
5999c315
JF
325 true_->Output(out, true);
326 if (false_ != NULL) {
327 out << "else ";
328 false_->Output(out, false);
329 }
330}
331
b09da87b
JF
332void CYIndirect::Output(std::ostream &out, CYFlags flags) const {
333 rhs_->Output(out, 1, CYLeft(flags));
9b5527f0
JF
334 out << ".$cyi";
335}
336
337void 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 }
5999c315
JF
347}
348
b09da87b
JF
349void 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;
1ef7d061
JF
363 if (strcmp(name, "-") == 0)
364 right |= CYNoHyphen;
b09da87b
JF
365 rhs_->Output(out, Precedence() - 1, right);
366 if (protect)
367 out << ')';
5999c315
JF
368}
369
b09da87b
JF
370void CYLambda::Output(std::ostream &out, CYFlags flags) const {
371 bool protect((flags & CYNoFunction) != 0);
372 if (protect)
373 out << '(';
5999c315
JF
374 out << "function";
375 if (name_ != NULL)
376 out << ' ' << *name_;
377 out << '(';
378 if (parameters_ != NULL)
379 out << *parameters_;
b09da87b
JF
380 out << "){";
381 if (body_ != NULL)
382 body_->Show(out);
383 out << '}';
384 if (protect)
385 out << ')';
5999c315
JF
386}
387
e5bc40db 388void CYMessage::Output(std::ostream &out, bool replace) const {
4e8c99fb 389 if (next_ != NULL)
e5bc40db 390 next_->Output(out, replace);
b09da87b
JF
391 out << "$cyn=new Selector(\"";
392 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
393 if (parameter->tag_ != NULL) {
394 out << *parameter->tag_;
395 if (parameter->name_ != NULL)
5999c315
JF
396 out << ':';
397 }
b09da87b 398 out << "\");";
e5bc40db
JF
399 out << "$cyt=$cyn.type($cy" << (instance_ ? 's' : 'p') << ");";
400 out << "class_" << (replace ? "replace" : "add") << "Method($cy" << (instance_ ? 'c' : 'm') << ",$cyn,";
478d4ed0 401 out << "new Functor(function(self,_cmd";
b09da87b 402 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
478d4ed0
JF
403 if (parameter->name_ != NULL)
404 out << ',' << *parameter->name_;
405 out << "){return function(){";
b09da87b
JF
406 if (body_ != NULL)
407 body_->Show(out);
478d4ed0 408 out << "}.call(self);},$cyt),$cyt);";
5999c315
JF
409}
410
b09da87b 411void CYNew::Output(std::ostream &out, CYFlags flags) const {
bce8339b
JF
412 if ((flags & CYNoLeader) != 0)
413 out << ' ';
d35a3b07 414 out << "new";
b09da87b 415 constructor_->Output(out, Precedence(), CYCenter(flags) | CYNoLeader);
d35a3b07 416 out << '(';
5999c315 417 if (arguments_ != NULL)
d35a3b07 418 arguments_->Output(out);
5999c315
JF
419 out << ')';
420}
421
b09da87b
JF
422void CYNull::Output(std::ostream &out, CYFlags flags) const {
423 if ((flags & CYNoLeader) != 0)
424 out << ' ';
5999c315 425 CYWord::Output(out);
b09da87b
JF
426 if ((flags & CYNoTrailer) != 0)
427 out << ' ';
5999c315
JF
428}
429
b09da87b 430void CYNumber::Output(std::ostream &out, CYFlags flags) const {
1ef7d061
JF
431 double value(Value());
432 if ((flags & CYNoLeader) != 0 || value < 0 && (flags & CYNoHyphen) != 0)
b09da87b 433 out << ' ';
18401062 434 // XXX: decide on correct precision
1ef7d061 435 out << std::setprecision(9) << value;
b09da87b
JF
436 if ((flags & CYNoTrailer) != 0)
437 out << ' ';
5999c315
JF
438}
439
e5bc40db
JF
440void CYNumber::PropertyName(std::ostream &out) const {
441 Output(out);
442}
443
b09da87b
JF
444void CYObject::Output(std::ostream &out, CYFlags flags) const {
445 bool protect((flags & CYNoBrace) != 0);
446 if (protect)
447 out << '(';
693d501b
JF
448 out << '{';
449 if (property_ != NULL)
450 property_->Output(out);
451 out << '}';
b09da87b
JF
452 if (protect)
453 out << ')';
693d501b
JF
454}
455
b09da87b
JF
456void CYPostfix::Output(std::ostream &out, CYFlags flags) const {
457 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 458 out << Operator();
5999c315
JF
459}
460
b09da87b 461void CYPrefix::Output(std::ostream &out, CYFlags flags) const {
1ef7d061 462 const char *name(Operator());
b09da87b 463 bool alphabetic(Alphabetic());
1ef7d061
JF
464 if (alphabetic && (flags & CYNoLeader) != 0 || name[0] == '-' && (flags & CYNoHyphen) != 0)
465 out << ' ';
466 out << name;
b09da87b
JF
467 CYFlags right(CYRight(flags));
468 if (alphabetic)
469 right |= CYNoLeader;
470 rhs_->Output(out, Precedence(), right);
5999c315
JF
471}
472
693d501b 473void CYProperty::Output(std::ostream &out) const {
e5bc40db 474 name_->PropertyName(out);
579ed526 475 out << ':';
b09da87b 476 value_->Output(out, CYPA, CYNoFlags);
5999c315
JF
477 if (next_ != NULL) {
478 out << ',';
693d501b 479 next_->Output(out);
5999c315 480 }
5999c315
JF
481}
482
483void CYReturn::Output(std::ostream &out) const {
484 out << "return";
b09da87b
JF
485 if (value_ != NULL)
486 value_->Output(out, CYNoLeader);
5999c315
JF
487 out << ';';
488}
489
b09da87b 490void CYSelector::Output(std::ostream &out, CYFlags flags) const {
bce8339b
JF
491 if ((flags & CYNoLeader) != 0)
492 out << ' ';
b09da87b 493 out << "new Selector(\"";
62014ea9
JF
494 if (name_ != NULL)
495 name_->Output(out);
dea834b0 496 out << "\")";
e7ed5354
JF
497}
498
62014ea9
JF
499void CYSelectorPart::Output(std::ostream &out) const {
500 if (name_ != NULL)
501 out << *name_;
502 if (value_)
503 out << ':';
504 if (next_ != NULL)
505 next_->Output(out);
506}
507
b09da87b 508void CYSend::Output(std::ostream &out, CYFlags flags) const {
c239b9f8
JF
509 if ((flags & CYNoLeader) != 0)
510 out << ' ';
b09da87b
JF
511 out << "objc_msgSend(";
512 self_->Output(out, CYPA, CYNoFlags);
4afefdd9
JF
513 out << ",";
514 std::ostringstream name;
b09da87b
JF
515 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
516 if (argument->name_ != NULL) {
4afefdd9 517 name << *argument->name_;
b09da87b 518 if (argument->value_ != NULL)
4afefdd9 519 name << ':';
b09da87b 520 }
4afefdd9 521 out << reinterpret_cast<void *>(sel_registerName(name.str().c_str()));
b09da87b
JF
522 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
523 if (argument->value_ != NULL) {
524 out << ",";
525 argument->value_->Output(out, CYPA, CYNoFlags);
526 }
527 out << ')';
528}
529
b1ff2d78 530void CYSource::Show(std::ostream &out) const {
5999c315 531 for (const CYSource *next(this); next != NULL; next = next->next_)
b09da87b 532 next->Output(out);
5999c315
JF
533}
534
535void CYSource::Output(std::ostream &out, bool block) const {
536 if (!block && next_ == NULL)
537 Output(out);
538 else {
539 out << '{';
b1ff2d78 540 Show(out);
5999c315
JF
541 out << '}';
542 }
543}
544
b09da87b 545void CYString::Output(std::ostream &out, CYFlags flags) const {
b4aa79af
JF
546 unsigned quot(0), apos(0);
547 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
548 if (*value == '"')
549 ++quot;
550 else if (*value == '\'')
551 ++apos;
552
553 bool single(quot > apos);
554
555 out << (single ? '\'' : '"');
5999c315
JF
556 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
557 switch (*value) {
5999c315
JF
558 case '\\': out << "\\\\"; break;
559 case '\b': out << "\\b"; break;
560 case '\f': out << "\\f"; break;
561 case '\n': out << "\\n"; break;
562 case '\r': out << "\\r"; break;
563 case '\t': out << "\\t"; break;
564 case '\v': out << "\\v"; break;
565
b4aa79af
JF
566 case '"':
567 if (!single)
568 out << "\\\"";
569 else goto simple;
570 break;
571
572 case '\'':
573 if (single)
574 out << "\\'";
575 else goto simple;
576 break;
577
5999c315
JF
578 default:
579 if (*value < 0x20 || *value >= 0x7f)
580 out << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value);
b4aa79af 581 else simple:
5999c315
JF
582 out << *value;
583 }
b4aa79af 584 out << (single ? '\'' : '"');
5999c315
JF
585}
586
e5bc40db
JF
587void CYString::PropertyName(std::ostream &out) const {
588 if (const char *word = Word())
589 out << word;
590 else
591 Output(out);
592}
593
5999c315 594void CYSwitch::Output(std::ostream &out) const {
d35a3b07 595 out << "switch(";
b09da87b 596 value_->Output(out, CYNoFlags);
d35a3b07 597 out << "){";
5999c315
JF
598 if (clauses_ != NULL)
599 out << *clauses_;
600 out << '}';
601}
602
b09da87b
JF
603void CYThis::Output(std::ostream &out, CYFlags flags) const {
604 if ((flags & CYNoLeader) != 0)
605 out << ' ';
5999c315 606 CYWord::Output(out);
b09da87b
JF
607 if ((flags & CYNoTrailer) != 0)
608 out << ' ';
5999c315
JF
609}
610
611void CYThrow::Output(std::ostream &out) const {
d35a3b07 612 out << "throw";
b09da87b
JF
613 if (value_ != NULL)
614 value_->Output(out, CYNoLeader);
5999c315
JF
615 out << ';';
616}
617
618void CYTry::Output(std::ostream &out) const {
619 out << "try";
620 try_->Output(out, true);
621 if (catch_ != NULL)
9b5527f0 622 catch_->Output(out);
5999c315
JF
623 if (finally_ != NULL) {
624 out << "finally";
625 finally_->Output(out, true);
626 }
627}
628
b09da87b 629void CYVariable::Output(std::ostream &out, CYFlags flags) const {
478d4ed0
JF
630 if ((flags & CYNoLeader) != 0)
631 out << ' ';
5999c315 632 out << *name_;
478d4ed0
JF
633 if ((flags & CYNoTrailer) != 0)
634 out << ' ';
5999c315
JF
635}
636
637void CYWhile::Output(std::ostream &out) const {
d35a3b07 638 out << "while(";
b09da87b 639 test_->Output(out, CYNoFlags);
d35a3b07 640 out << ')';
5999c315
JF
641 code_->Output(out, false);
642}
643
644void CYWith::Output(std::ostream &out) const {
d35a3b07 645 out << "with(";
b09da87b 646 scope_->Output(out, CYNoFlags);
d35a3b07 647 out << ')';
5999c315
JF
648 code_->Output(out, false);
649}
650
e5bc40db
JF
651void CYWord::ClassName(std::ostream &out) const {
652 out << "objc_getClass(\"" << Value() << "\")";
653}
654
5999c315
JF
655void CYWord::Output(std::ostream &out) const {
656 out << Value();
657}
e5bc40db
JF
658
659void CYWord::PropertyName(std::ostream &out) const {
660 Output(out);
661}