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 44void linkageToBuffer(OutBuffer *buf, LINK linkage); 45void MODtoBuffer(OutBuffer *buf, MOD mod); 46 47void 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 */ 74void moduleToBuffer(OutBuffer *buf, Module *m) 75{ 76 HdrGenState hgs; 77 hgs.fullDump = true; 78 toCBuffer(m, buf, &hgs); 79} 80 81class PrettyPrintVisitor : public Visitor 82{ 83public: 84 OutBuffer *buf; 85 HdrGenState *hgs; 86 bool declstring; // set while declaring alias for string,wstring or dstring 87 EnumDeclaration *inEnumDecl; 88 89 PrettyPrintVisitor(OutBuffer *buf, HdrGenState *hgs) 90 : buf(buf), hgs(hgs), declstring(false), inEnumDecl(NULL) 91 { 92 } 93 94 void visit(Statement *) 95 { 96 buf->printf("Statement::toCBuffer()"); 97 buf->writenl(); 98 assert(0); 99 } 100 101 void visit(ErrorStatement *) 102 { 103 buf->printf("__error__"); 104 buf->writenl(); 105 } 106 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 441 void visit(StaticAssertStatement *s) 442 { 443 s->sa->accept(this); 444 } 445 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 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 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 491 void visit(DefaultStatement *s) 492 { 493 buf->writestring("default:"); 494 buf->writenl(); 495 s->statement->accept(this); 496 } 497 498 void visit(GotoDefaultStatement *) 499 { 500 buf->writestring("goto default;"); 501 buf->writenl(); 502 } 503 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 516 void visit(SwitchErrorStatement *) 517 { 518 buf->writestring("SwitchErrorStatement::toCBuffer()"); 519 buf->writenl(); 520 } 521 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 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 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 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 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 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 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 621 void visit(OnScopeStatement *s) 622 { 623 buf->writestring(Token::toChars(s->tok)); 624 buf->writeByte(' '); 625 s->statement->accept(this); 626 } 627 628 void visit(ThrowStatement *s) 629 { 630 buf->printf("throw "); 631 s->exp->accept(this); 632 buf->writeByte(';'); 633 buf->writenl(); 634 } 635 636 void visit(DebugStatement *s) 637 { 638 if (s->statement) 639 { 640 s->statement->accept(this); 641 } 642 } 643 644 void visit(GotoStatement *s) 645 { 646 buf->writestring("goto "); 647 buf->writestring(s->ident->toChars()); 648 buf->writeByte(';'); 649 buf->writenl(); 650 } 651 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 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 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 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 */ 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 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 777 void visit(Type *t) 778 { 779 printf("t = %p, ty = %d\n", t, t->ty); 780 assert(0); 781 } 782 783 void visit(TypeError *) 784 { 785 buf->writestring("_error_"); 786 } 787 788 void visit(TypeBasic *t) 789 { 790 //printf("TypeBasic::toCBuffer2(t->mod = %d)\n", t->mod); 791 buf->writestring(t->dstring); 792 } 793 794 void visit(TypeTraits *t) 795 { 796 //printf("TypeBasic::toCBuffer2(t.mod = %d)\n", t.mod); 797 t->exp->accept(this); 798 } 799 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 808 void visit(TypeSArray *t) 809 { 810 visitWithMask(t->next, t->mod); 811 buf->writeByte('['); 812 sizeToBuffer(t->dim); 813 buf->writeByte(']'); 814 } 815 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 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 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 855 void visit(TypeReference *t) 856 { 857 visitWithMask(t->next, t->mod); 858 buf->writeByte('&'); 859 } 860 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 874 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 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 } 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 996 void visit(TypeDelegate *t) 997 { 998 visitFuncIdentWithPostfix((TypeFunction *)t->next, "delegate"); 999 } 1000 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 1033 void visit(TypeIdentifier *t) 1034 { 1035 buf->writestring(t->ident->toChars()); 1036 visitTypeQualifiedHelper(t); 1037 } 1038 1039 void visit(TypeInstance *t) 1040 { 1041 t->tempinst->accept(this); 1042 visitTypeQualifiedHelper(t); 1043 } 1044 1045 void visit(TypeTypeof *t) 1046 { 1047 buf->writestring("typeof("); 1048 t->exp->accept(this); 1049 buf->writeByte(')'); 1050 visitTypeQualifiedHelper(t); 1051 } 1052 1053 void visit(TypeReturn *t) 1054 { 1055 buf->writestring("typeof(return)"); 1056 visitTypeQualifiedHelper(t); 1057 } 1058 1059 void visit(TypeEnum *t) 1060 { 1061 buf->writestring(t->sym->toChars()); 1062 } 1063 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 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 1086 void visit(TypeTuple *t) 1087 { 1088 parametersToBuffer(t->arguments, 0); 1089 } 1090 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 1102 void visit(TypeNull *) 1103 { 1104 buf->writestring("typeof(null)"); 1105 } 1106 1107 //////////////////////////////////////////////////////////////////////////// 1108 1109 void visit(Dsymbol *s) 1110 { 1111 buf->writestring(s->toChars()); 1112 } 1113 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 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 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 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 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 1204 void visit(AliasThis *d) 1205 { 1206 buf->writestring("alias "); 1207 buf->writestring(d->ident->toChars()); 1208 buf->writestring(" this;\n"); 1209 } 1210 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 1249 void visit(StorageClassDeclaration *d) 1250 { 1251 if (stcToBuffer(buf, d->stc)) 1252 buf->writeByte(' '); 1253 visit((AttribDeclaration *)d); 1254 } 1255 1256 void visit(DeprecatedDeclaration *d) 1257 { 1258 buf->writestring("deprecated("); 1259 d->msg->accept(this); 1260 buf->writestring(") "); 1261 visit((AttribDeclaration *)d); 1262 } 1263 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 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 1304 void visit(ProtDeclaration *d) 1305 { 1306 protectionToBuffer(buf, d->protection); 1307 buf->writeByte(' '); 1308 visit((AttribDeclaration *)d); 1309 } 1310 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 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 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 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 1393 void visit(ForwardingStatement *s) 1394 { 1395 s->statement->accept(this); 1396 } 1397 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 1419 void visit(CompileDeclaration *d) 1420 { 1421 buf->writestring("mixin("); 1422 d->exp->accept(this); 1423 buf->writestring(");"); 1424 buf->writenl(); 1425 } 1426 1427 void visit(UserAttributeDeclaration *d) 1428 { 1429 buf->writestring("@("); 1430 argsToBuffer(d->atts); 1431 buf->writeByte(')'); 1432 visit((AttribDeclaration *)d); 1433 } 1434 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 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 } 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 } 1568 void visitTemplateConstraint(Expression *constraint) 1569 { 1570 if (!constraint) 1571 return; 1572 buf->writestring(" if ("); 1573 constraint->accept(this); 1574 buf->writeByte(')'); 1575 } 1576 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 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 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 */ 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 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 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 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 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 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 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 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 } 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 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 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 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 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 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 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 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 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 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 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 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 2130 void visit(ErrorInitializer *) 2131 { 2132 buf->writestring("__error__"); 2133 } 2134 2135 void visit(VoidInitializer *) 2136 { 2137 buf->writestring("void"); 2138 } 2139 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 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 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 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 */ 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 2257 void visit(Expression *e) 2258 { 2259 buf->writestring(Token::toChars(e->op)); 2260 } 2261 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 2383 void visit(ErrorExp *) 2384 { 2385 buf->writestring("__error"); 2386 } 2387 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 2433 void visit(RealExp *e) 2434 { 2435 floatToBuffer(e->type, e->value); 2436 } 2437 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 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 2458 void visit(DsymbolExp *e) 2459 { 2460 buf->writestring(e->s->toChars()); 2461 } 2462 2463 void visit(ThisExp *) 2464 { 2465 buf->writestring("this"); 2466 } 2467 2468 void visit(SuperExp *) 2469 { 2470 buf->writestring("super"); 2471 } 2472 2473 void visit(NullExp *) 2474 { 2475 buf->writestring("null"); 2476 } 2477 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 2514 void visit(ArrayLiteralExp *e) 2515 { 2516 buf->writeByte('['); 2517 argsToBuffer(e->elements, e->basis); 2518 buf->writeByte(']'); 2519 } 2520 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 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 2560 void visit(TypeExp *e) 2561 { 2562 typeToBuffer(e->type, NULL); 2563 } 2564 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 2588 void visit(TemplateExp *e) 2589 { 2590 buf->writestring(e->td->toChars()); 2591 } 2592 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 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 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 2651 void visit(VarExp *e) 2652 { 2653 buf->writestring(e->var->toChars()); 2654 } 2655 2656 void visit(OverExp *e) 2657 { 2658 buf->writestring(e->vars->ident->toChars()); 2659 } 2660 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 2679 void visit(FuncExp *e) 2680 { 2681 e->fd->accept(this); 2682 //buf->writestring(e->fd->toChars()); 2683 } 2684 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 2706 void visit(TypeidExp *e) 2707 { 2708 buf->writestring("typeid("); 2709 objectToBuffer(e->obj); 2710 buf->writeByte(')'); 2711 } 2712 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 2730 void visit(HaltExp *) 2731 { 2732 buf->writestring("halt"); 2733 } 2734 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 2759 void visit(UnaExp *e) 2760 { 2761 buf->writestring(Token::toChars(e->op)); 2762 expToBuffer(e->e1, precedence[e->op]); 2763 } 2764 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 2774 void visit(CompileExp *e) 2775 { 2776 buf->writestring("mixin("); 2777 expToBuffer(e->e1, PREC_assign); 2778 buf->writeByte(')'); 2779 } 2780 2781 void visit(ImportExp *e) 2782 { 2783 buf->writestring("import("); 2784 expToBuffer(e->e1, PREC_assign); 2785 buf->writeByte(')'); 2786 } 2787 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 2800 void visit(DotIdExp *e) 2801 { 2802 expToBuffer(e->e1, PREC_primary); 2803 buf->writeByte('.'); 2804 buf->writestring(e->ident->toChars()); 2805 } 2806 2807 void visit(DotTemplateExp *e) 2808 { 2809 expToBuffer(e->e1, PREC_primary); 2810 buf->writeByte('.'); 2811 buf->writestring(e->td->toChars()); 2812 } 2813 2814 void visit(DotVarExp *e) 2815 { 2816 expToBuffer(e->e1, PREC_primary); 2817 buf->writeByte('.'); 2818 buf->writestring(e->var->toChars()); 2819 } 2820 2821 void visit(DotTemplateInstanceExp *e) 2822 { 2823 expToBuffer(e->e1, PREC_primary); 2824 buf->writeByte('.'); 2825 e->ti->accept(this); 2826 } 2827 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 2839 void visit(DotTypeExp *e) 2840 { 2841 expToBuffer(e->e1, PREC_primary); 2842 buf->writeByte('.'); 2843 buf->writestring(e->sym->toChars()); 2844 } 2845 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 2864 void visit(PtrExp *e) 2865 { 2866 buf->writeByte('*'); 2867 expToBuffer(e->e1, precedence[e->op]); 2868 } 2869 2870 void visit(DeleteExp *e) 2871 { 2872 buf->writestring("delete "); 2873 expToBuffer(e->e1, precedence[e->op]); 2874 } 2875 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 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 2897 void visit(VectorArrayExp *e) 2898 { 2899 expToBuffer(e->e1, PREC_primary); 2900 buf->writestring(".array"); 2901 } 2902 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 2922 void visit(ArrayLengthExp *e) 2923 { 2924 expToBuffer(e->e1, PREC_primary); 2925 buf->writestring(".length"); 2926 } 2927 2928 void visit(IntervalExp *e) 2929 { 2930 expToBuffer(e->lwr, PREC_assign); 2931 buf->writestring(".."); 2932 expToBuffer(e->upr, PREC_assign); 2933 } 2934 2935 void visit(DelegatePtrExp *e) 2936 { 2937 expToBuffer(e->e1, PREC_primary); 2938 buf->writestring(".ptr"); 2939 } 2940 2941 void visit(DelegateFuncptrExp *e) 2942 { 2943 expToBuffer(e->e1, PREC_primary); 2944 buf->writestring(".funcptr"); 2945 } 2946 2947 void visit(ArrayExp *e) 2948 { 2949 expToBuffer(e->e1, PREC_primary); 2950 buf->writeByte('['); 2951 argsToBuffer(e->arguments); 2952 buf->writeByte(']'); 2953 } 2954 2955 void visit(DotExp *e) 2956 { 2957 expToBuffer(e->e1, PREC_primary); 2958 buf->writeByte('.'); 2959 expToBuffer(e->e2, PREC_primary); 2960 } 2961 2962 void visit(IndexExp *e) 2963 { 2964 expToBuffer(e->e1, PREC_primary); 2965 buf->writeByte('['); 2966 sizeToBuffer(e->e2); 2967 buf->writeByte(']'); 2968 } 2969 2970 void visit(PostExp *e) 2971 { 2972 expToBuffer(e->e1, precedence[e->op]); 2973 buf->writestring(Token::toChars(e->op)); 2974 } 2975 2976 void visit(PreExp *e) 2977 { 2978 buf->writestring(Token::toChars(e->op)); 2979 expToBuffer(e->e1, precedence[e->op]); 2980 } 2981 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 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 2999 void visit(DefaultInitExp *e) 3000 { 3001 buf->writestring(Token::toChars(e->subop)); 3002 } 3003 3004 void visit(ClassReferenceExp *e) 3005 { 3006 buf->writestring(e->value->toChars()); 3007 } 3008 3009 //////////////////////////////////////////////////////////////////////////// 3010 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 3026 void visit(TemplateThisParameter *tp) 3027 { 3028 buf->writestring("this "); 3029 visit((TemplateTypeParameter *)tp); 3030 } 3031 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 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 3066 void visit(TemplateTupleParameter *tp) 3067 { 3068 buf->writestring(tp->ident->toChars()); 3069 buf->writestring("..."); 3070 } 3071 3072 //////////////////////////////////////////////////////////////////////////// 3073 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 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 3090 void visit(StaticIfCondition *c) 3091 { 3092 buf->writestring("static if ("); 3093 c->exp->accept(this); 3094 buf->writeByte(')'); 3095 } 3096 3097 //////////////////////////////////////////////////////////////////////////// 3098 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 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 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 3205void toCBuffer(Statement *s, OutBuffer *buf, HdrGenState *hgs) 3206{ 3207 PrettyPrintVisitor v(buf, hgs); 3208 s->accept(&v); 3209} 3210 3211void toCBuffer(Type *t, OutBuffer *buf, Identifier *ident, HdrGenState *hgs) 3212{ 3213 PrettyPrintVisitor v(buf, hgs); 3214 v.typeToBuffer(t, ident); 3215} 3216 3217void 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() 3224void 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 3232void toCBuffer(Initializer *iz, OutBuffer *buf, HdrGenState *hgs) 3233{ 3234 PrettyPrintVisitor v(buf, hgs); 3235 iz->accept(&v); 3236} 3237 3238bool 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 */ 3264const 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 3330void trustToBuffer(OutBuffer *buf, TRUST trust) 3331{ 3332 const char *p = trustToChars(trust); 3333 if (p) 3334 buf->writestring(p); 3335} 3336 3337const 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 3350void 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 3361const 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 3378void 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 3392const 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 3409void 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 3418void functionToBufferWithIdent(TypeFunction *tf, OutBuffer *buf, const char *ident) 3419{ 3420 HdrGenState hgs; 3421 PrettyPrintVisitor v(buf, &hgs); 3422 v.visitFuncIdentWithPostfix(tf, ident); 3423} 3424 3425void 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 */ 3434void 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 3450void toCBuffer(TemplateParameter *tp, OutBuffer *buf, HdrGenState *hgs) 3451{ 3452 PrettyPrintVisitor v(buf, hgs); 3453 tp->accept(&v); 3454} 3455 3456void 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 3472const 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