]> git.saurik.com Git - cycript.git/blame - Output.cpp
Removed dlclose() as it scares me and would cause everything to crash horribly if...
[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) {
fb98ac0c 34 return flags & (CYNoIn | CYNoTrailer | CYNoTerminator);
b09da87b
JF
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
652ec1ba 47void CYAddressOf::Output(CYOutput &out, CYFlags flags) const {
b09da87b 48 rhs_->Output(out, 1, CYLeft(flags));
9b5527f0 49 out << ".$cya()";
5999c315
JF
50}
51
652ec1ba 52void CYArgument::Output(CYOutput &out) const {
d35a3b07 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
652ec1ba 69void CYArray::Output(CYOutput &out, CYFlags flags) const {
5befe15e
JF
70 out << '[';
71 if (elements_ != NULL)
72 elements_->Output(out);
73 out << ']';
74}
75
652ec1ba 76void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
75b0a457
JF
77 // XXX: I don't necc. need the ()s
78 out << "(function($cyv";
79 for (CYComprehension *comprehension(comprehensions_); comprehension != NULL; comprehension = comprehension->next_)
80 if (const char *name = comprehension->Name())
81 out << ',' << name;
82 out << "){";
dc81e1c2 83 out << "$cyv=[];";
75b0a457 84 comprehensions_->Output(out);
dc81e1c2 85 out << "$cyv.push(";
75b0a457
JF
86 expression_->Output(out, CYPA, CYNoFlags);
87 out << ");";
88 for (CYComprehension *comprehension(comprehensions_); comprehension != NULL; comprehension = comprehension->next_)
89 comprehension->End_(out);
dc81e1c2 90 out << "return $cyv;";
75b0a457
JF
91 out << "}())";
92}
93
652ec1ba 94void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 95 lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand);
d35a3b07 96 out << Operator();
b09da87b 97 rhs_->Output(out, Precedence(), CYRight(flags));
d35a3b07
JF
98}
99
fb98ac0c
JF
100void CYBlock::Output(CYOutput &out, CYFlags flags) const {
101 statements_->Single(out, flags);
9e562cfc
JF
102}
103
652ec1ba 104void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
105 if ((flags & CYNoLeader) != 0)
106 out << ' ';
5999c315 107 out << (Value() ? "true" : "false");
b09da87b
JF
108 if ((flags & CYNoTrailer) != 0)
109 out << ' ';
5999c315
JF
110}
111
fb98ac0c
JF
112void CYBreak::Output(CYOutput &out, CYFlags flags) const {
113 if ((flags & CYNoLeader) != 0)
114 out << ' ';
5999c315
JF
115 out << "break";
116 if (label_ != NULL)
117 out << ' ' << *label_;
fb98ac0c
JF
118 if ((flags & CYNoTerminator) == 0)
119 out << ';';
120 else if ((flags & CYNoTrailer) != 0)
121 out << ' ';
5999c315
JF
122}
123
652ec1ba 124void CYCall::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c
JF
125 bool protect((flags & CYNoCall) != 0);
126 if (protect)
127 out << '(';
128 function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
d35a3b07 129 out << '(';
5999c315 130 if (arguments_ != NULL)
d35a3b07 131 arguments_->Output(out);
5999c315 132 out << ')';
fb98ac0c
JF
133 if (protect)
134 out << ')';
5999c315
JF
135}
136
652ec1ba 137void CYCatch::Output(CYOutput &out) const {
b10bd496
JF
138 out << "catch(" << *name_ << "){";
139 if (code_ != NULL)
fb98ac0c 140 code_->Multiple(out);
b10bd496 141 out << "}";
5999c315
JF
142}
143
fb98ac0c 144void CYCategory::Output(CYOutput &out, CYFlags flags) const {
e5bc40db
JF
145 out << "(function($cys,$cyp,$cyc,$cyn,$cyt){";
146 out << "$cyp=object_getClass($cys);";
147 out << "$cyc=$cys;";
148 if (messages_ != NULL)
149 messages_->Output(out, true);
150 out << "})(";
367eebb1 151 name_->ClassName(out, true);
fb98ac0c
JF
152 out << ')';
153 if ((flags & CYNoTerminator) == 0)
154 out << ';';
365abb0a
JF
155}
156
652ec1ba 157void CYClass::Output(CYOutput &out, CYFlags flags) const {
367eebb1 158 // XXX: I don't necc. need the ()s
e5bc40db
JF
159 out << "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){";
160 out << "$cyp=object_getClass($cys);";
367eebb1
JF
161 out << "$cyc=objc_allocateClassPair($cys,";
162 if (name_ != NULL)
163 name_->ClassName(out, false);
164 else
165 out << "$cyq(\"CY$\")";
166 out << ",0);";
b09da87b
JF
167 out << "$cym=object_getClass($cyc);";
168 if (fields_ != NULL)
169 fields_->Output(out);
170 if (messages_ != NULL)
e5bc40db 171 messages_->Output(out, false);
b09da87b 172 out << "objc_registerClassPair($cyc);";
367eebb1
JF
173 out << "return $cyc;";
174 out << "}(";
b09da87b
JF
175 if (super_ != NULL)
176 super_->Output(out, CYPA, CYNoFlags);
177 else
178 out << "null";
367eebb1 179 out << "))";
b09da87b
JF
180}
181
fb98ac0c
JF
182void CYClassExpression::Output(CYOutput &out, CYFlags flags) const {
183 CYClass::Output(out, flags);
184}
185
186void CYClassStatement::Output(CYOutput &out, CYFlags flags) const {
187 CYClass::Output(out, flags);
188}
189
652ec1ba 190void CYCompound::Output(CYOutput &out, CYFlags flags) const {
e5bc40db
JF
191 if (CYExpression *expression = expressions_)
192 if (CYExpression *next = expression->next_) {
193 expression->Output(out, CYLeft(flags));
194 CYFlags center(CYCenter(flags));
195 while (next != NULL) {
196 expression = next;
197 out << ',';
198 next = expression->next_;
199 CYFlags right(next != NULL ? center : CYRight(flags));
200 expression->Output(out, right);
201 }
202 } else
203 expression->Output(out, flags);
204}
205
652ec1ba 206void CYComprehension::Output(CYOutput &out) const {
75b0a457
JF
207 Begin_(out);
208 if (next_ != NULL)
209 next_->Output(out);
210}
211
652ec1ba 212void CYCondition::Output(CYOutput &out, CYFlags flags) const {
b09da87b 213 test_->Output(out, Precedence() - 1, CYLeft(flags));
d35a3b07 214 out << '?';
5999c315 215 if (true_ != NULL)
b09da87b 216 true_->Output(out, CYPA, CYNoFlags);
d35a3b07 217 out << ':';
b09da87b 218 false_->Output(out, CYPA, CYRight(flags));
5999c315
JF
219}
220
fb98ac0c
JF
221void CYContinue::Output(CYOutput &out, CYFlags flags) const {
222 if ((flags & CYNoLeader) != 0)
223 out << ' ';
5999c315
JF
224 out << "continue";
225 if (label_ != NULL)
226 out << ' ' << *label_;
fb98ac0c
JF
227 if ((flags & CYNoTerminator) == 0)
228 out << ';';
229 else if ((flags & CYNoTrailer) != 0)
230 out << ' ';
5999c315
JF
231}
232
652ec1ba 233void CYClause::Output(CYOutput &out) const {
d35a3b07
JF
234 if (case_ != NULL) {
235 out << "case";
cac61857 236 case_->Output(out, CYNoLeader);
d35a3b07 237 } else
5999c315
JF
238 out << "default";
239 out << ':';
240 if (code_ != NULL)
fb98ac0c 241 code_->Multiple(out, next_ == NULL ? CYNoFlags : CYNoTrailer);
cac61857
JF
242 if (next_ != NULL)
243 out << *next_;
244}
245
246const char *CYDeclaration::ForEachIn() const {
247 return identifier_->Value();
5999c315
JF
248}
249
652ec1ba 250void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
75b0a457
JF
251 if ((flags & CYNoLeader) != 0)
252 out << ' ';
fb98ac0c
JF
253 out << "var";
254 Output(out, CYRight(flags) | CYNoLeader);
75b0a457
JF
255}
256
652ec1ba 257void CYDeclaration::ForEachIn(CYOutput &out) const {
75b0a457 258 out << *identifier_;
5999c315
JF
259}
260
652ec1ba 261void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c
JF
262 if ((flags & CYNoLeader) != 0)
263 out << ' ';
5999c315 264 out << *identifier_;
d35a3b07
JF
265 if (initialiser_ != NULL) {
266 out << '=';
75b0a457
JF
267 initialiser_->Output(out, CYPA, CYRight(flags));
268 } else if ((flags & CYNoTrailer) != 0)
269 out << ' ';
5999c315
JF
270}
271
652ec1ba 272void CYDeclarations::For(CYOutput &out) const {
fb98ac0c
JF
273 out << "var";
274 Output(out, CYNoIn | CYNoLeader);
cac61857 275}
d35a3b07 276
652ec1ba 277void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
5999c315 278 const CYDeclarations *declaration(this);
fb98ac0c 279 bool first(true);
d35a3b07 280 output:
75b0a457 281 CYDeclarations *next(declaration->next_);
fb98ac0c
JF
282 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
283 first = false;
284 declaration->declaration_->Output(out, jacks);
d35a3b07 285
75b0a457 286 if (next != NULL) {
d35a3b07 287 out << ',';
75b0a457 288 declaration = next;
d35a3b07
JF
289 goto output;
290 }
5999c315
JF
291}
292
652ec1ba 293void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0
JF
294 object_->Output(out, Precedence(), CYLeft(flags));
295 if (const char *word = property_->Word())
296 out << '.' << word;
297 else {
298 out << '[';
299 property_->Output(out, CYNoFlags);
300 out << ']';
301 }
302}
303
fb98ac0c
JF
304void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
305 if ((flags & CYNoLeader) != 0)
306 out << ' ';
307 out << "do";
308 code_->Single(out, CYNoLeader | CYNoTrailer);
d35a3b07 309 out << "while(";
b09da87b
JF
310 test_->Output(out, CYNoFlags);
311 out << ')';
5999c315
JF
312}
313
652ec1ba 314void CYElement::Output(CYOutput &out) const {
5999c315 315 if (value_ != NULL)
b09da87b 316 value_->Output(out, CYPA, CYNoFlags);
5befe15e 317 if (next_ != NULL || value_ == NULL)
5999c315 318 out << ',';
5befe15e
JF
319 if (next_ != NULL)
320 next_->Output(out);
5999c315
JF
321}
322
fb98ac0c 323void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
324 out << ';';
325}
326
fb98ac0c
JF
327void CYExpress::Output(CYOutput &out, CYFlags flags) const {
328 bool terminator((flags & CYNoTerminator) == 0);
329 expression_->Output(out, (terminator ? CYLeft(flags) : flags) | CYNoBF);
330 if (terminator)
331 out << ';';
5999c315
JF
332}
333
652ec1ba 334void CYExpression::ClassName(CYOutput &out, bool object) const {
e5bc40db
JF
335 Output(out, CYPA, CYNoFlags);
336}
337
cac61857
JF
338const char *CYExpression::ForEachIn() const {
339 return NULL;
340}
341
652ec1ba 342void CYExpression::For(CYOutput &out) const {
cac61857
JF
343 Output(out, CYNoIn);
344}
345
652ec1ba 346void CYExpression::ForEachIn(CYOutput &out) const {
fb98ac0c 347 Output(out, CYPA, CYNoRightHand);
75b0a457
JF
348}
349
652ec1ba 350void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 351 Output(out, flags | CYNoRightHand);
d35a3b07
JF
352}
353
652ec1ba 354void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const {
fb98ac0c 355 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand()) {
5999c315 356 out << '(';
b09da87b 357 Output(out, CYNoFlags);
5999c315 358 out << ')';
b09da87b
JF
359 } else
360 Output(out, flags);
361}
362
652ec1ba 363void CYField::Output(CYOutput &out) const {
b09da87b 364 // XXX: implement!
5999c315
JF
365}
366
b10bd496
JF
367void CYFinally::Output(CYOutput &out) const {
368 out << "finally{";
369 if (code_ != NULL)
fb98ac0c 370 code_->Multiple(out);
b10bd496
JF
371 out << "}";
372}
373
fb98ac0c
JF
374void CYFor::Output(CYOutput &out, CYFlags flags) const {
375 if ((flags & CYNoLeader) != 0)
376 out << ' ';
5999c315
JF
377 out << "for(";
378 if (initialiser_ != NULL)
cac61857 379 initialiser_->For(out);
5999c315
JF
380 out << ';';
381 if (test_ != NULL)
b09da87b 382 test_->Output(out, CYNoFlags);
5999c315
JF
383 out << ';';
384 if (increment_ != NULL)
b09da87b 385 increment_->Output(out, CYNoFlags);
5999c315 386 out << ')';
fb98ac0c 387 code_->Single(out, CYNoFlags);
5999c315
JF
388}
389
fb98ac0c
JF
390void CYForEachIn::Output(CYOutput &out, CYFlags flags) const {
391 if ((flags & CYNoLeader) != 0)
392 out << ' ';
393
6f926cee 394 out << "with({$cys:0,$cyt:0}){";
75b0a457 395
75b0a457
JF
396 out << "$cys=";
397 set_->Output(out, CYPA, CYNoFlags);
398 out << ";";
399
400 out << "for($cyt in $cys){";
401
402 initialiser_->ForEachIn(out);
403 out << "=$cys[$cyt];";
404
fb98ac0c 405 code_->Multiple(out);
75b0a457 406
6f926cee 407 out << '}';
75b0a457 408
6f926cee 409 out << '}';
75b0a457
JF
410}
411
652ec1ba 412void CYForEachInComprehension::Begin_(CYOutput &out) const {
75b0a457
JF
413 out << "(function($cys){";
414 out << "$cys=";
415 set_->Output(out, CYPA, CYNoFlags);
416 out << ";";
417
418 out << "for(" << *name_ << " in $cys){";
419 out << *name_ << "=$cys[" << *name_ << "];";
420}
421
652ec1ba 422void CYForEachInComprehension::End_(CYOutput &out) const {
75b0a457
JF
423 out << "}}());";
424}
425
fb98ac0c
JF
426void CYForIn::Output(CYOutput &out, CYFlags flags) const {
427 if ((flags & CYNoLeader) != 0)
428 out << ' ';
5999c315 429 out << "for(";
cac61857 430 initialiser_->ForIn(out, CYNoIn | CYNoTrailer);
b09da87b
JF
431 out << "in";
432 set_->Output(out, CYNoLeader);
5999c315 433 out << ')';
fb98ac0c 434 code_->Single(out, CYRight(flags));
5999c315
JF
435}
436
652ec1ba 437void CYForInComprehension::Begin_(CYOutput &out) const {
75b0a457
JF
438 out << "for(" << *name_ << " in";
439 set_->Output(out, CYNoLeader);
440 out << ')';
441}
442
fb98ac0c
JF
443void CYFunction::Output(CYOutput &out, CYFlags flags) const {
444 bool protect((flags & CYNoFunction) != 0);
445 if (protect)
446 out << '(';
447 else if ((flags & CYNoLeader) != 0)
448 out << ' ';
449 out << "function";
450 if (name_ != NULL)
451 out << ' ' << *name_;
452 out << '(';
453 if (parameters_ != NULL)
454 out << *parameters_;
455 out << "){";
456 if (body_ != NULL)
457 body_->Multiple(out);
458 out << '}';
459 if (protect)
460 out << ')';
461}
462
463void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
464 CYFunction::Output(out, flags);
465}
466
467void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
468 CYFunction::Output(out, flags);
b09da87b
JF
469}
470
652ec1ba 471void CYFunctionParameter::Output(CYOutput &out) const {
b09da87b
JF
472 out << *name_;
473 if (next_ != NULL) {
474 out << ',';
475 out << *next_;
476 }
5999c315
JF
477}
478
fb98ac0c
JF
479void CYIf::Output(CYOutput &out, CYFlags flags) const {
480 bool protect(false);
481 if (false_ == NULL && (flags & CYNoDangle) != 0) {
482 protect = true;
483 out << '{';
484 } else if ((flags & CYNoLeader) != 0)
485 out << ' ';
d35a3b07 486 out << "if(";
b09da87b 487 test_->Output(out, CYNoFlags);
d35a3b07 488 out << ')';
fb98ac0c
JF
489 CYFlags right(protect ? CYNoFlags : CYRight(flags));
490 CYFlags jacks(CYNoDangle);
491 jacks |= false_ == NULL ? right : CYNoTrailer;
492 true_->Single(out, jacks);
5999c315 493 if (false_ != NULL) {
fb98ac0c
JF
494 out << "else";
495 if (protect)
496 right |= CYNoTerminator;
497 false_->Single(out, CYNoLeader | right);
5999c315 498 }
fb98ac0c
JF
499 if (protect)
500 out << '}';
5999c315
JF
501}
502
652ec1ba 503void CYIfComprehension::Begin_(CYOutput &out) const {
75b0a457
JF
504 out << "if(";
505 test_->Output(out, CYNoFlags);
506 out << ')';
507}
508
652ec1ba 509void CYIndirect::Output(CYOutput &out, CYFlags flags) const {
b09da87b 510 rhs_->Output(out, 1, CYLeft(flags));
9b5527f0 511 out << ".$cyi";
fb98ac0c
JF
512 if ((flags & CYNoTrailer) != 0)
513 out << ' ';
9b5527f0
JF
514}
515
652ec1ba 516void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0
JF
517 object_->Output(out, Precedence(), CYLeft(flags));
518 out << ".$cyi";
519 if (const char *word = property_->Word())
520 out << '.' << word;
521 else {
522 out << '[';
523 property_->Output(out, CYNoFlags);
524 out << ']';
525 }
5999c315
JF
526}
527
652ec1ba 528void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
529 const char *name(Operator());
530 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in"));
531 if (protect)
532 out << '(';
533 bool alphabetic(Alphabetic());
534 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
535 if (alphabetic)
536 left |= CYNoTrailer;
537 lhs_->Output(out, Precedence(), left);
538 out << name;
539 CYFlags right(protect ? CYNoFlags : CYRight(flags));
540 if (alphabetic)
541 right |= CYNoLeader;
1ef7d061
JF
542 if (strcmp(name, "-") == 0)
543 right |= CYNoHyphen;
b09da87b
JF
544 rhs_->Output(out, Precedence() - 1, right);
545 if (protect)
546 out << ')';
5999c315
JF
547}
548
fb98ac0c
JF
549void CYLet::Output(CYOutput &out, CYFlags flags) const {
550 if ((flags & CYNoLeader) != 0)
83b5afe2 551 out << ' ';
cac61857
JF
552 out << "let(";
553 declarations_->Output(out, CYNoFlags);
554 out << "){";
555 if (statements_ != NULL)
fb98ac0c 556 statements_->Multiple(out);
cac61857
JF
557 out << "}";
558}
559
652ec1ba 560void CYMessage::Output(CYOutput &out, bool replace) const {
4e8c99fb 561 if (next_ != NULL)
e5bc40db 562 next_->Output(out, replace);
b09da87b
JF
563 out << "$cyn=new Selector(\"";
564 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
565 if (parameter->tag_ != NULL) {
566 out << *parameter->tag_;
567 if (parameter->name_ != NULL)
5999c315
JF
568 out << ':';
569 }
b09da87b 570 out << "\");";
e5bc40db
JF
571 out << "$cyt=$cyn.type($cy" << (instance_ ? 's' : 'p') << ");";
572 out << "class_" << (replace ? "replace" : "add") << "Method($cy" << (instance_ ? 'c' : 'm') << ",$cyn,";
478d4ed0 573 out << "new Functor(function(self,_cmd";
b09da87b 574 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
478d4ed0
JF
575 if (parameter->name_ != NULL)
576 out << ',' << *parameter->name_;
577 out << "){return function(){";
b09da87b 578 if (body_ != NULL)
fb98ac0c 579 body_->Multiple(out);
478d4ed0 580 out << "}.call(self);},$cyt),$cyt);";
5999c315
JF
581}
582
652ec1ba 583void CYNew::Output(CYOutput &out, CYFlags flags) const {
bce8339b
JF
584 if ((flags & CYNoLeader) != 0)
585 out << ' ';
d35a3b07 586 out << "new";
fb98ac0c
JF
587 constructor_->Output(out, Precedence(), CYCenter(flags) | CYNoLeader | CYNoCall);
588 if (arguments_ != NULL) {
589 out << '(';
d35a3b07 590 arguments_->Output(out);
fb98ac0c
JF
591 out << ')';
592 }
5999c315
JF
593}
594
652ec1ba 595void CYNull::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
596 if ((flags & CYNoLeader) != 0)
597 out << ' ';
5999c315 598 CYWord::Output(out);
b09da87b
JF
599 if ((flags & CYNoTrailer) != 0)
600 out << ' ';
5999c315
JF
601}
602
652ec1ba 603void CYNumber::Output(CYOutput &out, CYFlags flags) const {
1ef7d061
JF
604 double value(Value());
605 if ((flags & CYNoLeader) != 0 || value < 0 && (flags & CYNoHyphen) != 0)
b09da87b 606 out << ' ';
18401062 607 // XXX: decide on correct precision
652ec1ba 608 out.out_ << std::setprecision(9) << value;
b09da87b
JF
609 if ((flags & CYNoTrailer) != 0)
610 out << ' ';
5999c315
JF
611}
612
652ec1ba 613void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 614 Output(out, CYNoFlags);
e5bc40db
JF
615}
616
652ec1ba 617void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
618 bool protect((flags & CYNoBrace) != 0);
619 if (protect)
620 out << '(';
693d501b
JF
621 out << '{';
622 if (property_ != NULL)
623 property_->Output(out);
624 out << '}';
b09da87b
JF
625 if (protect)
626 out << ')';
693d501b
JF
627}
628
652ec1ba 629void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 630 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 631 out << Operator();
5999c315
JF
632}
633
652ec1ba 634void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 635 const char *name(Operator());
b09da87b 636 bool alphabetic(Alphabetic());
1ef7d061
JF
637 if (alphabetic && (flags & CYNoLeader) != 0 || name[0] == '-' && (flags & CYNoHyphen) != 0)
638 out << ' ';
639 out << name;
b09da87b
JF
640 CYFlags right(CYRight(flags));
641 if (alphabetic)
642 right |= CYNoLeader;
643 rhs_->Output(out, Precedence(), right);
5999c315
JF
644}
645
652ec1ba 646void CYProperty::Output(CYOutput &out) const {
e5bc40db 647 name_->PropertyName(out);
579ed526 648 out << ':';
b09da87b 649 value_->Output(out, CYPA, CYNoFlags);
5999c315
JF
650 if (next_ != NULL) {
651 out << ',';
693d501b 652 next_->Output(out);
5999c315 653 }
5999c315
JF
654}
655
63cd45c9
JF
656void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
657 out << Value();
658 if ((flags & CYNoTrailer) != 0)
659 out << ' ';
660}
661
fb98ac0c
JF
662void CYReturn::Output(CYOutput &out, CYFlags flags) const {
663 bool terminator((flags & CYNoTerminator) == 0);
664 if ((flags & CYNoLeader) != 0)
665 out << ' ';
5999c315 666 out << "return";
b09da87b 667 if (value_ != NULL)
fb98ac0c
JF
668 value_->Output(out, (terminator ? CYCenter(flags) : flags) | CYNoLeader);
669 if (terminator)
670 out << ';';
5999c315
JF
671}
672
652ec1ba 673void CYSelector::Output(CYOutput &out, CYFlags flags) const {
bce8339b
JF
674 if ((flags & CYNoLeader) != 0)
675 out << ' ';
b09da87b 676 out << "new Selector(\"";
62014ea9
JF
677 if (name_ != NULL)
678 name_->Output(out);
dea834b0 679 out << "\")";
e7ed5354
JF
680}
681
652ec1ba 682void CYSelectorPart::Output(CYOutput &out) const {
62014ea9
JF
683 if (name_ != NULL)
684 out << *name_;
685 if (value_)
686 out << ':';
687 if (next_ != NULL)
688 next_->Output(out);
689}
690
652ec1ba 691void CYSend::Output(CYOutput &out, CYFlags flags) const {
c239b9f8
JF
692 if ((flags & CYNoLeader) != 0)
693 out << ' ';
b09da87b
JF
694 out << "objc_msgSend(";
695 self_->Output(out, CYPA, CYNoFlags);
4afefdd9
JF
696 out << ",";
697 std::ostringstream name;
b09da87b
JF
698 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
699 if (argument->name_ != NULL) {
4afefdd9 700 name << *argument->name_;
b09da87b 701 if (argument->value_ != NULL)
4afefdd9 702 name << ':';
b09da87b 703 }
652ec1ba 704 out.out_ << reinterpret_cast<void *>(sel_registerName(name.str().c_str()));
b09da87b
JF
705 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
706 if (argument->value_ != NULL) {
707 out << ",";
708 argument->value_->Output(out, CYPA, CYNoFlags);
709 }
710 out << ')';
711}
712
fb98ac0c
JF
713void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
714 bool first(true);
715 for (const CYStatement *next(this); next != NULL; next = next->next_) {
716 bool last(next->next_ == NULL);
717 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYCenter(flags) : CYRight(flags));
718 if (last)
719 jacks |= CYNoTerminator;
720 first = false;
721 next->Output(out, jacks);
722 }
5999c315
JF
723}
724
fb98ac0c
JF
725void CYStatement::Single(CYOutput &out, CYFlags flags) const {
726 if (next_ != NULL) {
5999c315 727 out << '{';
fb98ac0c 728 Multiple(out);
5999c315 729 out << '}';
fb98ac0c
JF
730 } else {
731 bool protect(false);
732 if (labels_ != NULL && (flags & CYNoLeader) != 0)
733 protect = true;
734 if (protect)
735 out << ' ';
736 for (CYLabel *label(labels_); label != NULL; label = label->next_)
737 out << *label->name_ << ':';
738 Output(out, protect ? CYRight(flags) : flags);
5999c315
JF
739 }
740}
741
652ec1ba 742void CYString::Output(CYOutput &out, CYFlags flags) const {
b4aa79af
JF
743 unsigned quot(0), apos(0);
744 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
745 if (*value == '"')
746 ++quot;
747 else if (*value == '\'')
748 ++apos;
749
750 bool single(quot > apos);
751
752 out << (single ? '\'' : '"');
5999c315
JF
753 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
754 switch (*value) {
5999c315
JF
755 case '\\': out << "\\\\"; break;
756 case '\b': out << "\\b"; break;
757 case '\f': out << "\\f"; break;
758 case '\n': out << "\\n"; break;
759 case '\r': out << "\\r"; break;
760 case '\t': out << "\\t"; break;
761 case '\v': out << "\\v"; break;
762
b4aa79af
JF
763 case '"':
764 if (!single)
765 out << "\\\"";
766 else goto simple;
767 break;
768
769 case '\'':
770 if (single)
771 out << "\\'";
772 else goto simple;
773 break;
774
5999c315
JF
775 default:
776 if (*value < 0x20 || *value >= 0x7f)
652ec1ba 777 out.out_ << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value);
b4aa79af 778 else simple:
5999c315
JF
779 out << *value;
780 }
b4aa79af 781 out << (single ? '\'' : '"');
5999c315
JF
782}
783
652ec1ba 784void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
785 if (const char *word = Word())
786 out << word;
787 else
fb98ac0c 788 Output(out, CYNoFlags);
e5bc40db
JF
789}
790
fb98ac0c
JF
791void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
792 if ((flags & CYNoLeader) != 0)
793 out << ' ';
d35a3b07 794 out << "switch(";
b09da87b 795 value_->Output(out, CYNoFlags);
d35a3b07 796 out << "){";
5999c315
JF
797 if (clauses_ != NULL)
798 out << *clauses_;
799 out << '}';
800}
801
652ec1ba 802void CYThis::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
803 if ((flags & CYNoLeader) != 0)
804 out << ' ';
5999c315 805 CYWord::Output(out);
b09da87b
JF
806 if ((flags & CYNoTrailer) != 0)
807 out << ' ';
5999c315
JF
808}
809
fb98ac0c
JF
810void CYThrow::Output(CYOutput &out, CYFlags flags) const {
811 bool terminator((flags & CYNoTerminator) == 0);
812 if ((flags & CYNoLeader) != 0)
813 out << ' ';
d35a3b07 814 out << "throw";
b09da87b 815 if (value_ != NULL)
fb98ac0c
JF
816 value_->Output(out, (terminator ? CYCenter(flags) : flags) | CYNoLeader);
817 if (terminator)
818 out << ';';
5999c315
JF
819}
820
fb98ac0c
JF
821void CYTry::Output(CYOutput &out, CYFlags flags) const {
822 if ((flags & CYNoLeader) != 0)
823 out << ' ';
b10bd496
JF
824 out << "try{";
825 if (code_ != NULL)
fb98ac0c 826 code_->Multiple(out);
b10bd496 827 out << "}";
5999c315 828 if (catch_ != NULL)
9b5527f0 829 catch_->Output(out);
b10bd496
JF
830 if (finally_ != NULL)
831 finally_->Output(out);
5999c315
JF
832}
833
fb98ac0c
JF
834void CYVar::Output(CYOutput &out, CYFlags flags) const {
835 bool terminator((flags & CYNoTerminator) == 0);
836 if ((flags & CYNoLeader) != 0)
837 out << ' ';
838 out << "var";
839 declarations_->Output(out, (terminator ? CYCenter(flags) : flags) | CYNoLeader);
840 if (terminator)
841 out << ';';
cac61857
JF
842}
843
652ec1ba 844void CYVariable::Output(CYOutput &out, CYFlags flags) const {
478d4ed0
JF
845 if ((flags & CYNoLeader) != 0)
846 out << ' ';
5999c315 847 out << *name_;
478d4ed0
JF
848 if ((flags & CYNoTrailer) != 0)
849 out << ' ';
5999c315
JF
850}
851
fb98ac0c
JF
852void CYWhile::Output(CYOutput &out, CYFlags flags) const {
853 if ((flags & CYNoLeader) != 0)
854 out << ' ';
d35a3b07 855 out << "while(";
b09da87b 856 test_->Output(out, CYNoFlags);
d35a3b07 857 out << ')';
fb98ac0c 858 code_->Single(out, CYRight(flags));
5999c315
JF
859}
860
fb98ac0c
JF
861void CYWith::Output(CYOutput &out, CYFlags flags) const {
862 if ((flags & CYNoLeader) != 0)
863 out << ' ';
d35a3b07 864 out << "with(";
b09da87b 865 scope_->Output(out, CYNoFlags);
d35a3b07 866 out << ')';
fb98ac0c 867 code_->Single(out, CYRight(flags));
5999c315
JF
868}
869
652ec1ba 870void CYWord::ClassName(CYOutput &out, bool object) const {
367eebb1
JF
871 if (object)
872 out << "objc_getClass(";
873 out << '"' << Value() << '"';
874 if (object)
875 out << ')';
e5bc40db
JF
876}
877
652ec1ba 878void CYWord::Output(CYOutput &out) const {
5999c315
JF
879 out << Value();
880}
e5bc40db 881
652ec1ba 882void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
883 Output(out);
884}