28constexpr const char*
copyright =
"Copyright (C) 2024-"
30 " Andrew S. Rightenburg\n\n"
31 "This program is free software; you can redistribute it and/or modify\n"
32 "it under the terms of the GNU General Public License as published by\n"
33 "the Free Software Foundation; either version 3 of the License, or\n"
34 "(at your option) any later version.\n\n"
35 "This program is distributed in the hope that it will be useful,\n"
36 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
37 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
38 "GNU General Public License for more details.\n\n"
39 "You should have received a copy of the GNU General Public License\n"
40 "along with this program. If not, see http://www.gnu.org/licenses/.\n";
43 "Usage: bpp [options] [file] ...\n"
44 "If no file is specified, read from stdin\n"
45 "All arguments after the file are passed to the compiled program\n"
73 std::shared_ptr<std::vector<std::string>>
include_paths = std::make_shared<std::vector<std::string>>();
87 auto [compiler_arguments, program_arguments]
90 args.
program_arguments = std::vector<char*>{program_arguments.argv, program_arguments.argv + program_arguments.argc};
92 if (compiler_arguments.getNonOptionArguments().size() > 0) {
93 args.
input_file = std::string(compiler_arguments.getNonOptionArguments()[0]);
96 bool received_output_filename =
false;
97 for (
const auto& arg : compiler_arguments) {
98 switch (arg.getShortOpt()) {
102 std::istringstream version_stream(std::string(arg.getArgument()));
103 uint16_t major, minor;
105 if (!(version_stream >> major >> dot >> minor) || dot !=
'.') {
106 throw std::runtime_error(
"Invalid Bash version format: " + std::string(arg.getArgument()) +
107 "\nExpected format: <major>.<minor> (e.g., 5.2)");
120 if (!std::filesystem::exists(arg.getArgument()) || !std::filesystem::is_directory(arg.getArgument())) {
121 throw std::runtime_error(
"Include path '" + std::string(arg.getArgument()) +
"' does not exist or is not a directory");
123 args.
include_paths->push_back(std::string(arg.getArgument()));
126 if (received_output_filename) {
127 throw std::runtime_error(
"Multiple output files specified");
130 if (std::string(arg.getArgument()) ==
"-") {
136 std::filesystem::path output_path(arg.getArgument());
137 if (output_path.is_absolute()) {
140 args.
output_file = std::filesystem::current_path() / output_path;
147 if (std::filesystem::exists(args.
output_file.value())) {
148 if (!std::filesystem::is_regular_file(args.
output_file.value())) {
149 throw std::runtime_error(
"Output file '" + args.
output_file.value() +
"' is not a regular file");
151 if (access(args.
output_file.value().c_str(), W_OK) != 0) {
152 throw std::runtime_error(
"No write permission for output file '" + args.
output_file.value() +
"'");
155 std::filesystem::path parent_path = std::filesystem::path(args.
output_file.value()).parent_path();
156 if (!std::filesystem::exists(parent_path) || !std::filesystem::is_directory(parent_path)) {
157 throw std::runtime_error(
"Parent directory of output file '" + args.
output_file.value() +
"' does not exist or is not a directory");
159 if (access(parent_path.c_str(), W_OK) != 0) {
160 throw std::runtime_error(
"No write permission for parent directory of output file '" + args.
output_file.value() +
"'");
163 }
catch (
const std::exception& e) {
164 throw std::runtime_error(std::string(
"Could not verify write permission for output file '") + args.
output_file.value() +
"': " + e.what());
Parses command-line arguments based on a set of defined options.
Definition xgetopt.h:532
@ NoArgument
Definition xgetopt.h:179
@ RequiredArgument
Definition xgetopt.h:180
@ AfterFirstNonOptionArgument
Definition xgetopt.h:516
Arguments parse_arguments(int argc, char *argv[])
Definition parse_arguments.h:81
constexpr const char * help_intro
Definition parse_arguments.h:42
constexpr XGetOpt::OptionParser< XGetOpt::Option< 'o', "output", "Specify output file (default: run on exit)", XGetOpt::RequiredArgument >, XGetOpt::Option< 'b', "target-bash", "Target Bash version (default: 5.2)", XGetOpt::RequiredArgument >, XGetOpt::Option< 's', "no-warnings", "Suppress warnings", XGetOpt::NoArgument >, XGetOpt::Option< 'I', "include", "Add directory to include path", XGetOpt::RequiredArgument >, XGetOpt::Option< 't', "tokens", "Display tokens from lexer (do not compile program)", XGetOpt::NoArgument >, XGetOpt::Option< 'p', "parse-tree", "Display parse tree (do not compile program)", XGetOpt::NoArgument >, XGetOpt::Option< 'v', "version", "Display version information and exit", XGetOpt::NoArgument >, XGetOpt::Option< 'h', "help", "Display this help message and exit", XGetOpt::NoArgument > > OptionParser
Definition parse_arguments.h:57
constexpr const char * copyright
Definition parse_arguments.h:28
constexpr const char * program_name
Definition parse_arguments.h:26
Represents the parsed command-line arguments given to the compiler.
Definition parse_arguments.h:68
BashVersion target_bash_version
Definition parse_arguments.h:72
bool display_parse_tree
Definition parse_arguments.h:76
bool exit_early
Definition parse_arguments.h:78
bool display_tokens
Definition parse_arguments.h:75
std::optional< std::string > output_file
Definition parse_arguments.h:71
bool suppress_warnings
Definition parse_arguments.h:74
std::shared_ptr< std::vector< std::string > > include_paths
Definition parse_arguments.h:73
std::optional< std::string > input_file
Definition parse_arguments.h:70
std::vector< char * > program_arguments
Definition parse_arguments.h:69
Represents a Bash version to target for code generation.
Definition BashVersion.h:21
Compile-time representation of a command-line option.
Definition xgetopt.h:200
#define bpp_compiler_updated_year
Definition updated_year.h:1
#define bpp_compiler_version
Definition version.h:1