https://github.com/akkartik/mu/blob/main/001help.cc
1
2
3
4 :(before "End Commandline Parsing")
5 if (argc <= 1 || is_equal(argv[1], "--help")) {
6
7
8 cerr << get(Help, "usage");
9 return 0;
10 }
11
12
13
14
15 char** arg = &argv[1];
16 while (argc > 1 && starts_with(*arg, "--")) {
17 if (false)
18 ;
19
20 else
21 cerr << "skipping unknown option " << *arg << '\n';
22 --argc; ++argv; ++arg;
23 }
24
25 if (is_equal(argv[1], "help")) {
26 if (argc == 2) {
27 cerr << "help on what?\n";
28 help_contents();
29 return 0;
30 }
31 string key(argv[2]);
32
33 if (contains_key(Help, key)) {
34 cerr << get(Help, key);
35 return 0;
36 }
37 else {
38 cerr << "No help found for '" << key << "'\n";
39 help_contents();
40 cerr << "Please check your command for typos.\n";
41 return 1;
42 }
43 }
44
45 :(code)
46 void help_contents() {
47 cerr << "Available top-level topics:\n";
48 cerr << " usage\n";
49
50 }
51
52 :(before "End Globals")
53 map<string, string> Help;
54 :(before "End Includes")
55 #include <map>
56 using std::map;
57 :(before "End One-time Setup")
58 init_help();
59 :(code)
60 void init_help() {
61 put(Help, "usage",
62 "bootstrap: the bootstrap translator for SubX.\n"
63 "This program also wraps some miscellaneous useful functionality:\n"
64 " - an x86 emulator: `bootstrap run`\n"
65 " - online help: `bootstrap help`\n"
66 "\n"
67 "== Ways to invoke bootstrap\n"
68 "- See this message:\n"
69 " bootstrap --help\n"
70 "- Convert a textual SubX program into a standard ELF binary that you can\n"
71 " run on your computer:\n"
72 " bootstrap translate input1.subx input2.subx ... -o <output ELF binary>\n"
73 "- Run a SubX binary using SubX itself (for better error messages):\n"
74 " bootstrap run <ELF binary>\n"
75 "- Run all bootstrap's unit tests:\n"
76 " bootstrap test\n"
77 "- Run a single unit test:\n"
78 " bootstrap test <test name>\n"
79 " e.g. bootstrap test test_copy_imm32_to_EAX\n"
80 "\n"
81 "== Debugging aids\n"
82 "- Add '--trace' to any of these commands to save a trace to disk at the end.\n"
83 " This can run out of memory for long-running commands.\n"
84 "- Add '--debug' to emit additional debug information during translation.\n"
85 " 'bootstrap --debug translate' will save metadata to disk that\n"
86 " 'bootstrap --trace run' uses to make traces more informative.\n"
87 "\n"
88 "Options starting with '--' must always come before any other arguments.\n"
89 "\n"
90 "To start learning how to write SubX programs, see Readme.md (particularly\n"
91 "the section on the x86 instruction set) and then run:\n"
92 " bootstrap help\n"
93 );
94
95 }
96
97 :(code)
98 bool is_equal(char* s, const char* lit) {
99 return strncmp(s, lit, strlen(lit)) == 0;
100 }
101
102 bool starts_with(const string& s, const string& pat) {
103 string::const_iterator a=s.begin(), b=pat.begin();
104 for (; a!=s.end() && b!=pat.end(); ++a, ++b)
105 if (*a != *b) return false;
106 return b == pat.end();
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
154
155
156
157
158
159
160
161
162
163
164
165 :(before "End Includes")
166 #define SIZE(X) (assert((X).size() < (1LL<<(sizeof(int)*8-2))), static_cast<int>((X).size()))
167
168
169
170
171 :(before "atexit(reset)")
172 initialize_signal_handlers();
173
174
175 :(code)
176
177 void initialize_signal_handlers() {
178 struct sigaction action;
179 bzero(&action, sizeof(action));
180 action.sa_sigaction = dump_and_exit;
181 sigemptyset(&action.sa_mask);
182 sigaction(SIGABRT, &action, NULL);
183 sigaction(SIGILL, &action, NULL);
184 }
185 void dump_and_exit(int sig, siginfo_t* , void* ) {
186 switch (sig) {
187 case SIGABRT:
188 #ifndef __APPLE__
189 cerr << "SIGABRT: might be an integer overflow if it wasn't an assert() failure\n";
190 _Exit(1);
191 #endif
192 break;
193 case SIGILL:
194 #ifdef __APPLE__
195 cerr << "SIGILL: most likely caused by integer overflow\n";
196 _Exit(1);
197 #endif
198 break;
199 default:
200 break;
201 }
202 }
203 :(before "End Includes")
204 #include <signal.h>
205
206
207 :(before "Globals")
208
209 template<typename T> typename T::mapped_type& get(T& map, typename T::key_type const& key) {
210 typename T::iterator iter(map.find(key));
211 if (iter == map.end()) {
212 cerr << "get couldn't find key '" << key << "'\n";
213 assert(iter != map.end());
214 }
215 return iter->second;
216 }
217 template<typename T> typename T::mapped_type const& get(const T& map, typename T::key_type const& key) {
218 typename T::const_iterator iter(map.find(key));
219 if (iter == map.end()) {
220 cerr << "get couldn't find key '" << key << "'\n";
221 assert(iter != map.end());
222 }
223 return iter->second;
224 }
225 template<typename T> typename T::mapped_type const& put(T& map, typename T::key_type const& key, typename T::mapped_type const& value) {
226 map[key] = value;
227 return map[key];
228 }
229 template<typename T> bool contains_key(T& map, typename T::key_type const& key) {
230 return map.find(key) != map.end();
231 }
232 template<typename T> typename T::mapped_type& get_or_insert(T& map, typename T::key_type const& key) {
233 return map[key];
234 }
235 template<typename T> typename T::mapped_type const& put_new(T& map, typename T::key_type const& key, typename T::mapped_type const& value) {
236 assert(map.find(key) == map.end());
237 map[key] = value;
238 return map[key];
239 }
240
241
242
243
244
245
246 :(code)
247 bool has_data(istream& in) {
248 return in && !in.eof();
249 }
250
251 :(before "End Includes")
252 #include <assert.h>
253
254 #include <iostream>
255 using std::istream;
256 using std::ostream;
257 using std::iostream;
258 using std::cin;
259 using std::cout;
260 using std::cerr;
261 #include <iomanip>
262
263 #include <string.h>
264 #include <string>
265 using std::string;
266
267 #include <algorithm>
268 using std::min;
269 using std::max;