1
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
4 * written by Dave Fladebo
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/hdrgen.c
9 */
10
11 // Routines to emit header files
12
13 #include "root/dsystem.h"
14 #include "root/rmem.h"
15
16 #include "mars.h"
17 #include "id.h"
18 #include "init.h"
19
20 #include "attrib.h"
21 #include "cond.h"
22 #include "doc.h"
23 #include "enum.h"
24 #include "import.h"
25 #include "module.h"
26 #include "mtype.h"
27 #include "parse.h"
28 #include "scope.h"
29 #include "staticassert.h"
30 #include "target.h"
31 #include "template.h"
32 #include "utf.h"
33 #include "version.h"
34
35 #include "declaration.h"
36 #include "aggregate.h"
37 #include "expression.h"
38 #include "ctfe.h"
39 #include "statement.h"
40 #include "aliasthis.h"
41 #include "nspace.h"
42 #include "hdrgen.h"
43
44 void linkageToBuffer(OutBuffer *buf, LINK linkage);
45 void MODtoBuffer(OutBuffer *buf, MOD mod);
46
genhdrfile(Module * m)47 void genhdrfile(Module *m)
48 {
49 OutBuffer buf;
50 buf.doindent = 1;
51
52 buf.printf("// D import file generated from '%s'", m->srcfile->toChars());
53 buf.writenl();
54
55 HdrGenState hgs;
56 hgs.hdrgen = true;
57
58 toCBuffer(m, &buf, &hgs);
59
60 // Transfer image to file
61 m->hdrfile->setbuffer(buf.data, buf.offset);
62 buf.extractData();
63
64 ensurePathToNameExists(Loc(), m->hdrfile->toChars());
65 writeFile(m->loc, m->hdrfile);
66 }
67
68 /**
69 * Dumps the full contents of module `m` to `buf`.
70 * Params:
71 * buf = buffer to write to.
72 * m = module to visit all members of.
73 */
moduleToBuffer(OutBuffer * buf,Module * m)74 void moduleToBuffer(OutBuffer *buf, Module *m)
75 {
76 HdrGenState hgs;
77 hgs.fullDump = true;
78 toCBuffer(m, buf, &hgs);
79 }
80
81 class PrettyPrintVisitor : public Visitor
82 {
83 public:
84 OutBuffer *buf;
85 HdrGenState *hgs;
86 bool declstring; // set while declaring alias for string,wstring or dstring
87 EnumDeclaration *inEnumDecl;
88
PrettyPrintVisitor(OutBuffer * buf,HdrGenState * hgs)89 PrettyPrintVisitor(OutBuffer *buf, HdrGenState *hgs)
90 : buf(buf), hgs(hgs), declstring(false), inEnumDecl(NULL)
91 {
92 }
93
visit(Statement *)94 void visit(Statement *)
95 {
96 buf->printf("Statement::toCBuffer()");
97 buf->writenl();
98 assert(0);
99 }
100
visit(ErrorStatement *)101 void visit(ErrorStatement *)
102 {
103 buf->printf("__error__");
104 buf->writenl();
105 }
106
visit(ExpStatement * s)107 void visit(ExpStatement *s)
108 {
109 if (s->exp && s->exp->op == TOKdeclaration)
110 {
111 // bypass visit(DeclarationExp)
112 ((DeclarationExp *)s->exp)->declaration->accept(this);
113 return;
114 }
115 if (s->exp)
116 s->exp->accept(this);
117 buf->writeByte(';');
118 if (!hgs->forStmtInit)
119 buf->writenl();
120 }
121
visit(CompileStatement * s)122 void visit(CompileStatement *s)
123 {
124 buf->writestring("mixin(");
125 s->exp->accept(this);
126 buf->writestring(");");
127 if (!hgs->forStmtInit)
128 buf->writenl();
129 }
130
visit(CompoundStatement * s)131 void visit(CompoundStatement *s)
132 {
133 for (size_t i = 0; i < s->statements->dim; i++)
134 {
135 Statement *sx = (*s->statements)[i];
136 if (sx)
137 sx->accept(this);
138 }
139 }
140
visit(CompoundDeclarationStatement * s)141 void visit(CompoundDeclarationStatement *s)
142 {
143 bool anywritten = false;
144 for (size_t i = 0; i < s->statements->dim; i++)
145 {
146 Statement *sx = (*s->statements)[i];
147 ExpStatement *ds = sx ? sx->isExpStatement() : NULL;
148 if (ds && ds->exp->op == TOKdeclaration)
149 {
150 Dsymbol *d = ((DeclarationExp *)ds->exp)->declaration;
151 assert(d->isDeclaration());
152 if (VarDeclaration *v = d->isVarDeclaration())
153 visitVarDecl(v, anywritten);
154 else
155 d->accept(this);
156 anywritten = true;
157 }
158 }
159 buf->writeByte(';');
160 if (!hgs->forStmtInit)
161 buf->writenl();
162 }
163
visit(UnrolledLoopStatement * s)164 void visit(UnrolledLoopStatement *s)
165 {
166 buf->writestring("unrolled {");
167 buf->writenl();
168 buf->level++;
169
170 for (size_t i = 0; i < s->statements->dim; i++)
171 {
172 Statement *sx = (*s->statements)[i];
173 if (sx)
174 sx->accept(this);
175 }
176
177 buf->level--;
178 buf->writeByte('}');
179 buf->writenl();
180 }
181
visit(ScopeStatement * s)182 void visit(ScopeStatement *s)
183 {
184 buf->writeByte('{');
185 buf->writenl();
186 buf->level++;
187
188 if (s->statement)
189 s->statement->accept(this);
190
191 buf->level--;
192 buf->writeByte('}');
193 buf->writenl();
194 }
195
visit(WhileStatement * s)196 void visit(WhileStatement *s)
197 {
198 buf->writestring("while (");
199 s->condition->accept(this);
200 buf->writeByte(')');
201 buf->writenl();
202 if (s->_body)
203 s->_body->accept(this);
204 }
205
visit(DoStatement * s)206 void visit(DoStatement *s)
207 {
208 buf->writestring("do");
209 buf->writenl();
210 if (s->_body)
211 s->_body->accept(this);
212 buf->writestring("while (");
213 s->condition->accept(this);
214 buf->writestring(");");
215 buf->writenl();
216 }
217
visit(ForStatement * s)218 void visit(ForStatement *s)
219 {
220 buf->writestring("for (");
221 if (s->_init)
222 {
223 hgs->forStmtInit++;
224 s->_init->accept(this);
225 hgs->forStmtInit--;
226 }
227 else
228 buf->writeByte(';');
229 if (s->condition)
230 {
231 buf->writeByte(' ');
232 s->condition->accept(this);
233 }
234 buf->writeByte(';');
235 if (s->increment)
236 {
237 buf->writeByte(' ');
238 s->increment->accept(this);
239 }
240 buf->writeByte(')');
241 buf->writenl();
242 buf->writeByte('{');
243 buf->writenl();
244 buf->level++;
245 if (s->_body)
246 s->_body->accept(this);
247 buf->level--;
248 buf->writeByte('}');
249 buf->writenl();
250 }
251
visit(ForeachStatement * s)252 void visit(ForeachStatement *s)
253 {
254 buf->writestring(Token::toChars(s->op));
255 buf->writestring(" (");
256 for (size_t i = 0; i < s->parameters->dim; i++)
257 {
258 Parameter *p = (*s->parameters)[i];
259 if (i)
260 buf->writestring(", ");
261 if (stcToBuffer(buf, p->storageClass))
262 buf->writeByte(' ');
263 if (p->type)
264 typeToBuffer(p->type, p->ident);
265 else
266 buf->writestring(p->ident->toChars());
267 }
268 buf->writestring("; ");
269 s->aggr->accept(this);
270 buf->writeByte(')');
271 buf->writenl();
272 buf->writeByte('{');
273 buf->writenl();
274 buf->level++;
275 if (s->_body)
276 s->_body->accept(this);
277 buf->level--;
278 buf->writeByte('}');
279 buf->writenl();
280 }
281
visit(ForeachRangeStatement * s)282 void visit(ForeachRangeStatement *s)
283 {
284 buf->writestring(Token::toChars(s->op));
285 buf->writestring(" (");
286
287 if (s->prm->type)
288 typeToBuffer(s->prm->type, s->prm->ident);
289 else
290 buf->writestring(s->prm->ident->toChars());
291
292 buf->writestring("; ");
293 s->lwr->accept(this);
294 buf->writestring(" .. ");
295 s->upr->accept(this);
296 buf->writeByte(')');
297 buf->writenl();
298 buf->writeByte('{');
299 buf->writenl();
300 buf->level++;
301 if (s->_body)
302 s->_body->accept(this);
303 buf->level--;
304 buf->writeByte('}');
305 buf->writenl();
306 }
307
visit(IfStatement * s)308 void visit(IfStatement *s)
309 {
310 buf->writestring("if (");
311 if (Parameter *p = s->prm)
312 {
313 StorageClass stc = p->storageClass;
314 if (!p->type && !stc)
315 stc = STCauto;
316 if (stcToBuffer(buf, stc))
317 buf->writeByte(' ');
318 if (p->type)
319 typeToBuffer(p->type, p->ident);
320 else
321 buf->writestring(p->ident->toChars());
322 buf->writestring(" = ");
323 }
324 s->condition->accept(this);
325 buf->writeByte(')');
326 buf->writenl();
327 if (s->ifbody->isScopeStatement())
328 {
329 s->ifbody->accept(this);
330 }
331 else
332 {
333 buf->level++;
334 s->ifbody->accept(this);
335 buf->level--;
336 }
337 if (s->elsebody)
338 {
339 buf->writestring("else");
340 if (!s->elsebody->isIfStatement())
341 {
342 buf->writenl();
343 }
344 else
345 {
346 buf->writeByte(' ');
347 }
348 if (s->elsebody->isScopeStatement() || s->elsebody->isIfStatement())
349 {
350 s->elsebody->accept(this);
351 }
352 else
353 {
354 buf->level++;
355 s->elsebody->accept(this);
356 buf->level--;
357 }
358 }
359 }
360
visit(ConditionalStatement * s)361 void visit(ConditionalStatement *s)
362 {
363 s->condition->accept(this);
364 buf->writenl();
365 buf->writeByte('{');
366 buf->writenl();
367 buf->level++;
368 if (s->ifbody)
369 s->ifbody->accept(this);
370 buf->level--;
371 buf->writeByte('}');
372 buf->writenl();
373 if (s->elsebody)
374 {
375 buf->writestring("else");
376 buf->writenl();
377 buf->writeByte('{');
378 buf->level++;
379 buf->writenl();
380 s->elsebody->accept(this);
381 buf->level--;
382 buf->writeByte('}');
383 }
384 buf->writenl();
385 }
386
visit(PragmaStatement * s)387 void visit(PragmaStatement *s)
388 {
389 buf->writestring("pragma (");
390 buf->writestring(s->ident->toChars());
391 if (s->args && s->args->dim)
392 {
393 buf->writestring(", ");
394 argsToBuffer(s->args);
395 }
396 buf->writeByte(')');
397 if (s->_body)
398 {
399 buf->writenl();
400 buf->writeByte('{');
401 buf->writenl();
402 buf->level++;
403
404 s->_body->accept(this);
405
406 buf->level--;
407 buf->writeByte('}');
408 buf->writenl();
409 }
410 else
411 {
412 buf->writeByte(';');
413 buf->writenl();
414 }
415 }
416
visit(StaticAssertStatement * s)417 void visit(StaticAssertStatement *s)
418 {
419 s->sa->accept(this);
420 }
421
visit(SwitchStatement * s)422 void visit(SwitchStatement *s)
423 {
424 buf->writestring(s->isFinal ? "final switch (" : "switch (");
425 s->condition->accept(this);
426 buf->writeByte(')');
427 buf->writenl();
428 if (s->_body)
429 {
430 if (!s->_body->isScopeStatement())
431 {
432 buf->writeByte('{');
433 buf->writenl();
434 buf->level++;
435 s->_body->accept(this);
436 buf->level--;
437 buf->writeByte('}');
438 buf->writenl();
439 }
440 else
441 {
442 s->_body->accept(this);
443 }
444 }
445 }
446
visit(CaseStatement * s)447 void visit(CaseStatement *s)
448 {
449 buf->writestring("case ");
450 s->exp->accept(this);
451 buf->writeByte(':');
452 buf->writenl();
453 s->statement->accept(this);
454 }
455
visit(CaseRangeStatement * s)456 void visit(CaseRangeStatement *s)
457 {
458 buf->writestring("case ");
459 s->first->accept(this);
460 buf->writestring(": .. case ");
461 s->last->accept(this);
462 buf->writeByte(':');
463 buf->writenl();
464 s->statement->accept(this);
465 }
466
visit(DefaultStatement * s)467 void visit(DefaultStatement *s)
468 {
469 buf->writestring("default:");
470 buf->writenl();
471 s->statement->accept(this);
472 }
473
visit(GotoDefaultStatement *)474 void visit(GotoDefaultStatement *)
475 {
476 buf->writestring("goto default;");
477 buf->writenl();
478 }
479
visit(GotoCaseStatement * s)480 void visit(GotoCaseStatement *s)
481 {
482 buf->writestring("goto case");
483 if (s->exp)
484 {
485 buf->writeByte(' ');
486 s->exp->accept(this);
487 }
488 buf->writeByte(';');
489 buf->writenl();
490 }
491
visit(SwitchErrorStatement *)492 void visit(SwitchErrorStatement *)
493 {
494 buf->writestring("SwitchErrorStatement::toCBuffer()");
495 buf->writenl();
496 }
497
visit(ReturnStatement * s)498 void visit(ReturnStatement *s)
499 {
500 buf->printf("return ");
501 if (s->exp)
502 s->exp->accept(this);
503 buf->writeByte(';');
504 buf->writenl();
505 }
506
visit(BreakStatement * s)507 void visit(BreakStatement *s)
508 {
509 buf->writestring("break");
510 if (s->ident)
511 {
512 buf->writeByte(' ');
513 buf->writestring(s->ident->toChars());
514 }
515 buf->writeByte(';');
516 buf->writenl();
517 }
518
visit(ContinueStatement * s)519 void visit(ContinueStatement *s)
520 {
521 buf->writestring("continue");
522 if (s->ident)
523 {
524 buf->writeByte(' ');
525 buf->writestring(s->ident->toChars());
526 }
527 buf->writeByte(';');
528 buf->writenl();
529 }
530
visit(SynchronizedStatement * s)531 void visit(SynchronizedStatement *s)
532 {
533 buf->writestring("synchronized");
534 if (s->exp)
535 {
536 buf->writeByte('(');
537 s->exp->accept(this);
538 buf->writeByte(')');
539 }
540 if (s->_body)
541 {
542 buf->writeByte(' ');
543 s->_body->accept(this);
544 }
545 }
546
visit(WithStatement * s)547 void visit(WithStatement *s)
548 {
549 buf->writestring("with (");
550 s->exp->accept(this);
551 buf->writestring(")");
552 buf->writenl();
553 if (s->_body)
554 s->_body->accept(this);
555 }
556
visit(TryCatchStatement * s)557 void visit(TryCatchStatement *s)
558 {
559 buf->writestring("try");
560 buf->writenl();
561 if (s->_body)
562 s->_body->accept(this);
563 for (size_t i = 0; i < s->catches->dim; i++)
564 {
565 Catch *c = (*s->catches)[i];
566 visit(c);
567 }
568 }
569
visit(TryFinallyStatement * s)570 void visit(TryFinallyStatement *s)
571 {
572 buf->writestring("try");
573 buf->writenl();
574 buf->writeByte('{');
575 buf->writenl();
576 buf->level++;
577 s->_body->accept(this);
578 buf->level--;
579 buf->writeByte('}');
580 buf->writenl();
581 buf->writestring("finally");
582 buf->writenl();
583 if (s->finalbody->isScopeStatement())
584 {
585 s->finalbody->accept(this);
586 }
587 else
588 {
589 buf->level++;
590 s->finalbody->accept(this);
591 buf->level--;
592 }
593 buf->writeByte('}');
594 buf->writenl();
595 }
596
visit(OnScopeStatement * s)597 void visit(OnScopeStatement *s)
598 {
599 buf->writestring(Token::toChars(s->tok));
600 buf->writeByte(' ');
601 s->statement->accept(this);
602 }
603
visit(ThrowStatement * s)604 void visit(ThrowStatement *s)
605 {
606 buf->printf("throw ");
607 s->exp->accept(this);
608 buf->writeByte(';');
609 buf->writenl();
610 }
611
visit(DebugStatement * s)612 void visit(DebugStatement *s)
613 {
614 if (s->statement)
615 {
616 s->statement->accept(this);
617 }
618 }
619
visit(GotoStatement * s)620 void visit(GotoStatement *s)
621 {
622 buf->writestring("goto ");
623 buf->writestring(s->ident->toChars());
624 buf->writeByte(';');
625 buf->writenl();
626 }
627
visit(LabelStatement * s)628 void visit(LabelStatement *s)
629 {
630 buf->writestring(s->ident->toChars());
631 buf->writeByte(':');
632 buf->writenl();
633 if (s->statement)
634 s->statement->accept(this);
635 }
636
visit(AsmStatement * s)637 void visit(AsmStatement *s)
638 {
639 buf->writestring("asm { ");
640 Token *t = s->tokens;
641 buf->level++;
642 while (t)
643 {
644 buf->writestring(t->toChars());
645 if (t->next &&
646 t->value != TOKmin &&
647 t->value != TOKcomma && t->next->value != TOKcomma &&
648 t->value != TOKlbracket && t->next->value != TOKlbracket &&
649 t->next->value != TOKrbracket &&
650 t->value != TOKlparen && t->next->value != TOKlparen &&
651 t->next->value != TOKrparen &&
652 t->value != TOKdot && t->next->value != TOKdot)
653 {
654 buf->writeByte(' ');
655 }
656 t = t->next;
657 }
658 buf->level--;
659 buf->writestring("; }");
660 buf->writenl();
661 }
662
visit(ImportStatement * s)663 void visit(ImportStatement *s)
664 {
665 for (size_t i = 0; i < s->imports->dim; i++)
666 {
667 Dsymbol *imp = (*s->imports)[i];
668 imp->accept(this);
669 }
670 }
671
visit(Catch * c)672 void visit(Catch *c)
673 {
674 buf->writestring("catch");
675 if (c->type)
676 {
677 buf->writeByte('(');
678 typeToBuffer(c->type, c->ident);
679 buf->writeByte(')');
680 }
681 buf->writenl();
682 buf->writeByte('{');
683 buf->writenl();
684 buf->level++;
685 if (c->handler)
686 c->handler->accept(this);
687 buf->level--;
688 buf->writeByte('}');
689 buf->writenl();
690 }
691
692 ////////////////////////////////////////////////////////////////////////////
693
694 /**************************************************
695 * An entry point to pretty-print type.
696 */
typeToBuffer(Type * t,Identifier * ident)697 void typeToBuffer(Type *t, Identifier *ident)
698 {
699 if (t->ty == Tfunction)
700 {
701 visitFuncIdentWithPrefix((TypeFunction *)t, ident, NULL);
702 return;
703 }
704
705 visitWithMask(t, 0);
706
707 if (ident)
708 {
709 buf->writeByte(' ');
710 buf->writestring(ident->toChars());
711 }
712 }
713
visitWithMask(Type * t,unsigned char modMask)714 void visitWithMask(Type *t, unsigned char modMask)
715 {
716 // Tuples and functions don't use the type constructor syntax
717 if (modMask == t->mod ||
718 t->ty == Tfunction ||
719 t->ty == Ttuple)
720 {
721 t->accept(this);
722 }
723 else
724 {
725 unsigned char m = t->mod & ~(t->mod & modMask);
726 if (m & MODshared)
727 {
728 MODtoBuffer(buf, MODshared);
729 buf->writeByte('(');
730 }
731 if (m & MODwild)
732 {
733 MODtoBuffer(buf, MODwild);
734 buf->writeByte('(');
735 }
736 if (m & (MODconst | MODimmutable))
737 {
738 MODtoBuffer(buf, m & (MODconst | MODimmutable));
739 buf->writeByte('(');
740 }
741
742 t->accept(this);
743
744 if (m & (MODconst | MODimmutable))
745 buf->writeByte(')');
746 if (m & MODwild)
747 buf->writeByte(')');
748 if (m & MODshared)
749 buf->writeByte(')');
750 }
751 }
752
visit(Type * t)753 void visit(Type *t)
754 {
755 printf("t = %p, ty = %d\n", t, t->ty);
756 assert(0);
757 }
758
visit(TypeError *)759 void visit(TypeError *)
760 {
761 buf->writestring("_error_");
762 }
763
visit(TypeBasic * t)764 void visit(TypeBasic *t)
765 {
766 //printf("TypeBasic::toCBuffer2(t->mod = %d)\n", t->mod);
767 buf->writestring(t->dstring);
768 }
769
visit(TypeVector * t)770 void visit(TypeVector *t)
771 {
772 //printf("TypeVector::toCBuffer2(t->mod = %d)\n", t->mod);
773 buf->writestring("__vector(");
774 visitWithMask(t->basetype, t->mod);
775 buf->writestring(")");
776 }
777
visit(TypeSArray * t)778 void visit(TypeSArray *t)
779 {
780 visitWithMask(t->next, t->mod);
781 buf->writeByte('[');
782 sizeToBuffer(t->dim);
783 buf->writeByte(']');
784 }
785
visit(TypeDArray * t)786 void visit(TypeDArray *t)
787 {
788 Type *ut = t->castMod(0);
789 if (declstring)
790 goto L1;
791 if (ut->equals(Type::tstring))
792 buf->writestring("string");
793 else if (ut->equals(Type::twstring))
794 buf->writestring("wstring");
795 else if (ut->equals(Type::tdstring))
796 buf->writestring("dstring");
797 else
798 {
799 L1:
800 visitWithMask(t->next, t->mod);
801 buf->writestring("[]");
802 }
803 }
804
visit(TypeAArray * t)805 void visit(TypeAArray *t)
806 {
807 visitWithMask(t->next, t->mod);
808 buf->writeByte('[');
809 visitWithMask(t->index, 0);
810 buf->writeByte(']');
811 }
812
visit(TypePointer * t)813 void visit(TypePointer *t)
814 {
815 //printf("TypePointer::toCBuffer2() next = %d\n", t->next->ty);
816 if (t->next->ty == Tfunction)
817 visitFuncIdentWithPostfix((TypeFunction *)t->next, "function");
818 else
819 {
820 visitWithMask(t->next, t->mod);
821 buf->writeByte('*');
822 }
823 }
824
visit(TypeReference * t)825 void visit(TypeReference *t)
826 {
827 visitWithMask(t->next, t->mod);
828 buf->writeByte('&');
829 }
830
visit(TypeFunction * t)831 void visit(TypeFunction *t)
832 {
833 //printf("TypeFunction::toCBuffer2() t = %p, ref = %d\n", t, t->isref);
834 visitFuncIdentWithPostfix(t, NULL);
835 }
836
837 // callback for TypeFunction::attributesApply
838 struct PrePostAppendStrings
839 {
840 OutBuffer *buf;
841 bool isPostfixStyle;
842 bool isCtor;
843
fpPrePostAppendStrings844 static int fp(void *param, const char *str)
845 {
846 PrePostAppendStrings *p = (PrePostAppendStrings *)param;
847
848 // don't write 'ref' for ctors
849 if (p->isCtor && strcmp(str, "ref") == 0)
850 return 0;
851
852 if ( p->isPostfixStyle) p->buf->writeByte(' ');
853 p->buf->writestring(str);
854 if (!p->isPostfixStyle) p->buf->writeByte(' ');
855 return 0;
856 }
857 };
858
visitFuncIdentWithPostfix(TypeFunction * t,const char * ident)859 void visitFuncIdentWithPostfix(TypeFunction *t, const char *ident)
860 {
861 if (t->inuse)
862 {
863 t->inuse = 2; // flag error to caller
864 return;
865 }
866 t->inuse++;
867
868 PrePostAppendStrings pas;
869 pas.buf = buf;
870 pas.isCtor = false;
871 pas.isPostfixStyle = true;
872
873 if (t->linkage > LINKd && hgs->ddoc != 1 && !hgs->hdrgen)
874 {
875 linkageToBuffer(buf, t->linkage);
876 buf->writeByte(' ');
877 }
878
879 if (t->next)
880 {
881 typeToBuffer(t->next, NULL);
882 if (ident)
883 buf->writeByte(' ');
884 }
885 else if (hgs->ddoc)
886 buf->writestring("auto ");
887
888 if (ident)
889 buf->writestring(ident);
890
891 parametersToBuffer(t->parameters, t->varargs);
892
893 /* Use postfix style for attributes
894 */
895 if (t->mod)
896 {
897 buf->writeByte(' ');
898 MODtoBuffer(buf, t->mod);
899 }
900 t->attributesApply(&pas, &PrePostAppendStrings::fp);
901
902 t->inuse--;
903 }
visitFuncIdentWithPrefix(TypeFunction * t,Identifier * ident,TemplateDeclaration * td)904 void visitFuncIdentWithPrefix(TypeFunction *t, Identifier *ident, TemplateDeclaration *td)
905 {
906 if (t->inuse)
907 {
908 t->inuse = 2; // flag error to caller
909 return;
910 }
911 t->inuse++;
912
913 PrePostAppendStrings pas;
914 pas.buf = buf;
915 pas.isCtor = (ident == Id::ctor);
916 pas.isPostfixStyle = false;
917
918 /* Use 'storage class' (prefix) style for attributes
919 */
920 if (t->mod)
921 {
922 MODtoBuffer(buf, t->mod);
923 buf->writeByte(' ');
924 }
925 t->attributesApply(&pas, &PrePostAppendStrings::fp);
926
927 if (t->linkage > LINKd && hgs->ddoc != 1 && !hgs->hdrgen)
928 {
929 linkageToBuffer(buf, t->linkage);
930 buf->writeByte(' ');
931 }
932
933 if (ident && ident->toHChars2() != ident->toChars())
934 {
935 // Don't print return type for ctor, dtor, unittest, etc
936 }
937 else if (t->next)
938 {
939 typeToBuffer(t->next, NULL);
940 if (ident)
941 buf->writeByte(' ');
942 }
943 else if (hgs->ddoc)
944 buf->writestring("auto ");
945
946 if (ident)
947 buf->writestring(ident->toHChars2());
948
949 if (td)
950 {
951 buf->writeByte('(');
952 for (size_t i = 0; i < td->origParameters->dim; i++)
953 {
954 TemplateParameter *p = (*td->origParameters)[i];
955 if (i)
956 buf->writestring(", ");
957 p->accept(this);
958 }
959 buf->writeByte(')');
960 }
961 parametersToBuffer(t->parameters, t->varargs);
962
963 t->inuse--;
964 }
965
visit(TypeDelegate * t)966 void visit(TypeDelegate *t)
967 {
968 visitFuncIdentWithPostfix((TypeFunction *)t->next, "delegate");
969 }
970
visitTypeQualifiedHelper(TypeQualified * t)971 void visitTypeQualifiedHelper(TypeQualified *t)
972 {
973 for (size_t i = 0; i < t->idents.dim; i++)
974 {
975 RootObject *id = t->idents[i];
976
977 if (id->dyncast() == DYNCAST_DSYMBOL)
978 {
979 buf->writeByte('.');
980 TemplateInstance *ti = (TemplateInstance *)id;
981 ti->accept(this);
982 }
983 else if (id->dyncast() == DYNCAST_EXPRESSION)
984 {
985 buf->writeByte('[');
986 ((Expression *)id)->accept(this);
987 buf->writeByte(']');
988 }
989 else if (id->dyncast() == DYNCAST_TYPE)
990 {
991 buf->writeByte('[');
992 ((Type *)id)->accept(this);
993 buf->writeByte(']');
994 }
995 else
996 {
997 buf->writeByte('.');
998 buf->writestring(id->toChars());
999 }
1000 }
1001 }
1002
visit(TypeIdentifier * t)1003 void visit(TypeIdentifier *t)
1004 {
1005 buf->writestring(t->ident->toChars());
1006 visitTypeQualifiedHelper(t);
1007 }
1008
visit(TypeInstance * t)1009 void visit(TypeInstance *t)
1010 {
1011 t->tempinst->accept(this);
1012 visitTypeQualifiedHelper(t);
1013 }
1014
visit(TypeTypeof * t)1015 void visit(TypeTypeof *t)
1016 {
1017 buf->writestring("typeof(");
1018 t->exp->accept(this);
1019 buf->writeByte(')');
1020 visitTypeQualifiedHelper(t);
1021 }
1022
visit(TypeReturn * t)1023 void visit(TypeReturn *t)
1024 {
1025 buf->writestring("typeof(return)");
1026 visitTypeQualifiedHelper(t);
1027 }
1028
visit(TypeEnum * t)1029 void visit(TypeEnum *t)
1030 {
1031 buf->writestring(t->sym->toChars());
1032 }
1033
visit(TypeStruct * t)1034 void visit(TypeStruct *t)
1035 {
1036 // Bugzilla 13776: Don't use ti->toAlias() to avoid forward reference error
1037 // while printing messages.
1038 TemplateInstance *ti = t->sym->parent ? t->sym->parent->isTemplateInstance() : NULL;
1039 if (ti && ti->aliasdecl == t->sym)
1040 buf->writestring(hgs->fullQual ? ti->toPrettyChars() : ti->toChars());
1041 else
1042 buf->writestring(hgs->fullQual ? t->sym->toPrettyChars() : t->sym->toChars());
1043 }
1044
visit(TypeClass * t)1045 void visit(TypeClass *t)
1046 {
1047 // Bugzilla 13776: Don't use ti->toAlias() to avoid forward reference error
1048 // while printing messages.
1049 TemplateInstance *ti = t->sym->parent->isTemplateInstance();
1050 if (ti && ti->aliasdecl == t->sym)
1051 buf->writestring(hgs->fullQual ? ti->toPrettyChars() : ti->toChars());
1052 else
1053 buf->writestring(hgs->fullQual ? t->sym->toPrettyChars() : t->sym->toChars());
1054 }
1055
visit(TypeTuple * t)1056 void visit(TypeTuple *t)
1057 {
1058 parametersToBuffer(t->arguments, 0);
1059 }
1060
visit(TypeSlice * t)1061 void visit(TypeSlice *t)
1062 {
1063 visitWithMask(t->next, t->mod);
1064
1065 buf->writeByte('[');
1066 sizeToBuffer(t->lwr);
1067 buf->writestring(" .. ");
1068 sizeToBuffer(t->upr);
1069 buf->writeByte(']');
1070 }
1071
visit(TypeNull *)1072 void visit(TypeNull *)
1073 {
1074 buf->writestring("typeof(null)");
1075 }
1076
1077 ////////////////////////////////////////////////////////////////////////////
1078
visit(Dsymbol * s)1079 void visit(Dsymbol *s)
1080 {
1081 buf->writestring(s->toChars());
1082 }
1083
visit(StaticAssert * s)1084 void visit(StaticAssert *s)
1085 {
1086 buf->writestring(s->kind());
1087 buf->writeByte('(');
1088 s->exp->accept(this);
1089 if (s->msg)
1090 {
1091 buf->writestring(", ");
1092 s->msg->accept(this);
1093 }
1094 buf->writestring(");");
1095 buf->writenl();
1096 }
1097
visit(DebugSymbol * s)1098 void visit(DebugSymbol *s)
1099 {
1100 buf->writestring("debug = ");
1101 if (s->ident)
1102 buf->writestring(s->ident->toChars());
1103 else
1104 buf->printf("%u", s->level);
1105 buf->writestring(";");
1106 buf->writenl();
1107 }
1108
visit(VersionSymbol * s)1109 void visit(VersionSymbol *s)
1110 {
1111 buf->writestring("version = ");
1112 if (s->ident)
1113 buf->writestring(s->ident->toChars());
1114 else
1115 buf->printf("%u", s->level);
1116 buf->writestring(";");
1117 buf->writenl();
1118 }
1119
visit(EnumMember * em)1120 void visit(EnumMember *em)
1121 {
1122 if (em->type)
1123 typeToBuffer(em->type, em->ident);
1124 else
1125 buf->writestring(em->ident->toChars());
1126 if (em->value())
1127 {
1128 buf->writestring(" = ");
1129 em->value()->accept(this);
1130 }
1131 }
1132
visit(Import * imp)1133 void visit(Import *imp)
1134 {
1135 if (hgs->hdrgen && imp->id == Id::object)
1136 return; // object is imported by default
1137
1138 if (imp->isstatic)
1139 buf->writestring("static ");
1140 buf->writestring("import ");
1141 if (imp->aliasId)
1142 {
1143 buf->printf("%s = ", imp->aliasId->toChars());
1144 }
1145 if (imp->packages && imp->packages->dim)
1146 {
1147 for (size_t i = 0; i < imp->packages->dim; i++)
1148 {
1149 Identifier *pid = (*imp->packages)[i];
1150 buf->printf("%s.", pid->toChars());
1151 }
1152 }
1153 buf->printf("%s", imp->id->toChars());
1154 if (imp->names.dim)
1155 {
1156 buf->writestring(" : ");
1157 for (size_t i = 0; i < imp->names.dim; i++)
1158 {
1159 if (i)
1160 buf->writestring(", ");
1161
1162 Identifier *name = imp->names[i];
1163 Identifier *alias = imp->aliases[i];
1164 if (alias)
1165 buf->printf("%s = %s", alias->toChars(), name->toChars());
1166 else
1167 buf->printf("%s", name->toChars());
1168 }
1169 }
1170 buf->printf(";");
1171 buf->writenl();
1172 }
1173
visit(AliasThis * d)1174 void visit(AliasThis *d)
1175 {
1176 buf->writestring("alias ");
1177 buf->writestring(d->ident->toChars());
1178 buf->writestring(" this;\n");
1179 }
1180
visit(AttribDeclaration * d)1181 void visit(AttribDeclaration *d)
1182 {
1183 if (!d->decl)
1184 {
1185 buf->writeByte(';');
1186 buf->writenl();
1187 return;
1188 }
1189
1190 if (d->decl->dim == 0)
1191 buf->writestring("{}");
1192 else if (hgs->hdrgen && d->decl->dim == 1 && (*d->decl)[0]->isUnitTestDeclaration())
1193 {
1194 // hack for bugzilla 8081
1195 buf->writestring("{}");
1196 }
1197 else if (d->decl->dim == 1)
1198 {
1199 ((*d->decl)[0])->accept(this);
1200 return;
1201 }
1202 else
1203 {
1204 buf->writenl();
1205 buf->writeByte('{');
1206 buf->writenl();
1207 buf->level++;
1208 for (size_t i = 0; i < d->decl->dim; i++)
1209 {
1210 Dsymbol *de = (*d->decl)[i];
1211 de->accept(this);
1212 }
1213 buf->level--;
1214 buf->writeByte('}');
1215 }
1216 buf->writenl();
1217 }
1218
visit(StorageClassDeclaration * d)1219 void visit(StorageClassDeclaration *d)
1220 {
1221 if (stcToBuffer(buf, d->stc))
1222 buf->writeByte(' ');
1223 visit((AttribDeclaration *)d);
1224 }
1225
visit(DeprecatedDeclaration * d)1226 void visit(DeprecatedDeclaration *d)
1227 {
1228 buf->writestring("deprecated(");
1229 d->msg->accept(this);
1230 buf->writestring(") ");
1231 visit((AttribDeclaration *)d);
1232 }
1233
visit(LinkDeclaration * d)1234 void visit(LinkDeclaration *d)
1235 {
1236 const char *p;
1237
1238 switch (d->linkage)
1239 {
1240 case LINKd: p = "D"; break;
1241 case LINKc: p = "C"; break;
1242 case LINKcpp: p = "C++"; break;
1243 case LINKwindows: p = "Windows"; break;
1244 case LINKpascal: p = "Pascal"; break;
1245 case LINKobjc: p = "Objective-C"; break;
1246 default:
1247 assert(0);
1248 break;
1249 }
1250 buf->writestring("extern (");
1251 buf->writestring(p);
1252 buf->writestring(") ");
1253 visit((AttribDeclaration *)d);
1254 }
1255
visit(CPPMangleDeclaration * d)1256 void visit(CPPMangleDeclaration *d)
1257 {
1258 const char *p;
1259
1260 switch (d->cppmangle)
1261 {
1262 case CPPMANGLEclass: p = "class"; break;
1263 case CPPMANGLEstruct: p = "struct"; break;
1264 default:
1265 assert(0);
1266 break;
1267 }
1268 buf->writestring("extern (C++, ");
1269 buf->writestring(p);
1270 buf->writestring(") ");
1271 visit((AttribDeclaration *)d);
1272 }
1273
visit(ProtDeclaration * d)1274 void visit(ProtDeclaration *d)
1275 {
1276 protectionToBuffer(buf, d->protection);
1277 buf->writeByte(' ');
1278 visit((AttribDeclaration *)d);
1279 }
1280
visit(AlignDeclaration * d)1281 void visit(AlignDeclaration *d)
1282 {
1283 if (!d->ealign)
1284 buf->printf("align ");
1285 else
1286 buf->printf("align (%s)", d->ealign->toChars());
1287 visit((AttribDeclaration *)d);
1288 }
1289
visit(AnonDeclaration * d)1290 void visit(AnonDeclaration *d)
1291 {
1292 buf->printf(d->isunion ? "union" : "struct");
1293 buf->writenl();
1294 buf->writestring("{");
1295 buf->writenl();
1296 buf->level++;
1297 if (d->decl)
1298 {
1299 for (size_t i = 0; i < d->decl->dim; i++)
1300 {
1301 Dsymbol *de = (*d->decl)[i];
1302 de->accept(this);
1303 }
1304 }
1305 buf->level--;
1306 buf->writestring("}");
1307 buf->writenl();
1308 }
1309
visit(PragmaDeclaration * d)1310 void visit(PragmaDeclaration *d)
1311 {
1312 buf->printf("pragma (%s", d->ident->toChars());
1313 if (d->args && d->args->dim)
1314 {
1315 buf->writestring(", ");
1316 argsToBuffer(d->args);
1317 }
1318 buf->writeByte(')');
1319 visit((AttribDeclaration *)d);
1320 }
1321
visit(ConditionalDeclaration * d)1322 void visit(ConditionalDeclaration *d)
1323 {
1324 d->condition->accept(this);
1325 if (d->decl || d->elsedecl)
1326 {
1327 buf->writenl();
1328 buf->writeByte('{');
1329 buf->writenl();
1330 buf->level++;
1331 if (d->decl)
1332 {
1333 for (size_t i = 0; i < d->decl->dim; i++)
1334 {
1335 Dsymbol *de = (*d->decl)[i];
1336 de->accept(this);
1337 }
1338 }
1339 buf->level--;
1340 buf->writeByte('}');
1341 if (d->elsedecl)
1342 {
1343 buf->writenl();
1344 buf->writestring("else");
1345 buf->writenl();
1346 buf->writeByte('{');
1347 buf->writenl();
1348 buf->level++;
1349 for (size_t i = 0; i < d->elsedecl->dim; i++)
1350 {
1351 Dsymbol *de = (*d->elsedecl)[i];
1352 de->accept(this);
1353 }
1354 buf->level--;
1355 buf->writeByte('}');
1356 }
1357 }
1358 else
1359 buf->writeByte(':');
1360 buf->writenl();
1361 }
1362
visit(CompileDeclaration * d)1363 void visit(CompileDeclaration *d)
1364 {
1365 buf->writestring("mixin(");
1366 d->exp->accept(this);
1367 buf->writestring(");");
1368 buf->writenl();
1369 }
1370
visit(UserAttributeDeclaration * d)1371 void visit(UserAttributeDeclaration *d)
1372 {
1373 buf->writestring("@(");
1374 argsToBuffer(d->atts);
1375 buf->writeByte(')');
1376 visit((AttribDeclaration *)d);
1377 }
1378
visit(TemplateDeclaration * d)1379 void visit(TemplateDeclaration *d)
1380 {
1381 if ((hgs->hdrgen || hgs->fullDump) && visitEponymousMember(d))
1382 return;
1383
1384 if (hgs->ddoc)
1385 buf->writestring(d->kind());
1386 else
1387 buf->writestring("template");
1388 buf->writeByte(' ');
1389 buf->writestring(d->ident->toChars());
1390 buf->writeByte('(');
1391 visitTemplateParameters(hgs->ddoc ? d->origParameters : d->parameters);
1392 buf->writeByte(')');
1393 visitTemplateConstraint(d->constraint);
1394
1395 if (hgs->hdrgen || hgs->fullDump)
1396 {
1397 hgs->tpltMember++;
1398 buf->writenl();
1399 buf->writeByte('{');
1400 buf->writenl();
1401 buf->level++;
1402 for (size_t i = 0; i < d->members->dim; i++)
1403 {
1404 Dsymbol *s = (*d->members)[i];
1405 s->accept(this);
1406 }
1407 buf->level--;
1408 buf->writeByte('}');
1409 buf->writenl();
1410 hgs->tpltMember--;
1411 }
1412 }
1413
visitEponymousMember(TemplateDeclaration * d)1414 bool visitEponymousMember(TemplateDeclaration *d)
1415 {
1416 if (!d->members || d->members->dim != 1)
1417 return false;
1418
1419 Dsymbol *onemember = (*d->members)[0];
1420 if (onemember->ident != d->ident)
1421 return false;
1422
1423 if (FuncDeclaration *fd = onemember->isFuncDeclaration())
1424 {
1425 assert(fd->type);
1426 if (stcToBuffer(buf, fd->storage_class))
1427 buf->writeByte(' ');
1428 functionToBufferFull((TypeFunction *)fd->type, buf, d->ident, hgs, d);
1429 visitTemplateConstraint(d->constraint);
1430
1431 hgs->tpltMember++;
1432 bodyToBuffer(fd);
1433 hgs->tpltMember--;
1434 return true;
1435 }
1436 if (AggregateDeclaration *ad = onemember->isAggregateDeclaration())
1437 {
1438 buf->writestring(ad->kind());
1439 buf->writeByte(' ');
1440 buf->writestring(ad->ident->toChars());
1441 buf->writeByte('(');
1442 visitTemplateParameters(hgs->ddoc ? d->origParameters : d->parameters);
1443 buf->writeByte(')');
1444 visitTemplateConstraint(d->constraint);
1445 visitBaseClasses(ad->isClassDeclaration());
1446
1447 hgs->tpltMember++;
1448 if (ad->members)
1449 {
1450 buf->writenl();
1451 buf->writeByte('{');
1452 buf->writenl();
1453 buf->level++;
1454 for (size_t i = 0; i < ad->members->dim; i++)
1455 {
1456 Dsymbol *s = (*ad->members)[i];
1457 s->accept(this);
1458 }
1459 buf->level--;
1460 buf->writeByte('}');
1461 }
1462 else
1463 buf->writeByte(';');
1464 buf->writenl();
1465 hgs->tpltMember--;
1466 return true;
1467 }
1468 if (VarDeclaration *vd = onemember->isVarDeclaration())
1469 {
1470 if (d->constraint)
1471 return false;
1472
1473 if (stcToBuffer(buf, vd->storage_class))
1474 buf->writeByte(' ');
1475 if (vd->type)
1476 typeToBuffer(vd->type, vd->ident);
1477 else
1478 buf->writestring(vd->ident->toChars());
1479
1480 buf->writeByte('(');
1481 visitTemplateParameters(hgs->ddoc ? d->origParameters : d->parameters);
1482 buf->writeByte(')');
1483
1484 if (vd->_init)
1485 {
1486 buf->writestring(" = ");
1487 ExpInitializer *ie = vd->_init->isExpInitializer();
1488 if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
1489 ((AssignExp *)ie->exp)->e2->accept(this);
1490 else
1491 vd->_init->accept(this);
1492 }
1493 buf->writeByte(';');
1494 buf->writenl();
1495 return true;
1496 }
1497
1498 return false;
1499 }
visitTemplateParameters(TemplateParameters * parameters)1500 void visitTemplateParameters(TemplateParameters *parameters)
1501 {
1502 if (!parameters || !parameters->dim)
1503 return;
1504 for (size_t i = 0; i < parameters->dim; i++)
1505 {
1506 TemplateParameter *p = (*parameters)[i];
1507 if (i)
1508 buf->writestring(", ");
1509 p->accept(this);
1510 }
1511 }
visitTemplateConstraint(Expression * constraint)1512 void visitTemplateConstraint(Expression *constraint)
1513 {
1514 if (!constraint)
1515 return;
1516 buf->writestring(" if (");
1517 constraint->accept(this);
1518 buf->writeByte(')');
1519 }
1520
visit(TemplateInstance * ti)1521 void visit(TemplateInstance *ti)
1522 {
1523 buf->writestring(ti->name->toChars());
1524 tiargsToBuffer(ti);
1525
1526 if (hgs->fullDump)
1527 {
1528 buf->writenl();
1529 if (ti->aliasdecl)
1530 {
1531 // the ti.aliasDecl is the instantiated body
1532 // if we have it, print it.
1533 ti->aliasdecl->accept(this);
1534 }
1535 }
1536 }
1537
visit(TemplateMixin * tm)1538 void visit(TemplateMixin *tm)
1539 {
1540 buf->writestring("mixin ");
1541
1542 typeToBuffer(tm->tqual, NULL);
1543 tiargsToBuffer(tm);
1544
1545 if (tm->ident && memcmp(tm->ident->toChars(), "__mixin", 7) != 0)
1546 {
1547 buf->writeByte(' ');
1548 buf->writestring(tm->ident->toChars());
1549 }
1550 buf->writeByte(';');
1551 buf->writenl();
1552 }
1553
tiargsToBuffer(TemplateInstance * ti)1554 void tiargsToBuffer(TemplateInstance *ti)
1555 {
1556 buf->writeByte('!');
1557 if (ti->nest)
1558 {
1559 buf->writestring("(...)");
1560 return;
1561 }
1562 if (!ti->tiargs)
1563 {
1564 buf->writestring("()");
1565 return;
1566 }
1567
1568 if (ti->tiargs->dim == 1)
1569 {
1570 RootObject *oarg = (*ti->tiargs)[0];
1571 if (Type *t = isType(oarg))
1572 {
1573 if (t->equals(Type::tstring) ||
1574 t->equals(Type::twstring) ||
1575 t->equals(Type::tdstring) ||
1576 (t->mod == 0 &&
1577 (t->isTypeBasic() ||
1578 (t->ty == Tident && ((TypeIdentifier *)t)->idents.dim == 0))))
1579 {
1580 buf->writestring(t->toChars());
1581 return;
1582 }
1583 }
1584 else if (Expression *e = isExpression(oarg))
1585 {
1586 if (e->op == TOKint64 ||
1587 e->op == TOKfloat64 ||
1588 e->op == TOKnull ||
1589 e->op == TOKstring ||
1590 e->op == TOKthis)
1591 {
1592 buf->writestring(e->toChars());
1593 return;
1594 }
1595 }
1596 }
1597 buf->writeByte('(');
1598 ti->nest++;
1599 for (size_t i = 0; i < ti->tiargs->dim; i++)
1600 {
1601 RootObject *arg = (*ti->tiargs)[i];
1602 if (i)
1603 buf->writestring(", ");
1604 objectToBuffer(arg);
1605 }
1606 ti->nest--;
1607 buf->writeByte(')');
1608 }
1609
1610 /****************************************
1611 * This makes a 'pretty' version of the template arguments.
1612 * It's analogous to genIdent() which makes a mangled version.
1613 */
objectToBuffer(RootObject * oarg)1614 void objectToBuffer(RootObject *oarg)
1615 {
1616 //printf("objectToBuffer()\n");
1617
1618 /* The logic of this should match what genIdent() does. The _dynamic_cast()
1619 * function relies on all the pretty strings to be unique for different classes
1620 * (see Bugzilla 7375).
1621 * Perhaps it would be better to demangle what genIdent() does.
1622 */
1623 if (Type *t = isType(oarg))
1624 {
1625 //printf("\tt: %s ty = %d\n", t->toChars(), t->ty);
1626 typeToBuffer(t, NULL);
1627 }
1628 else if (Expression *e = isExpression(oarg))
1629 {
1630 if (e->op == TOKvar)
1631 e = e->optimize(WANTvalue); // added to fix Bugzilla 7375
1632 e->accept(this);
1633 }
1634 else if (Dsymbol *s = isDsymbol(oarg))
1635 {
1636 const char *p = s->ident ? s->ident->toChars() : s->toChars();
1637 buf->writestring(p);
1638 }
1639 else if (Tuple *v = isTuple(oarg))
1640 {
1641 Objects *args = &v->objects;
1642 for (size_t i = 0; i < args->dim; i++)
1643 {
1644 RootObject *arg = (*args)[i];
1645 if (i)
1646 buf->writestring(", ");
1647 objectToBuffer(arg);
1648 }
1649 }
1650 else if (!oarg)
1651 {
1652 buf->writestring("NULL");
1653 }
1654 else
1655 {
1656 assert(0);
1657 }
1658 }
1659
visit(EnumDeclaration * d)1660 void visit(EnumDeclaration *d)
1661 {
1662 EnumDeclaration *oldInEnumDecl = inEnumDecl;
1663 inEnumDecl = d;
1664 buf->writestring("enum ");
1665 if (d->ident)
1666 {
1667 buf->writestring(d->ident->toChars());
1668 buf->writeByte(' ');
1669 }
1670 if (d->memtype)
1671 {
1672 buf->writestring(": ");
1673 typeToBuffer(d->memtype, NULL);
1674 }
1675 if (!d->members)
1676 {
1677 buf->writeByte(';');
1678 buf->writenl();
1679 inEnumDecl = oldInEnumDecl;
1680 return;
1681 }
1682 buf->writenl();
1683 buf->writeByte('{');
1684 buf->writenl();
1685 buf->level++;
1686 for (size_t i = 0; i < d->members->dim; i++)
1687 {
1688 EnumMember *em = (*d->members)[i]->isEnumMember();
1689 if (!em)
1690 continue;
1691 em->accept(this);
1692 buf->writeByte(',');
1693 buf->writenl();
1694 }
1695 buf->level--;
1696 buf->writeByte('}');
1697 buf->writenl();
1698 inEnumDecl = oldInEnumDecl;
1699 }
1700
visit(Nspace * d)1701 void visit(Nspace *d)
1702 {
1703 buf->writestring("extern (C++, ");
1704 buf->writestring(d->ident->toChars());
1705 buf->writeByte(')');
1706 buf->writenl();
1707 buf->writeByte('{');
1708 buf->writenl();
1709 buf->level++;
1710 for (size_t i = 0; i < d->members->dim; i++)
1711 {
1712 Dsymbol *s = (*d->members)[i];
1713 s->accept(this);
1714 }
1715 buf->level--;
1716 buf->writeByte('}');
1717 buf->writenl();
1718 }
1719
visit(StructDeclaration * d)1720 void visit(StructDeclaration *d)
1721 {
1722 buf->printf("%s ", d->kind());
1723 if (!d->isAnonymous())
1724 buf->writestring(d->toChars());
1725 if (!d->members)
1726 {
1727 buf->writeByte(';');
1728 buf->writenl();
1729 return;
1730 }
1731 buf->writenl();
1732 buf->writeByte('{');
1733 buf->writenl();
1734 buf->level++;
1735 for (size_t i = 0; i < d->members->dim; i++)
1736 {
1737 Dsymbol *s = (*d->members)[i];
1738 s->accept(this);
1739 }
1740 buf->level--;
1741 buf->writeByte('}');
1742 buf->writenl();
1743 }
1744
visit(ClassDeclaration * d)1745 void visit(ClassDeclaration *d)
1746 {
1747 if (!d->isAnonymous())
1748 {
1749 buf->writestring(d->kind());
1750 buf->writeByte(' ');
1751 buf->writestring(d->ident->toChars());
1752 }
1753 visitBaseClasses(d);
1754 if (d->members)
1755 {
1756 buf->writenl();
1757 buf->writeByte('{');
1758 buf->writenl();
1759 buf->level++;
1760 for (size_t i = 0; i < d->members->dim; i++)
1761 {
1762 Dsymbol *s = (*d->members)[i];
1763 s->accept(this);
1764 }
1765 buf->level--;
1766 buf->writeByte('}');
1767 }
1768 else
1769 buf->writeByte(';');
1770 buf->writenl();
1771 }
1772
visitBaseClasses(ClassDeclaration * d)1773 void visitBaseClasses(ClassDeclaration *d)
1774 {
1775 if (!d || !d->baseclasses->dim)
1776 return;
1777
1778 buf->writestring(" : ");
1779 for (size_t i = 0; i < d->baseclasses->dim; i++)
1780 {
1781 if (i)
1782 buf->writestring(", ");
1783 BaseClass *b = (*d->baseclasses)[i];
1784 typeToBuffer(b->type, NULL);
1785 }
1786 }
1787
visit(AliasDeclaration * d)1788 void visit(AliasDeclaration *d)
1789 {
1790 buf->writestring("alias ");
1791 if (d->aliassym)
1792 {
1793 buf->writestring(d->ident->toChars());
1794 buf->writestring(" = ");
1795 if (stcToBuffer(buf, d->storage_class))
1796 buf->writeByte(' ');
1797 d->aliassym->accept(this);
1798 }
1799 else if (d->type->ty == Tfunction)
1800 {
1801 if (stcToBuffer(buf, d->storage_class))
1802 buf->writeByte(' ');
1803 typeToBuffer(d->type, d->ident);
1804 }
1805 else
1806 {
1807 declstring = (d->ident == Id::string || d->ident == Id::wstring || d->ident == Id::dstring);
1808 buf->writestring(d->ident->toChars());
1809 buf->writestring(" = ");
1810 if (stcToBuffer(buf, d->storage_class))
1811 buf->writeByte(' ');
1812 typeToBuffer(d->type, NULL);
1813 declstring = false;
1814 }
1815 buf->writeByte(';');
1816 buf->writenl();
1817 }
1818
visit(VarDeclaration * d)1819 void visit(VarDeclaration *d)
1820 {
1821 visitVarDecl(d, false);
1822 buf->writeByte(';');
1823 buf->writenl();
1824 }
visitVarDecl(VarDeclaration * v,bool anywritten)1825 void visitVarDecl(VarDeclaration *v, bool anywritten)
1826 {
1827 if (anywritten)
1828 {
1829 buf->writestring(", ");
1830 buf->writestring(v->ident->toChars());
1831 }
1832 else
1833 {
1834 if (stcToBuffer(buf, v->storage_class))
1835 buf->writeByte(' ');
1836 if (v->type)
1837 typeToBuffer(v->type, v->ident);
1838 else
1839 buf->writestring(v->ident->toChars());
1840 }
1841 if (v->_init)
1842 {
1843 buf->writestring(" = ");
1844 ExpInitializer *ie = v->_init->isExpInitializer();
1845 if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
1846 ((AssignExp *)ie->exp)->e2->accept(this);
1847 else
1848 v->_init->accept(this);
1849 }
1850 }
1851
visit(FuncDeclaration * f)1852 void visit(FuncDeclaration *f)
1853 {
1854 //printf("FuncDeclaration::toCBuffer() '%s'\n", f->toChars());
1855
1856 if (stcToBuffer(buf, f->storage_class))
1857 buf->writeByte(' ');
1858 TypeFunction *tf = (TypeFunction *)f->type;
1859 typeToBuffer(tf, f->ident);
1860 if (hgs->hdrgen)
1861 {
1862 // if the return type is missing (e.g. ref functions or auto)
1863 if (!tf->next || f->storage_class & STCauto)
1864 {
1865 hgs->autoMember++;
1866 bodyToBuffer(f);
1867 hgs->autoMember--;
1868 }
1869 else if (hgs->tpltMember == 0 && global.params.hdrStripPlainFunctions)
1870 {
1871 buf->writeByte(';');
1872 buf->writenl();
1873 }
1874 else
1875 bodyToBuffer(f);
1876 }
1877 else
1878 bodyToBuffer(f);
1879 }
1880
bodyToBuffer(FuncDeclaration * f)1881 void bodyToBuffer(FuncDeclaration *f)
1882 {
1883 if (!f->fbody || (hgs->hdrgen && global.params.hdrStripPlainFunctions && !hgs->autoMember && !hgs->tpltMember))
1884 {
1885 buf->writeByte(';');
1886 buf->writenl();
1887 return;
1888 }
1889
1890 int savetlpt = hgs->tpltMember;
1891 int saveauto = hgs->autoMember;
1892 hgs->tpltMember = 0;
1893 hgs->autoMember = 0;
1894
1895 buf->writenl();
1896
1897 // in{}
1898 if (f->frequire)
1899 {
1900 buf->writestring("in");
1901 buf->writenl();
1902 f->frequire->accept(this);
1903 }
1904
1905 // out{}
1906 if (f->fensure)
1907 {
1908 buf->writestring("out");
1909 if (f->outId)
1910 {
1911 buf->writeByte('(');
1912 buf->writestring(f->outId->toChars());
1913 buf->writeByte(')');
1914 }
1915 buf->writenl();
1916 f->fensure->accept(this);
1917 }
1918
1919 if (f->frequire || f->fensure)
1920 {
1921 buf->writestring("body");
1922 buf->writenl();
1923 }
1924
1925 buf->writeByte('{');
1926 buf->writenl();
1927 buf->level++;
1928 f->fbody->accept(this);
1929 buf->level--;
1930 buf->writeByte('}');
1931 buf->writenl();
1932
1933 hgs->tpltMember = savetlpt;
1934 hgs->autoMember = saveauto;
1935 }
1936
visit(FuncLiteralDeclaration * f)1937 void visit(FuncLiteralDeclaration *f)
1938 {
1939 if (f->type->ty == Terror)
1940 {
1941 buf->writestring("__error");
1942 return;
1943 }
1944
1945 if (f->tok != TOKreserved)
1946 {
1947 buf->writestring(f->kind());
1948 buf->writeByte(' ');
1949 }
1950
1951 TypeFunction *tf = (TypeFunction *)f->type;
1952 // Don't print tf->mod, tf->trust, and tf->linkage
1953 if (!f->inferRetType && tf->next)
1954 typeToBuffer(tf->next, NULL);
1955 parametersToBuffer(tf->parameters, tf->varargs);
1956
1957 CompoundStatement *cs = f->fbody->isCompoundStatement();
1958 Statement *s1;
1959 if (f->semanticRun >= PASSsemantic3done && cs)
1960 {
1961 s1 = (*cs->statements)[cs->statements->dim - 1];
1962 }
1963 else
1964 s1 = !cs ? f->fbody : NULL;
1965 ReturnStatement *rs = s1 ? s1->isReturnStatement() : NULL;
1966 if (rs && rs->exp)
1967 {
1968 buf->writestring(" => ");
1969 rs->exp->accept(this);
1970 }
1971 else
1972 {
1973 hgs->tpltMember++;
1974 bodyToBuffer(f);
1975 hgs->tpltMember--;
1976 }
1977 }
1978
visit(PostBlitDeclaration * d)1979 void visit(PostBlitDeclaration *d)
1980 {
1981 if (stcToBuffer(buf, d->storage_class))
1982 buf->writeByte(' ');
1983 buf->writestring("this(this)");
1984 bodyToBuffer(d);
1985 }
1986
visit(DtorDeclaration * d)1987 void visit(DtorDeclaration *d)
1988 {
1989 if (d->storage_class & STCtrusted)
1990 buf->writestring("@trusted ");
1991 if (d->storage_class & STCsafe)
1992 buf->writestring("@safe ");
1993 if (d->storage_class & STCnogc)
1994 buf->writestring("@nogc ");
1995 if (d->storage_class & STCdisable)
1996 buf->writestring("@disable ");
1997
1998 buf->writestring("~this()");
1999 bodyToBuffer(d);
2000 }
2001
visit(StaticCtorDeclaration * d)2002 void visit(StaticCtorDeclaration *d)
2003 {
2004 if (stcToBuffer(buf, d->storage_class & ~STCstatic))
2005 buf->writeByte(' ');
2006 if (d->isSharedStaticCtorDeclaration())
2007 buf->writestring("shared ");
2008 buf->writestring("static this()");
2009 if (hgs->hdrgen && !hgs->tpltMember)
2010 {
2011 buf->writeByte(';');
2012 buf->writenl();
2013 }
2014 else
2015 bodyToBuffer(d);
2016 }
2017
visit(StaticDtorDeclaration * d)2018 void visit(StaticDtorDeclaration *d)
2019 {
2020 if (hgs->hdrgen)
2021 return;
2022 if (stcToBuffer(buf, d->storage_class & ~STCstatic))
2023 buf->writeByte(' ');
2024 if (d->isSharedStaticDtorDeclaration())
2025 buf->writestring("shared ");
2026 buf->writestring("static ~this()");
2027 bodyToBuffer(d);
2028 }
2029
visit(InvariantDeclaration * d)2030 void visit(InvariantDeclaration *d)
2031 {
2032 if (hgs->hdrgen)
2033 return;
2034 if (stcToBuffer(buf, d->storage_class))
2035 buf->writeByte(' ');
2036 buf->writestring("invariant");
2037 bodyToBuffer(d);
2038 }
2039
visit(UnitTestDeclaration * d)2040 void visit(UnitTestDeclaration *d)
2041 {
2042 if (hgs->hdrgen)
2043 return;
2044 if (stcToBuffer(buf, d->storage_class))
2045 buf->writeByte(' ');
2046 buf->writestring("unittest");
2047 bodyToBuffer(d);
2048 }
2049
visit(NewDeclaration * d)2050 void visit(NewDeclaration *d)
2051 {
2052 if (stcToBuffer(buf, d->storage_class & ~STCstatic))
2053 buf->writeByte(' ');
2054 buf->writestring("new");
2055 parametersToBuffer(d->parameters, d->varargs);
2056 bodyToBuffer(d);
2057 }
2058
visit(DeleteDeclaration * d)2059 void visit(DeleteDeclaration *d)
2060 {
2061 if (stcToBuffer(buf, d->storage_class & ~STCstatic))
2062 buf->writeByte(' ');
2063 buf->writestring("delete");
2064 parametersToBuffer(d->parameters, 0);
2065 bodyToBuffer(d);
2066 }
2067
2068 ////////////////////////////////////////////////////////////////////////////
2069
visit(ErrorInitializer *)2070 void visit(ErrorInitializer *)
2071 {
2072 buf->writestring("__error__");
2073 }
2074
visit(VoidInitializer *)2075 void visit(VoidInitializer *)
2076 {
2077 buf->writestring("void");
2078 }
2079
visit(StructInitializer * si)2080 void visit(StructInitializer *si)
2081 {
2082 //printf("StructInitializer::toCBuffer()\n");
2083 buf->writeByte('{');
2084 for (size_t i = 0; i < si->field.dim; i++)
2085 {
2086 if (i)
2087 buf->writestring(", ");
2088 if (Identifier *id = si->field[i])
2089 {
2090 buf->writestring(id->toChars());
2091 buf->writeByte(':');
2092 }
2093 if (Initializer *iz = si->value[i])
2094 iz->accept(this);
2095 }
2096 buf->writeByte('}');
2097 }
2098
visit(ArrayInitializer * ai)2099 void visit(ArrayInitializer *ai)
2100 {
2101 buf->writeByte('[');
2102 for (size_t i = 0; i < ai->index.dim; i++)
2103 {
2104 if (i)
2105 buf->writestring(", ");
2106 if (Expression *ex = ai->index[i])
2107 {
2108 ex->accept(this);
2109 buf->writeByte(':');
2110 }
2111 if (Initializer *iz = ai->value[i])
2112 iz->accept(this);
2113 }
2114 buf->writeByte(']');
2115 }
2116
visit(ExpInitializer * ei)2117 void visit(ExpInitializer *ei)
2118 {
2119 ei->exp->accept(this);
2120 }
2121
2122 ////////////////////////////////////////////////////////////////////////////
2123
2124 /**************************************************
2125 * Write out argument list to buf.
2126 */
2127 void argsToBuffer(Expressions *expressions, Expression *basis = NULL)
2128 {
2129 if (!expressions || !expressions->dim)
2130 return;
2131
2132 for (size_t i = 0; i < expressions->dim; i++)
2133 {
2134 Expression *el = (*expressions)[i];
2135 if (i)
2136 buf->writestring(", ");
2137 if (!el)
2138 el = basis;
2139 if (el)
2140 expToBuffer(el, PREC_assign);
2141 }
2142 }
2143
sizeToBuffer(Expression * e)2144 void sizeToBuffer(Expression *e)
2145 {
2146 if (e->type == Type::tsize_t)
2147 {
2148 Expression *ex = (e->op == TOKcast ? ((CastExp *)e)->e1 : e);
2149 ex = ex->optimize(WANTvalue);
2150
2151 dinteger_t uval = ex->op == TOKint64 ? ex->toInteger() : (dinteger_t)-1;
2152 if ((sinteger_t)uval >= 0)
2153 {
2154 dinteger_t sizemax;
2155 if (Target::ptrsize == 4)
2156 sizemax = 0xFFFFFFFFUL;
2157 else if (Target::ptrsize == 8)
2158 sizemax = 0xFFFFFFFFFFFFFFFFULL;
2159 else
2160 assert(0);
2161 if (uval <= sizemax && uval <= 0x7FFFFFFFFFFFFFFFULL)
2162 {
2163 buf->printf("%llu", uval);
2164 return;
2165 }
2166 }
2167 }
2168 expToBuffer(e, PREC_assign);
2169 }
2170
2171 /**************************************************
2172 * Write expression out to buf, but wrap it
2173 * in ( ) if its precedence is less than pr.
2174 */
expToBuffer(Expression * e,PREC pr)2175 void expToBuffer(Expression *e, PREC pr)
2176 {
2177 assert(precedence[e->op] != PREC_zero);
2178 assert(pr != PREC_zero);
2179
2180 //if (precedence[e->op] == 0) e->print();
2181 /* Despite precedence, we don't allow a<b<c expressions.
2182 * They must be parenthesized.
2183 */
2184 if (precedence[e->op] < pr ||
2185 (pr == PREC_rel && precedence[e->op] == pr))
2186 {
2187 buf->writeByte('(');
2188 e->accept(this);
2189 buf->writeByte(')');
2190 }
2191 else
2192 e->accept(this);
2193 }
2194
visit(Expression * e)2195 void visit(Expression *e)
2196 {
2197 buf->writestring(Token::toChars(e->op));
2198 }
2199
visit(IntegerExp * e)2200 void visit(IntegerExp *e)
2201 {
2202 dinteger_t v = e->toInteger();
2203
2204 if (e->type)
2205 {
2206 Type *t = e->type;
2207 L1:
2208 switch (t->ty)
2209 {
2210 case Tenum:
2211 {
2212 TypeEnum *te = (TypeEnum *)t;
2213 if (hgs->fullDump)
2214 {
2215 EnumDeclaration *sym = te->sym;
2216 if (inEnumDecl != sym)
2217 {
2218 for (size_t i = 0; i < sym->members->dim; i++)
2219 {
2220 EnumMember *em = (EnumMember *)(*sym->members)[i];
2221 if (em->value()->toInteger() == v)
2222 {
2223 buf->printf("%s.%s", sym->toChars(), em->ident->toChars());
2224 return;
2225 }
2226 }
2227 }
2228 }
2229 buf->printf("cast(%s)", te->sym->toChars());
2230 t = te->sym->memtype;
2231 goto L1;
2232 }
2233
2234 case Twchar: // BUG: need to cast(wchar)
2235 case Tdchar: // BUG: need to cast(dchar)
2236 if ((uinteger_t)v > 0xFF)
2237 {
2238 buf->printf("'\\U%08x'", v);
2239 break;
2240 }
2241 /* fall through */
2242 case Tchar:
2243 {
2244 size_t o = buf->offset;
2245 if (v == '\'')
2246 buf->writestring("'\\''");
2247 else if (isprint((int)v) && v != '\\')
2248 buf->printf("'%c'", (int)v);
2249 else
2250 buf->printf("'\\x%02x'", (int)v);
2251 if (hgs->ddoc)
2252 escapeDdocString(buf, o);
2253 break;
2254 }
2255
2256 case Tint8:
2257 buf->writestring("cast(byte)");
2258 goto L2;
2259
2260 case Tint16:
2261 buf->writestring("cast(short)");
2262 goto L2;
2263
2264 case Tint32:
2265 L2:
2266 buf->printf("%d", (int)v);
2267 break;
2268
2269 case Tuns8:
2270 buf->writestring("cast(ubyte)");
2271 goto L3;
2272
2273 case Tuns16:
2274 buf->writestring("cast(ushort)");
2275 goto L3;
2276
2277 case Tuns32:
2278 L3:
2279 buf->printf("%uu", (unsigned)v);
2280 break;
2281
2282 case Tint64:
2283 buf->printf("%lldL", v);
2284 break;
2285
2286 case Tuns64:
2287 L4:
2288 buf->printf("%lluLU", v);
2289 break;
2290
2291 case Tbool:
2292 buf->writestring(v ? "true" : "false");
2293 break;
2294
2295 case Tpointer:
2296 buf->writestring("cast(");
2297 buf->writestring(t->toChars());
2298 buf->writeByte(')');
2299 if (Target::ptrsize == 4)
2300 goto L3;
2301 else if (Target::ptrsize == 8)
2302 goto L4;
2303 else
2304 assert(0);
2305
2306 default:
2307 /* This can happen if errors, such as
2308 * the type is painted on like in fromConstInitializer().
2309 */
2310 if (!global.errors)
2311 {
2312 assert(0);
2313 }
2314 break;
2315 }
2316 }
2317 else if (v & 0x8000000000000000LL)
2318 buf->printf("0x%llx", v);
2319 else
2320 buf->printf("%lld", v);
2321 }
2322
visit(ErrorExp *)2323 void visit(ErrorExp *)
2324 {
2325 buf->writestring("__error");
2326 }
2327
floatToBuffer(Type * type,real_t value)2328 void floatToBuffer(Type *type, real_t value)
2329 {
2330 /** sizeof(value)*3 is because each byte of mantissa is max
2331 of 256 (3 characters). The string will be "-M.MMMMe-4932".
2332 (ie, 8 chars more than mantissa). Plus one for trailing \0.
2333 Plus one for rounding. */
2334 const size_t BUFFER_LEN = sizeof(value) * 3 + 8 + 1 + 1;
2335 char buffer[BUFFER_LEN];
2336 memset(buffer, 0, BUFFER_LEN);
2337 CTFloat::sprint(buffer, 'g', value);
2338 assert(strlen(buffer) < BUFFER_LEN);
2339
2340 if (hgs->hdrgen)
2341 {
2342 real_t r = CTFloat::parse(buffer);
2343 if (r != value) // if exact duplication
2344 CTFloat::sprint(buffer, 'a', value);
2345 }
2346 buf->writestring(buffer);
2347
2348 if (type)
2349 {
2350 Type *t = type->toBasetype();
2351 switch (t->ty)
2352 {
2353 case Tfloat32:
2354 case Timaginary32:
2355 case Tcomplex32:
2356 buf->writeByte('F');
2357 break;
2358
2359 case Tfloat80:
2360 case Timaginary80:
2361 case Tcomplex80:
2362 buf->writeByte('L');
2363 break;
2364
2365 default:
2366 break;
2367 }
2368 if (t->isimaginary())
2369 buf->writeByte('i');
2370 }
2371 }
2372
visit(RealExp * e)2373 void visit(RealExp *e)
2374 {
2375 floatToBuffer(e->type, e->value);
2376 }
2377
visit(ComplexExp * e)2378 void visit(ComplexExp *e)
2379 {
2380 /* Print as:
2381 * (re+imi)
2382 */
2383 buf->writeByte('(');
2384 floatToBuffer(e->type, creall(e->value));
2385 buf->writeByte('+');
2386 floatToBuffer(e->type, cimagl(e->value));
2387 buf->writestring("i)");
2388 }
2389
visit(IdentifierExp * e)2390 void visit(IdentifierExp *e)
2391 {
2392 if (hgs->hdrgen || hgs->ddoc)
2393 buf->writestring(e->ident->toHChars2());
2394 else
2395 buf->writestring(e->ident->toChars());
2396 }
2397
visit(DsymbolExp * e)2398 void visit(DsymbolExp *e)
2399 {
2400 buf->writestring(e->s->toChars());
2401 }
2402
visit(ThisExp *)2403 void visit(ThisExp *)
2404 {
2405 buf->writestring("this");
2406 }
2407
visit(SuperExp *)2408 void visit(SuperExp *)
2409 {
2410 buf->writestring("super");
2411 }
2412
visit(NullExp *)2413 void visit(NullExp *)
2414 {
2415 buf->writestring("null");
2416 }
2417
visit(StringExp * e)2418 void visit(StringExp *e)
2419 {
2420 buf->writeByte('"');
2421 size_t o = buf->offset;
2422 for (size_t i = 0; i < e->len; i++)
2423 {
2424 unsigned c = e->charAt(i);
2425 switch (c)
2426 {
2427 case '"':
2428 case '\\':
2429 buf->writeByte('\\');
2430 /* fall through */
2431 default:
2432 if (c <= 0xFF)
2433 {
2434 if (c <= 0x7F && isprint(c))
2435 buf->writeByte(c);
2436 else
2437 buf->printf("\\x%02x", c);
2438 }
2439 else if (c <= 0xFFFF)
2440 buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8);
2441 else
2442 buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x",
2443 c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24);
2444 break;
2445 }
2446 }
2447 if (hgs->ddoc)
2448 escapeDdocString(buf, o);
2449 buf->writeByte('"');
2450 if (e->postfix)
2451 buf->writeByte(e->postfix);
2452 }
2453
visit(ArrayLiteralExp * e)2454 void visit(ArrayLiteralExp *e)
2455 {
2456 buf->writeByte('[');
2457 argsToBuffer(e->elements, e->basis);
2458 buf->writeByte(']');
2459 }
2460
visit(AssocArrayLiteralExp * e)2461 void visit(AssocArrayLiteralExp *e)
2462 {
2463 buf->writeByte('[');
2464 for (size_t i = 0; i < e->keys->dim; i++)
2465 {
2466 Expression *key = (*e->keys)[i];
2467 Expression *value = (*e->values)[i];
2468
2469 if (i)
2470 buf->writestring(", ");
2471 expToBuffer(key, PREC_assign);
2472 buf->writeByte(':');
2473 expToBuffer(value, PREC_assign);
2474 }
2475 buf->writeByte(']');
2476 }
2477
visit(StructLiteralExp * e)2478 void visit(StructLiteralExp *e)
2479 {
2480 buf->writestring(e->sd->toChars());
2481 buf->writeByte('(');
2482
2483 // CTFE can generate struct literals that contain an AddrExp pointing
2484 // to themselves, need to avoid infinite recursion:
2485 // struct S { this(int){ this.s = &this; } S* s; }
2486 // const foo = new S(0);
2487 if (e->stageflags & stageToCBuffer)
2488 buf->writestring("<recursion>");
2489 else
2490 {
2491 int old = e->stageflags;
2492 e->stageflags |= stageToCBuffer;
2493 argsToBuffer(e->elements);
2494 e->stageflags = old;
2495 }
2496
2497 buf->writeByte(')');
2498 }
2499
visit(TypeExp * e)2500 void visit(TypeExp *e)
2501 {
2502 typeToBuffer(e->type, NULL);
2503 }
2504
visit(ScopeExp * e)2505 void visit(ScopeExp *e)
2506 {
2507 if (e->sds->isTemplateInstance())
2508 {
2509 e->sds->accept(this);
2510 }
2511 else if (hgs != NULL && hgs->ddoc)
2512 {
2513 // fixes bug 6491
2514 Module *m = e->sds->isModule();
2515 if (m)
2516 buf->writestring(m->md->toChars());
2517 else
2518 buf->writestring(e->sds->toChars());
2519 }
2520 else
2521 {
2522 buf->writestring(e->sds->kind());
2523 buf->writeByte(' ');
2524 buf->writestring(e->sds->toChars());
2525 }
2526 }
2527
visit(TemplateExp * e)2528 void visit(TemplateExp *e)
2529 {
2530 buf->writestring(e->td->toChars());
2531 }
2532
visit(NewExp * e)2533 void visit(NewExp *e)
2534 {
2535 if (e->thisexp)
2536 {
2537 expToBuffer(e->thisexp, PREC_primary);
2538 buf->writeByte('.');
2539 }
2540 buf->writestring("new ");
2541 if (e->newargs && e->newargs->dim)
2542 {
2543 buf->writeByte('(');
2544 argsToBuffer(e->newargs);
2545 buf->writeByte(')');
2546 }
2547 typeToBuffer(e->newtype, NULL);
2548 if (e->arguments && e->arguments->dim)
2549 {
2550 buf->writeByte('(');
2551 argsToBuffer(e->arguments);
2552 buf->writeByte(')');
2553 }
2554 }
2555
visit(NewAnonClassExp * e)2556 void visit(NewAnonClassExp *e)
2557 {
2558 if (e->thisexp)
2559 {
2560 expToBuffer(e->thisexp, PREC_primary);
2561 buf->writeByte('.');
2562 }
2563 buf->writestring("new");
2564 if (e->newargs && e->newargs->dim)
2565 {
2566 buf->writeByte('(');
2567 argsToBuffer(e->newargs);
2568 buf->writeByte(')');
2569 }
2570 buf->writestring(" class ");
2571 if (e->arguments && e->arguments->dim)
2572 {
2573 buf->writeByte('(');
2574 argsToBuffer(e->arguments);
2575 buf->writeByte(')');
2576 }
2577 if (e->cd)
2578 e->cd->accept(this);
2579 }
2580
visit(SymOffExp * e)2581 void visit(SymOffExp *e)
2582 {
2583 if (e->offset)
2584 buf->printf("(& %s+%u)", e->var->toChars(), e->offset);
2585 else if (e->var->isTypeInfoDeclaration())
2586 buf->printf("%s", e->var->toChars());
2587 else
2588 buf->printf("& %s", e->var->toChars());
2589 }
2590
visit(VarExp * e)2591 void visit(VarExp *e)
2592 {
2593 buf->writestring(e->var->toChars());
2594 }
2595
visit(OverExp * e)2596 void visit(OverExp *e)
2597 {
2598 buf->writestring(e->vars->ident->toChars());
2599 }
2600
visit(TupleExp * e)2601 void visit(TupleExp *e)
2602 {
2603 if (e->e0)
2604 {
2605 buf->writeByte('(');
2606 e->e0->accept(this);
2607 buf->writestring(", tuple(");
2608 argsToBuffer(e->exps);
2609 buf->writestring("))");
2610 }
2611 else
2612 {
2613 buf->writestring("tuple(");
2614 argsToBuffer(e->exps);
2615 buf->writeByte(')');
2616 }
2617 }
2618
visit(FuncExp * e)2619 void visit(FuncExp *e)
2620 {
2621 e->fd->accept(this);
2622 //buf->writestring(e->fd->toChars());
2623 }
2624
visit(DeclarationExp * e)2625 void visit(DeclarationExp *e)
2626 {
2627 /* Normal dmd execution won't reach here - regular variable declarations
2628 * are handled in visit(ExpStatement), so here would be used only when
2629 * we'll directly call Expression::toChars() for debugging.
2630 */
2631 if (VarDeclaration *v = e->declaration->isVarDeclaration())
2632 {
2633 // For debugging use:
2634 // - Avoid printing newline.
2635 // - Intentionally use the format (Type var;)
2636 // which isn't correct as regular D code.
2637 buf->writeByte('(');
2638 visitVarDecl(v, false);
2639 buf->writeByte(';');
2640 buf->writeByte(')');
2641 }
2642 else
2643 e->declaration->accept(this);
2644 }
2645
visit(TypeidExp * e)2646 void visit(TypeidExp *e)
2647 {
2648 buf->writestring("typeid(");
2649 objectToBuffer(e->obj);
2650 buf->writeByte(')');
2651 }
2652
visit(TraitsExp * e)2653 void visit(TraitsExp *e)
2654 {
2655 buf->writestring("__traits(");
2656 buf->writestring(e->ident->toChars());
2657 if (e->args)
2658 {
2659 for (size_t i = 0; i < e->args->dim; i++)
2660 {
2661 RootObject *arg = (*e->args)[i];
2662 buf->writestring(", ");
2663 objectToBuffer(arg);
2664 }
2665 }
2666 buf->writeByte(')');
2667 }
2668
visit(HaltExp *)2669 void visit(HaltExp *)
2670 {
2671 buf->writestring("halt");
2672 }
2673
visit(IsExp * e)2674 void visit(IsExp *e)
2675 {
2676 buf->writestring("is(");
2677 typeToBuffer(e->targ, e->id);
2678 if (e->tok2 != TOKreserved)
2679 {
2680 buf->printf(" %s %s", Token::toChars(e->tok), Token::toChars(e->tok2));
2681 }
2682 else if (e->tspec)
2683 {
2684 if (e->tok == TOKcolon)
2685 buf->writestring(" : ");
2686 else
2687 buf->writestring(" == ");
2688 typeToBuffer(e->tspec, NULL);
2689 }
2690 if (e->parameters && e->parameters->dim)
2691 {
2692 buf->writestring(", ");
2693 visitTemplateParameters(e->parameters);
2694 }
2695 buf->writeByte(')');
2696 }
2697
visit(UnaExp * e)2698 void visit(UnaExp *e)
2699 {
2700 buf->writestring(Token::toChars(e->op));
2701 expToBuffer(e->e1, precedence[e->op]);
2702 }
2703
visit(BinExp * e)2704 void visit(BinExp *e)
2705 {
2706 expToBuffer(e->e1, precedence[e->op]);
2707 buf->writeByte(' ');
2708 buf->writestring(Token::toChars(e->op));
2709 buf->writeByte(' ');
2710 expToBuffer(e->e2, (PREC)(precedence[e->op] + 1));
2711 }
2712
visit(CompileExp * e)2713 void visit(CompileExp *e)
2714 {
2715 buf->writestring("mixin(");
2716 expToBuffer(e->e1, PREC_assign);
2717 buf->writeByte(')');
2718 }
2719
visit(ImportExp * e)2720 void visit(ImportExp *e)
2721 {
2722 buf->writestring("import(");
2723 expToBuffer(e->e1, PREC_assign);
2724 buf->writeByte(')');
2725 }
2726
visit(AssertExp * e)2727 void visit(AssertExp *e)
2728 {
2729 buf->writestring("assert(");
2730 expToBuffer(e->e1, PREC_assign);
2731 if (e->msg)
2732 {
2733 buf->writestring(", ");
2734 expToBuffer(e->msg, PREC_assign);
2735 }
2736 buf->writeByte(')');
2737 }
2738
visit(DotIdExp * e)2739 void visit(DotIdExp *e)
2740 {
2741 expToBuffer(e->e1, PREC_primary);
2742 buf->writeByte('.');
2743 buf->writestring(e->ident->toChars());
2744 }
2745
visit(DotTemplateExp * e)2746 void visit(DotTemplateExp *e)
2747 {
2748 expToBuffer(e->e1, PREC_primary);
2749 buf->writeByte('.');
2750 buf->writestring(e->td->toChars());
2751 }
2752
visit(DotVarExp * e)2753 void visit(DotVarExp *e)
2754 {
2755 expToBuffer(e->e1, PREC_primary);
2756 buf->writeByte('.');
2757 buf->writestring(e->var->toChars());
2758 }
2759
visit(DotTemplateInstanceExp * e)2760 void visit(DotTemplateInstanceExp *e)
2761 {
2762 expToBuffer(e->e1, PREC_primary);
2763 buf->writeByte('.');
2764 e->ti->accept(this);
2765 }
2766
visit(DelegateExp * e)2767 void visit(DelegateExp *e)
2768 {
2769 buf->writeByte('&');
2770 if (!e->func->isNested())
2771 {
2772 expToBuffer(e->e1, PREC_primary);
2773 buf->writeByte('.');
2774 }
2775 buf->writestring(e->func->toChars());
2776 }
2777
visit(DotTypeExp * e)2778 void visit(DotTypeExp *e)
2779 {
2780 expToBuffer(e->e1, PREC_primary);
2781 buf->writeByte('.');
2782 buf->writestring(e->sym->toChars());
2783 }
2784
visit(CallExp * e)2785 void visit(CallExp *e)
2786 {
2787 if (e->e1->op == TOKtype)
2788 {
2789 /* Avoid parens around type to prevent forbidden cast syntax:
2790 * (sometype)(arg1)
2791 * This is ok since types in constructor calls
2792 * can never depend on parens anyway
2793 */
2794 e->e1->accept(this);
2795 }
2796 else
2797 expToBuffer(e->e1, precedence[e->op]);
2798 buf->writeByte('(');
2799 argsToBuffer(e->arguments);
2800 buf->writeByte(')');
2801 }
2802
visit(PtrExp * e)2803 void visit(PtrExp *e)
2804 {
2805 buf->writeByte('*');
2806 expToBuffer(e->e1, precedence[e->op]);
2807 }
2808
visit(DeleteExp * e)2809 void visit(DeleteExp *e)
2810 {
2811 buf->writestring("delete ");
2812 expToBuffer(e->e1, precedence[e->op]);
2813 }
2814
visit(CastExp * e)2815 void visit(CastExp *e)
2816 {
2817 buf->writestring("cast(");
2818 if (e->to)
2819 typeToBuffer(e->to, NULL);
2820 else
2821 {
2822 MODtoBuffer(buf, e->mod);
2823 }
2824 buf->writeByte(')');
2825 expToBuffer(e->e1, precedence[e->op]);
2826 }
2827
visit(VectorExp * e)2828 void visit(VectorExp *e)
2829 {
2830 buf->writestring("cast(");
2831 typeToBuffer(e->to, NULL);
2832 buf->writeByte(')');
2833 expToBuffer(e->e1, precedence[e->op]);
2834 }
2835
visit(VectorArrayExp * e)2836 void visit(VectorArrayExp *e)
2837 {
2838 expToBuffer(e->e1, PREC_primary);
2839 buf->writestring(".array");
2840 }
2841
visit(SliceExp * e)2842 void visit(SliceExp *e)
2843 {
2844 expToBuffer(e->e1, precedence[e->op]);
2845 buf->writeByte('[');
2846 if (e->upr || e->lwr)
2847 {
2848 if (e->lwr)
2849 sizeToBuffer(e->lwr);
2850 else
2851 buf->writeByte('0');
2852 buf->writestring("..");
2853 if (e->upr)
2854 sizeToBuffer(e->upr);
2855 else
2856 buf->writeByte('$');
2857 }
2858 buf->writeByte(']');
2859 }
2860
visit(ArrayLengthExp * e)2861 void visit(ArrayLengthExp *e)
2862 {
2863 expToBuffer(e->e1, PREC_primary);
2864 buf->writestring(".length");
2865 }
2866
visit(IntervalExp * e)2867 void visit(IntervalExp *e)
2868 {
2869 expToBuffer(e->lwr, PREC_assign);
2870 buf->writestring("..");
2871 expToBuffer(e->upr, PREC_assign);
2872 }
2873
visit(DelegatePtrExp * e)2874 void visit(DelegatePtrExp *e)
2875 {
2876 expToBuffer(e->e1, PREC_primary);
2877 buf->writestring(".ptr");
2878 }
2879
visit(DelegateFuncptrExp * e)2880 void visit(DelegateFuncptrExp *e)
2881 {
2882 expToBuffer(e->e1, PREC_primary);
2883 buf->writestring(".funcptr");
2884 }
2885
visit(ArrayExp * e)2886 void visit(ArrayExp *e)
2887 {
2888 expToBuffer(e->e1, PREC_primary);
2889 buf->writeByte('[');
2890 argsToBuffer(e->arguments);
2891 buf->writeByte(']');
2892 }
2893
visit(DotExp * e)2894 void visit(DotExp *e)
2895 {
2896 expToBuffer(e->e1, PREC_primary);
2897 buf->writeByte('.');
2898 expToBuffer(e->e2, PREC_primary);
2899 }
2900
visit(IndexExp * e)2901 void visit(IndexExp *e)
2902 {
2903 expToBuffer(e->e1, PREC_primary);
2904 buf->writeByte('[');
2905 sizeToBuffer(e->e2);
2906 buf->writeByte(']');
2907 }
2908
visit(PostExp * e)2909 void visit(PostExp *e)
2910 {
2911 expToBuffer(e->e1, precedence[e->op]);
2912 buf->writestring(Token::toChars(e->op));
2913 }
2914
visit(PreExp * e)2915 void visit(PreExp *e)
2916 {
2917 buf->writestring(Token::toChars(e->op));
2918 expToBuffer(e->e1, precedence[e->op]);
2919 }
2920
visit(RemoveExp * e)2921 void visit(RemoveExp *e)
2922 {
2923 expToBuffer(e->e1, PREC_primary);
2924 buf->writestring(".remove(");
2925 expToBuffer(e->e2, PREC_assign);
2926 buf->writeByte(')');
2927 }
2928
visit(CondExp * e)2929 void visit(CondExp *e)
2930 {
2931 expToBuffer(e->econd, PREC_oror);
2932 buf->writestring(" ? ");
2933 expToBuffer(e->e1, PREC_expr);
2934 buf->writestring(" : ");
2935 expToBuffer(e->e2, PREC_cond);
2936 }
2937
visit(DefaultInitExp * e)2938 void visit(DefaultInitExp *e)
2939 {
2940 buf->writestring(Token::toChars(e->subop));
2941 }
2942
visit(ClassReferenceExp * e)2943 void visit(ClassReferenceExp *e)
2944 {
2945 buf->writestring(e->value->toChars());
2946 }
2947
2948 ////////////////////////////////////////////////////////////////////////////
2949
visit(TemplateTypeParameter * tp)2950 void visit(TemplateTypeParameter *tp)
2951 {
2952 buf->writestring(tp->ident->toChars());
2953 if (tp->specType)
2954 {
2955 buf->writestring(" : ");
2956 typeToBuffer(tp->specType, NULL);
2957 }
2958 if (tp->defaultType)
2959 {
2960 buf->writestring(" = ");
2961 typeToBuffer(tp->defaultType, NULL);
2962 }
2963 }
2964
visit(TemplateThisParameter * tp)2965 void visit(TemplateThisParameter *tp)
2966 {
2967 buf->writestring("this ");
2968 visit((TemplateTypeParameter *)tp);
2969 }
2970
visit(TemplateAliasParameter * tp)2971 void visit(TemplateAliasParameter *tp)
2972 {
2973 buf->writestring("alias ");
2974 if (tp->specType)
2975 typeToBuffer(tp->specType, tp->ident);
2976 else
2977 buf->writestring(tp->ident->toChars());
2978 if (tp->specAlias)
2979 {
2980 buf->writestring(" : ");
2981 objectToBuffer(tp->specAlias);
2982 }
2983 if (tp->defaultAlias)
2984 {
2985 buf->writestring(" = ");
2986 objectToBuffer(tp->defaultAlias);
2987 }
2988 }
2989
visit(TemplateValueParameter * tp)2990 void visit(TemplateValueParameter *tp)
2991 {
2992 typeToBuffer(tp->valType, tp->ident);
2993 if (tp->specValue)
2994 {
2995 buf->writestring(" : ");
2996 tp->specValue->accept(this);
2997 }
2998 if (tp->defaultValue)
2999 {
3000 buf->writestring(" = ");
3001 tp->defaultValue->accept(this);
3002 }
3003 }
3004
visit(TemplateTupleParameter * tp)3005 void visit(TemplateTupleParameter *tp)
3006 {
3007 buf->writestring(tp->ident->toChars());
3008 buf->writestring("...");
3009 }
3010
3011 ////////////////////////////////////////////////////////////////////////////
3012
visit(DebugCondition * c)3013 void visit(DebugCondition *c)
3014 {
3015 if (c->ident)
3016 buf->printf("debug (%s)", c->ident->toChars());
3017 else
3018 buf->printf("debug (%u)", c->level);
3019 }
3020
visit(VersionCondition * c)3021 void visit(VersionCondition *c)
3022 {
3023 if (c->ident)
3024 buf->printf("version (%s)", c->ident->toChars());
3025 else
3026 buf->printf("version (%u)", c->level);
3027 }
3028
visit(StaticIfCondition * c)3029 void visit(StaticIfCondition *c)
3030 {
3031 buf->writestring("static if (");
3032 c->exp->accept(this);
3033 buf->writeByte(')');
3034 }
3035
3036 ////////////////////////////////////////////////////////////////////////////
3037
visit(Parameter * p)3038 void visit(Parameter *p)
3039 {
3040 if (p->storageClass & STCauto)
3041 buf->writestring("auto ");
3042
3043 if (p->storageClass & STCreturn)
3044 buf->writestring("return ");
3045
3046 if (p->storageClass & STCout)
3047 buf->writestring("out ");
3048 else if (p->storageClass & STCref)
3049 buf->writestring("ref ");
3050 else if (p->storageClass & STCin)
3051 buf->writestring("in ");
3052 else if (p->storageClass & STClazy)
3053 buf->writestring("lazy ");
3054 else if (p->storageClass & STCalias)
3055 buf->writestring("alias ");
3056
3057 StorageClass stc = p->storageClass;
3058 if (p->type && p->type->mod & MODshared)
3059 stc &= ~STCshared;
3060
3061 if (stcToBuffer(buf, stc & (STCconst | STCimmutable | STCwild | STCshared | STCscope | STCscopeinferred)))
3062 buf->writeByte(' ');
3063
3064 if (p->storageClass & STCalias)
3065 {
3066 if (p->ident)
3067 buf->writestring(p->ident->toChars());
3068 }
3069 else if (p->type->ty == Tident &&
3070 strlen(((TypeIdentifier *)p->type)->ident->toChars()) > 3 &&
3071 strncmp(((TypeIdentifier *)p->type)->ident->toChars(), "__T", 3) == 0)
3072 {
3073 // print parameter name, instead of undetermined type parameter
3074 buf->writestring(p->ident->toChars());
3075 }
3076 else
3077 typeToBuffer(p->type, p->ident);
3078 if (p->defaultArg)
3079 {
3080 buf->writestring(" = ");
3081 p->defaultArg->accept(this);
3082 }
3083 }
3084
parametersToBuffer(Parameters * parameters,int varargs)3085 void parametersToBuffer(Parameters *parameters, int varargs)
3086 {
3087 buf->writeByte('(');
3088 if (parameters)
3089 {
3090 size_t dim = Parameter::dim(parameters);
3091 for (size_t i = 0; i < dim; i++)
3092 {
3093 if (i)
3094 buf->writestring(", ");
3095 Parameter *fparam = Parameter::getNth(parameters, i);
3096 fparam->accept(this);
3097 }
3098 if (varargs)
3099 {
3100 if (parameters->dim && varargs == 1)
3101 buf->writestring(", ");
3102 buf->writestring("...");
3103 }
3104 }
3105 buf->writeByte(')');
3106 }
3107
visit(Module * m)3108 void visit(Module *m)
3109 {
3110 if (m->md)
3111 {
3112 if (m->userAttribDecl)
3113 {
3114 buf->writestring("@(");
3115 argsToBuffer(m->userAttribDecl->atts);
3116 buf->writeByte(')');
3117 buf->writenl();
3118 }
3119 if (m->md->isdeprecated)
3120 {
3121 if (m->md->msg)
3122 {
3123 buf->writestring("deprecated(");
3124 m->md->msg->accept(this);
3125 buf->writestring(") ");
3126 }
3127 else
3128 buf->writestring("deprecated ");
3129 }
3130
3131 buf->writestring("module ");
3132 buf->writestring(m->md->toChars());
3133 buf->writeByte(';');
3134 buf->writenl();
3135 }
3136 for (size_t i = 0; i < m->members->dim; i++)
3137 {
3138 Dsymbol *s = (*m->members)[i];
3139 s->accept(this);
3140 }
3141 }
3142 };
3143
toCBuffer(Statement * s,OutBuffer * buf,HdrGenState * hgs)3144 void toCBuffer(Statement *s, OutBuffer *buf, HdrGenState *hgs)
3145 {
3146 PrettyPrintVisitor v(buf, hgs);
3147 s->accept(&v);
3148 }
3149
toCBuffer(Type * t,OutBuffer * buf,Identifier * ident,HdrGenState * hgs)3150 void toCBuffer(Type *t, OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
3151 {
3152 PrettyPrintVisitor v(buf, hgs);
3153 v.typeToBuffer(t, ident);
3154 }
3155
toCBuffer(Dsymbol * s,OutBuffer * buf,HdrGenState * hgs)3156 void toCBuffer(Dsymbol *s, OutBuffer *buf, HdrGenState *hgs)
3157 {
3158 PrettyPrintVisitor v(buf, hgs);
3159 s->accept(&v);
3160 }
3161
3162 // used from TemplateInstance::toChars() and TemplateMixin::toChars()
toCBufferInstance(TemplateInstance * ti,OutBuffer * buf,bool qualifyTypes)3163 void toCBufferInstance(TemplateInstance *ti, OutBuffer *buf, bool qualifyTypes)
3164 {
3165 HdrGenState hgs;
3166 hgs.fullQual = qualifyTypes;
3167 PrettyPrintVisitor v(buf, &hgs);
3168 v.visit(ti);
3169 }
3170
toCBuffer(Initializer * iz,OutBuffer * buf,HdrGenState * hgs)3171 void toCBuffer(Initializer *iz, OutBuffer *buf, HdrGenState *hgs)
3172 {
3173 PrettyPrintVisitor v(buf, hgs);
3174 iz->accept(&v);
3175 }
3176
stcToBuffer(OutBuffer * buf,StorageClass stc)3177 bool stcToBuffer(OutBuffer *buf, StorageClass stc)
3178 {
3179 bool result = false;
3180 if ((stc & (STCreturn | STCscope)) == (STCreturn | STCscope))
3181 stc &= ~STCscope;
3182 if (stc & STCscopeinferred)
3183 stc &= ~(STCscope | STCscopeinferred);
3184 while (stc)
3185 {
3186 const char *p = stcToChars(stc);
3187 if (!p)
3188 break;
3189 if (!result)
3190 result = true;
3191 else
3192 buf->writeByte(' ');
3193 buf->writestring(p);
3194 }
3195 return result;
3196 }
3197
3198 /*************************************************
3199 * Pick off one of the storage classes from stc,
3200 * and return a pointer to a string representation of it.
3201 * stc is reduced by the one picked.
3202 */
stcToChars(StorageClass & stc)3203 const char *stcToChars(StorageClass& stc)
3204 {
3205 struct SCstring
3206 {
3207 StorageClass stc;
3208 TOK tok;
3209 const char *id;
3210 };
3211
3212 static SCstring table[] =
3213 {
3214 { STCauto, TOKauto, NULL },
3215 { STCscope, TOKscope, NULL },
3216 { STCstatic, TOKstatic, NULL },
3217 { STCextern, TOKextern, NULL },
3218 { STCconst, TOKconst, NULL },
3219 { STCfinal, TOKfinal, NULL },
3220 { STCabstract, TOKabstract, NULL },
3221 { STCsynchronized, TOKsynchronized, NULL },
3222 { STCdeprecated, TOKdeprecated, NULL },
3223 { STCoverride, TOKoverride, NULL },
3224 { STClazy, TOKlazy, NULL },
3225 { STCalias, TOKalias, NULL },
3226 { STCout, TOKout, NULL },
3227 { STCin, TOKin, NULL },
3228 { STCmanifest, TOKenum, NULL },
3229 { STCimmutable, TOKimmutable, NULL },
3230 { STCshared, TOKshared, NULL },
3231 { STCnothrow, TOKnothrow, NULL },
3232 { STCwild, TOKwild, NULL },
3233 { STCpure, TOKpure, NULL },
3234 { STCref, TOKref, NULL },
3235 { STCtls, TOKreserved, NULL },
3236 { STCgshared, TOKgshared, NULL },
3237 { STCnogc, TOKat, "@nogc" },
3238 { STCproperty, TOKat, "@property" },
3239 { STCsafe, TOKat, "@safe" },
3240 { STCtrusted, TOKat, "@trusted" },
3241 { STCsystem, TOKat, "@system" },
3242 { STCdisable, TOKat, "@disable" },
3243 { STCfuture, TOKat, "@__future" },
3244 { 0, TOKreserved, NULL }
3245 };
3246
3247 for (int i = 0; table[i].stc; i++)
3248 {
3249 StorageClass tbl = table[i].stc;
3250 assert(tbl & STCStorageClass);
3251 if (stc & tbl)
3252 {
3253 stc &= ~tbl;
3254 if (tbl == STCtls) // TOKtls was removed
3255 return "__thread";
3256
3257 TOK tok = table[i].tok;
3258 if (tok == TOKat)
3259 return table[i].id;
3260 else
3261 return Token::toChars(tok);
3262 }
3263 }
3264 //printf("stc = %llx\n", stc);
3265 return NULL;
3266 }
3267
trustToBuffer(OutBuffer * buf,TRUST trust)3268 void trustToBuffer(OutBuffer *buf, TRUST trust)
3269 {
3270 const char *p = trustToChars(trust);
3271 if (p)
3272 buf->writestring(p);
3273 }
3274
trustToChars(TRUST trust)3275 const char *trustToChars(TRUST trust)
3276 {
3277 switch (trust)
3278 {
3279 case TRUSTdefault: return NULL;
3280 case TRUSTsystem: return "@system";
3281 case TRUSTtrusted: return "@trusted";
3282 case TRUSTsafe: return "@safe";
3283 default: assert(0);
3284 }
3285 return NULL; // never reached
3286 }
3287
linkageToBuffer(OutBuffer * buf,LINK linkage)3288 void linkageToBuffer(OutBuffer *buf, LINK linkage)
3289 {
3290 const char *p = linkageToChars(linkage);
3291 if (p)
3292 {
3293 buf->writestring("extern (");
3294 buf->writestring(p);
3295 buf->writeByte(')');
3296 }
3297 }
3298
linkageToChars(LINK linkage)3299 const char *linkageToChars(LINK linkage)
3300 {
3301 switch (linkage)
3302 {
3303 case LINKdefault: return NULL;
3304 case LINKd: return "D";
3305 case LINKc: return "C";
3306 case LINKcpp: return "C++";
3307 case LINKwindows: return "Windows";
3308 case LINKpascal: return "Pascal";
3309 case LINKobjc: return "Objective-C";
3310 case LINKsystem: return "System";
3311 default: assert(0);
3312 }
3313 return NULL; // never reached
3314 }
3315
protectionToBuffer(OutBuffer * buf,Prot prot)3316 void protectionToBuffer(OutBuffer *buf, Prot prot)
3317 {
3318 const char *p = protectionToChars(prot.kind);
3319 if (p)
3320 buf->writestring(p);
3321
3322 if (prot.kind == PROTpackage && prot.pkg)
3323 {
3324 buf->writeByte('(');
3325 buf->writestring(prot.pkg->toPrettyChars(true));
3326 buf->writeByte(')');
3327 }
3328 }
3329
protectionToChars(PROTKIND kind)3330 const char *protectionToChars(PROTKIND kind)
3331 {
3332 switch (kind)
3333 {
3334 case PROTundefined: return NULL;
3335 case PROTnone: return "none";
3336 case PROTprivate: return "private";
3337 case PROTpackage: return "package";
3338 case PROTprotected: return "protected";
3339 case PROTpublic: return "public";
3340 case PROTexport: return "export";
3341 default: assert(0);
3342 }
3343 return NULL; // never reached
3344 }
3345
3346 // Print the full function signature with correct ident, attributes and template args
functionToBufferFull(TypeFunction * tf,OutBuffer * buf,Identifier * ident,HdrGenState * hgs,TemplateDeclaration * td)3347 void functionToBufferFull(TypeFunction *tf, OutBuffer *buf, Identifier *ident,
3348 HdrGenState* hgs, TemplateDeclaration *td)
3349 {
3350 //printf("TypeFunction::toCBuffer() this = %p\n", this);
3351 PrettyPrintVisitor v(buf, hgs);
3352 v.visitFuncIdentWithPrefix(tf, ident, td);
3353 }
3354
3355 // ident is inserted before the argument list and will be "function" or "delegate" for a type
functionToBufferWithIdent(TypeFunction * tf,OutBuffer * buf,const char * ident)3356 void functionToBufferWithIdent(TypeFunction *tf, OutBuffer *buf, const char *ident)
3357 {
3358 HdrGenState hgs;
3359 PrettyPrintVisitor v(buf, &hgs);
3360 v.visitFuncIdentWithPostfix(tf, ident);
3361 }
3362
toCBuffer(Expression * e,OutBuffer * buf,HdrGenState * hgs)3363 void toCBuffer(Expression *e, OutBuffer *buf, HdrGenState *hgs)
3364 {
3365 PrettyPrintVisitor v(buf, hgs);
3366 e->accept(&v);
3367 }
3368
3369 /**************************************************
3370 * Write out argument types to buf.
3371 */
argExpTypesToCBuffer(OutBuffer * buf,Expressions * arguments)3372 void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments)
3373 {
3374 if (!arguments || !arguments->dim)
3375 return;
3376
3377 HdrGenState hgs;
3378 PrettyPrintVisitor v(buf, &hgs);
3379 for (size_t i = 0; i < arguments->dim; i++)
3380 {
3381 Expression *arg = (*arguments)[i];
3382 if (i)
3383 buf->writestring(", ");
3384 v.typeToBuffer(arg->type, NULL);
3385 }
3386 }
3387
toCBuffer(TemplateParameter * tp,OutBuffer * buf,HdrGenState * hgs)3388 void toCBuffer(TemplateParameter *tp, OutBuffer *buf, HdrGenState *hgs)
3389 {
3390 PrettyPrintVisitor v(buf, hgs);
3391 tp->accept(&v);
3392 }
3393
arrayObjectsToBuffer(OutBuffer * buf,Objects * objects)3394 void arrayObjectsToBuffer(OutBuffer *buf, Objects *objects)
3395 {
3396 if (!objects || !objects->dim)
3397 return;
3398
3399 HdrGenState hgs;
3400 PrettyPrintVisitor v(buf, &hgs);
3401 for (size_t i = 0; i < objects->dim; i++)
3402 {
3403 RootObject *o = (*objects)[i];
3404 if (i)
3405 buf->writestring(", ");
3406 v.objectToBuffer(o);
3407 }
3408 }
3409
parametersTypeToChars(Parameters * parameters,int varargs)3410 const char *parametersTypeToChars(Parameters *parameters, int varargs)
3411 {
3412 OutBuffer buf;
3413 HdrGenState hgs;
3414 PrettyPrintVisitor v(&buf, &hgs);
3415 v.parametersToBuffer(parameters, varargs);
3416 return buf.extractString();
3417 }
3418