https://github.com/akkartik/mu/blob/master/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 add information to traces. 'bootstrap --debug translate'\n"
85 " will save metadata to disk that 'bootstrap --trace run' uses to make traces\n"
86 " more informative.\n"
87 "- Add '--dump --trace' to emit a trace incrementally to stderr.\n"
88 " This approach will work even for long-running programs.\n"
89 " (Though the combination of flags is counter-intuitive and can probably\n"
90 " be improved.)\n"
91 "\n"
92 "Options starting with '--' must always come before any other arguments.\n"
93 "\n"
94 "To start learning how to write SubX programs, see Readme.md (particularly\n"
95 "the section on the x86 instruction set) and then run:\n"
96 " bootstrap help\n"
97 );
98
99 }
100
101 :(code)
102 bool is_equal(char* s, const char* lit) {
103 return strncmp(s, lit, strlen(lit)) == 0;
104 }
105
106 bool starts_with(const string& s, const string& pat) {
107 string::const_iterator a=s.begin(), b=pat.begin();
108 for (; a!=s.end() && b!=pat.end(); ++a, ++b)
109 if (*a != *b) return false;
110 return b == pat.end();
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
166
167
168
169 :(before "End Includes")
170 #define SIZE(X) (assert((X).size() < (1LL<<(sizeof(int)*8-2))), static_cast<int>((X).size()))
171
172
173
174
175 :(before "atexit(reset)")
176 initialize_signal_handlers();
177
178
179 :(code)
180
181 void initialize_signal_handlers() {
182 struct sigaction action;
183 bzero(&action, sizeof(action));
184 action.sa_sigaction = dump_and_exit;
185 sigemptyset(&action.sa_mask);
186 sigaction(SIGABRT, &action, NULL);
187 sigaction(SIGILL, &action, NULL);
188 }
189 void dump_and_exit(int sig, siginfo_t* , void* ) {
190 switch (sig) {
191 case SIGABRT:
192 #ifndef __APPLE__
193 cerr << "SIGABRT: might be an integer overflow if it wasn't an assert() failure\n";
194 _Exit(1);
195 #endif
196 break;
197 case SIGILL:
198 #ifdef __APPLE__
199 cerr << "SIGILL: most likely caused by integer overflow\n";
200 _Exit(1);
201 #endif
202 break;
203 default:
204 break;
205 }
206 }
207 :(before "End Includes")
208 #include <signal.h>
209
210
211 :(before "Globals")
212
213 template<typename T> typename T::mapped_type& get(T& map, typename T::key_type const& key) {
214 typename T::iterator iter(map.find(key));
215 if (iter == map.end()) {
216 cerr << "get couldn't find key '" << key << "'\n";
217 assert(iter != map.end());
218 }
219 return iter->second;
220 }
221 template<typename T> typename T::mapped_type const& get(const T& map, typename T::key_type const& key) {
222 typename T::const_iterator iter(map.find(key));
223 if (iter == map.end()) {
224 cerr << "get couldn't find key '" << key << "'\n";
225 assert(iter != map.end());
226 }
227 return iter->second;
228 }
229 template<typename T> typename T::mapped_type const& put(T& map, typename T::key_type const& key, typename T::mapped_type const& value) {
230 map[key] = value;
231 return map[key];
232 }
233 template<typename T> bool contains_key(T& map, typename T::key_type const& key) {
234 return map.find(key) != map.end();
235 }
236 template<typename T> typename T::mapped_type& get_or_insert(T& map, typename T::key_type const& key) {
237 return map[key];
238 }
239 template<typename T> typename T::mapped_type const& put_new(T& map, typename T::key_type const& key, typename T::mapped_type const& value) {
240 assert(map.find(key) == map.end());
241 map[key] = value;
242 return map[key];
243 }
244
245
246
247
248
249
250 :(code)
251 bool has_data(istream& in) {
252 return in && !in.eof();
253 }
254
255 :(before "End Includes")
256 #include <assert.h>
257
258 #include <iostream>
259 using std::istream;
260 using std::ostream;
261 using std::iostream;
262 using std::cin;
263 using std::cout;
264 using std::cerr;
265 #include <iomanip>
266
267 #include <string.h>
268 #include <string>
269 using std::string;
270
271 #include <algorithm>
272 using std::min;
273 using std::max;