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