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