summaryrefslogtreecommitdiffhomepage
path: root/64x0/cc2/source/cppfront.cpp
blob: 989a6adcbe5202ba476154c006024eb00d217a6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

//  Copyright (c) Herb Sutter
//  SPDX-License-Identifier: CC-BY-NC-ND-4.0

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.


//===========================================================================
//  main - driver
//===========================================================================

#include "to_cpp1.h"

static auto flag_debug_output = false;
static cpp2::cmdline_processor::register_flag cmd_debug(
    9,
    "debug",
    "Emit compiler debug output",
    []{ flag_debug_output = true; }
);

auto main(
    int   argc,
    char* argv[]
)
    -> int
{
    using namespace cpp2;

    cmdline.set_args(argc, argv);
    cmdline.process_flags();

    if (cmdline.help_was_requested()) {
        return EXIT_SUCCESS;
    }

    if (cmdline.arguments().empty()) {
        std::cerr << "cppfront: error: no input files (try -help)\n";
        return EXIT_FAILURE;
    }

    //  For each Cpp2 source file
    int exit_status = EXIT_SUCCESS;
    for (auto const& arg : cmdline.arguments())
    {
        auto& out = flag_cpp1_filename != "stdout" ? std::cout : std::cerr;

        out << arg.text << "...";

        //  Load + lex + parse + sema
        cppfront c(arg.text);

        //  Generate Cpp1 (this may catch additional late errors)
        auto count = c.lower_to_cpp1();

        //  If there were no errors, say so and generate Cpp1
        if (c.had_no_errors())
        {
            if (!c.has_cpp1()) {
                out << " ok (all Cpp2, passes safety checks)\n";
            }
            else if (c.has_cpp2()) {
                out << " ok (mixed Cpp1/Cpp2, Cpp2 code passes safety checks)\n";
            }
            else {
                out << " ok (all Cpp1)\n";
            }

            if (flag_verbose) {
                out << "   Cpp1: " << count.cpp1_lines << " line" << (count.cpp1_lines != 1 ? "s" : "");
                out << "\n   Cpp2: " << count.cpp2_lines << " line" << (count.cpp2_lines != 1 ? "s" : "");
                auto total = count.cpp1_lines + count.cpp2_lines;
                if (total > 0) {
                    out << " (";
                    if (count.cpp2_lines / count.cpp1_lines > 25) {
                        out << std::setprecision(3)
                            << 100.0 * count.cpp2_lines / total;
                    }
                    else {
                        out << 100 * count.cpp2_lines / total;
                    }
                    out << "%)";
                }
            }

            out << "\n";
        }
        //  Otherwise, print the errors
        else
        {
            std::cerr << "\n";
            c.print_errors();
            std::cerr << "\n";
            exit_status = EXIT_FAILURE;
        }

        //  And, if requested, the debug information
        if (flag_debug_output) {
            c.debug_print();
        }
    }

    if (flag_internal_debug) {
        stackinstr::print_deepest();
        stackinstr::print_largest();
    }

    return exit_status;
}