-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
153 lines (118 loc) · 4.36 KB
/
main.cpp
File metadata and controls
153 lines (118 loc) · 4.36 KB
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <iostream>
#include <fstream>
#include "lang/config.h"
#include "lang/pp/ssource/pp_including_ssource.h"
#include "lang/pp/ssource/pp_nocomment_ssource.h"
#include "lang/pp/include/pp_included_file_ssource.h"
#include "lang/pp/pp_dependency_observer.h"
#include "lang/pp/pp_main_directive_processor.h"
#include "lang/error/include_error.h"
#include "main_args.h"
/*
*
* THE MASTER GENERAL BORING TODO LIST
* In order of priority
*
* DONE: #incbin & #incext
* TODO: "#define __strict" & "#define __sticky" - to overwrite pp.macro.strictMacroFormat
* TODO: pp.include.skipMissingFiles - to skip missing files
* TODO: "#include __optional" & "#include __required"- to overwrite pp.include.skipMissingFiles
* TODO: "#if[n]def __<something>" - to not have to check for a specific parameter count
* TODO; "#undef __<something>" - to undefine all macros of that name (regardless of argc)
* TODO: some option to allow newline escapes (using character '\' maybe probably)
* TODO: "#if <expression>" for generic conditions
* TODO: inline directives (proposed syntax: #{<directive>})
*
*/
template<typename CharType>
std::basic_ostream<CharType>& get_cout() { throw 0; }
template<> std::basic_ostream<wchar_t>& get_cout<wchar_t>() { return std::wcout; }
template<> std::basic_ostream<char>& get_cout<char>() { return std::cout; }
template<typename FuncType>
static void for_ostream_of(const fs::path& outFile, FuncType func) {
if (outFile.empty())
func(get_cout<lang::char_type>());
else {
std::basic_ofstream<lang::char_type> fStream;
fStream.open(outFile.native());
if (!fStream.is_open())
throw std::runtime_error(std::string("Couldn't open file for write: ").append(outFile.string()));
func(fStream);
}
}
int main(int argc, char** argv) {
if (args::should_show_help(argc, argv)) {
args::show_help(std::cout, argv[0]);
return 0;
}
lang::config config;
try {
args::args_to_config(config, argc, argv);
} catch (const std::exception& e) {
std::cerr << "ERROR - argument scanning failed - " << e.what() << std::endl;
return 1;
}
if (config.pp.eaCompat.force) {
config.pp.eaCompat.enableBinary = true; // #incbin, #incext
config.pp.eaCompat.enableDirectiveAliases = true; // #inctext, #inctevent
config.pp.macro.strictMacroFormat = false; // #define Macro(a, b) abracadabra; Marco(0, 1) -> 01r0c0d01r0
config.pp.tool.addToStdout = true; // #incext implies --to-stdout
config.pp.include.enableRootRelative = false;
config.pp.tool.enableLocalTools = false;
config.pp.tool.enableSystemTools = false;
}
macro_library library;
pp_dependency_observer dependencyMaker(&config);
pp_including_ssource mainSource(&config);
pp_nocomment_ssource source(mainSource);
pp_main_directive_processor dp(
&config,
mainSource,
dependencyMaker,
library
);
try {
for (const auto& define : config.pp.macro.extraDefines)
library.define_macro(define);
if (config.pp.input.empty())
throw std::runtime_error("no input");
if (!fs::exists(config.pp.input))
throw no_include_error(config.pp.input.c_str());
dependencyMaker.add_dependency(config.pp.input);
mainSource.include<pp_included_file_ssource>(false, config.pp.input);
} catch (const std::exception& e) {
std::cerr << "ERROR - " << e.what() << std::endl;
return 1;
}
try {
if (config.pp.emulate) {
while (!source.at_end())
dp.process_directive(source.get_string());
} else {
for_ostream_of(config.pp.output, [&dp, &source, &library] (std::basic_ostream<lang::char_type>& out) {
while (!source.at_end()) {
lang::string_type str = source.get_string();
if (dp.process_directive(str))
continue;
if (dp.in_selection())
out << library.expand(std::move(str)) << std::endl;
}
});
}
if (config.pp.makedep.enable) {
for_ostream_of(config.pp.makedep.output, [&dependencyMaker] (std::basic_ostream<lang::char_type>& out) {
dependencyMaker.generate_makefile(out);
});
}
} catch (const std::exception& e) {
std::cerr << "[";
if (mainSource.current_directory().size())
std::cerr << mainSource.current_directory().string() << ":";
lang::string_type srcName = mainSource.current_source_name();
std::cerr << std::string(srcName.begin(), srcName.end())
<< "(" << mainSource.current_source_line() << ")] ERROR - "
<< e.what() << std::endl;
return 1;
}
return 0;
}