Have Read the '#'
| 661 | |
| 662 | // Have Read the '#' |
| 663 | void Preprocessor::ParseInclude(TokenSequence& is, TokenSequence ls) { |
| 664 | bool next = ls.Next()->str_ == "include_next"; // Skip 'include' |
| 665 | if (!ls.Test(Token::LITERAL) && !ls.Test('<')) { |
| 666 | TokenSequence ts; |
| 667 | Expand(ts, ls, true); |
| 668 | ls = ts; |
| 669 | } |
| 670 | |
| 671 | auto tok = ls.Next(); |
| 672 | if (tok->tag_ == Token::LITERAL) { |
| 673 | if (!ls.Empty()) { |
| 674 | Error(ls.Peek(), "expect new line"); |
| 675 | } |
| 676 | std::string filename; |
| 677 | Scanner(tok).ScanLiteral(filename); |
| 678 | auto fullPath = SearchFile(filename, false, next, *tok->loc_.filename_); |
| 679 | if (fullPath == nullptr) |
| 680 | Error(tok, "%s: No such file or directory", filename.c_str()); |
| 681 | |
| 682 | IncludeFile(is, fullPath); |
| 683 | } |
| 684 | else if (tok->tag_ == '<') { |
| 685 | auto lhs = tok; |
| 686 | auto rhs = tok; |
| 687 | int cnt = 1; |
| 688 | while (!(rhs = ls.Next())->IsEOF()) { |
| 689 | if (rhs->tag_ == '<') |
| 690 | ++cnt; |
| 691 | else if (rhs->tag_ == '>') |
| 692 | --cnt; |
| 693 | if (cnt == 0) |
| 694 | break; |
| 695 | } |
| 696 | if (cnt != 0) |
| 697 | Error(rhs, "expect '>'"); |
| 698 | if (!ls.Empty()) |
| 699 | Error(ls.Peek(), "expect new line"); |
| 700 | |
| 701 | const auto& filename = Scanner::ScanHeadName(lhs, rhs); |
| 702 | auto fullPath = SearchFile(filename, true, next, *tok->loc_.filename_); |
| 703 | if (fullPath == nullptr) { |
| 704 | Error(tok, "%s: No such file or directory", filename.c_str()); |
| 705 | } |
| 706 | IncludeFile(is, fullPath); |
| 707 | } |
| 708 | else { |
| 709 | Error(tok, "expect filename(string or in '<>')"); |
| 710 | } |
| 711 | } |
| 712 | |
| 713 | |
| 714 | void Preprocessor::ParseUndef(TokenSequence ls) { |