From d3a9db3aff54ea485f409eaaef3d8f56ad77f0dc Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 5 Oct 2020 11:00:05 -0700 Subject: 6958 --- html/001help.cc.html | 384 +++++++++++++++++++++++++-------------------------- 1 file changed, 190 insertions(+), 194 deletions(-) (limited to 'html/001help.cc.html') diff --git a/html/001help.cc.html b/html/001help.cc.html index 52cd0df3..9edab617 100644 --- a/html/001help.cc.html +++ b/html/001help.cc.html @@ -15,14 +15,14 @@ body { font-size:12pt; font-family: monospace; color: #000000; background-color: a { color:inherit; } * { font-size:12pt; font-size: 1em; } .CommentedCode { color: #8a8a8a; } +.PreProc { color: #c000c0; } .LineNr { } +.SpecialChar { color: #d70000; } .Constant { color: #008787; } .Comment { color: #005faf; } .Delimiter { color: #c000c0; } -.Special { color: #d70000; } .Identifier { color: #af5f00; } .Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; } -.PreProc { color: #c000c0; } .cSpecial { color: #008000; } --> @@ -63,10 +63,10 @@ if ('onhashchange' in window) { 2 //: This should give you a sense for what to look forward to in later layers. 3 4 :(before "End Commandline Parsing") - 5 if (argc <= 1 || is_equal(argv[1], "--help")) { + 5 if (argc <= 1 || is_equal(argv[1], "--help")) { 6 //: this is the functionality later layers will provide 7 // currently no automated tests for commandline arg parsing - 8 cerr << get(Help, "usage"); + 8 cerr << get(Help, "usage"); 9 return 0; 10 } 11 @@ -74,7 +74,7 @@ if ('onhashchange' in window) { 13 //: Options always begin with '--' and are always the first arguments. An 14 //: option will never follow a non-option. 15 char** arg = &argv[1]; - 16 while (argc > 1 && starts_with(*arg, "--")) { + 16 while (argc > 1 && starts_with(*arg, "--")) { 17 if (false) 18 ; // no-op branch just so any further additions can consistently always start with 'else' 19 // End Commandline Options(*arg) @@ -83,7 +83,7 @@ if ('onhashchange' in window) { 22 --argc; ++argv; ++arg; 23 } 24 - 25 if (is_equal(argv[1], "help")) { + 25 if (is_equal(argv[1], "help")) { 26 if (argc == 2) { 27 cerr << "help on what?\n"; 28 help_contents(); @@ -91,8 +91,8 @@ if ('onhashchange' in window) { 30 } 31 string key(argv[2]); 32 // End Help Special-cases(key) - 33 if (contains_key(Help, key)) { - 34 cerr << get(Help, key); + 33 if (contains_key(Help, key)) { + 34 cerr << get(Help, key); 35 return 0; 36 } 37 else { @@ -111,7 +111,7 @@ if ('onhashchange' in window) { 50 } 51 52 :(before "End Globals") - 53 map<string, string> Help; + 53 map<string, string> Help; 54 :(before "End Includes") 55 #include <map> 56 using std::map; @@ -119,7 +119,7 @@ if ('onhashchange' in window) { 58 init_help(); 59 :(code) 60 void init_help() { - 61 put(Help, "usage", + 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" @@ -142,196 +142,192 @@ if ('onhashchange' in window) { 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 // End Help Texts - 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 (/*nada*/; a!=s.end() && b!=pat.end(); ++a, ++b) -109 if (*a != *b) return false; -110 return b == pat.end(); -111 } -112 -113 //: I'll throw some style conventions here for want of a better place for them. -114 //: As a rule I hate style guides. Do what you want, that's my motto. But since -115 //: we're dealing with C/C++, the one big thing we want to avoid is undefined -116 //: behavior. If a compiler ever encounters undefined behavior it can make -117 //: your program do anything it wants. -118 //: -119 //: For reference, my checklist of undefined behaviors to watch out for: -120 //: out-of-bounds access -121 //: uninitialized variables -122 //: use after free -123 //: dereferencing invalid pointers: null, a new of size 0, others -124 //: -125 //: casting a large number to a type too small to hold it -126 //: -127 //: integer overflow -128 //: division by zero and other undefined expressions -129 //: left-shift by negative count -130 //: shifting values by more than or equal to the number of bits they contain -131 //: bitwise operations on signed numbers -132 //: -133 //: Converting pointers to types of different alignment requirements -134 //: T* -> void* -> T*: defined -135 //: T* -> U* -> T*: defined if non-function pointers and alignment requirements are same -136 //: function pointers may be cast to other function pointers + 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 // End Help Texts + 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 (/*nada*/; a!=s.end() && b!=pat.end(); ++a, ++b) +105 if (*a != *b) return false; +106 return b == pat.end(); +107 } +108 +109 //: I'll throw some style conventions here for want of a better place for them. +110 //: As a rule I hate style guides. Do what you want, that's my motto. But since +111 //: we're dealing with C/C++, the one big thing we want to avoid is undefined +112 //: behavior. If a compiler ever encounters undefined behavior it can make +113 //: your program do anything it wants. +114 //: +115 //: For reference, my checklist of undefined behaviors to watch out for: +116 //: out-of-bounds access +117 //: uninitialized variables +118 //: use after free +119 //: dereferencing invalid pointers: null, a new of size 0, others +120 //: +121 //: casting a large number to a type too small to hold it +122 //: +123 //: integer overflow +124 //: division by zero and other undefined expressions +125 //: left-shift by negative count +126 //: shifting values by more than or equal to the number of bits they contain +127 //: bitwise operations on signed numbers +128 //: +129 //: Converting pointers to types of different alignment requirements +130 //: T* -> void* -> T*: defined +131 //: T* -> U* -> T*: defined if non-function pointers and alignment requirements are same +132 //: function pointers may be cast to other function pointers +133 //: +134 //: Casting a numeric value into a value that can't be represented by the target type (either directly or via static_cast) +135 //: +136 //: To guard against these, some conventions: 137 //: -138 //: Casting a numeric value into a value that can't be represented by the target type (either directly or via static_cast) +138 //: 0. Initialize all primitive variables in functions and constructors. 139 //: -140 //: To guard against these, some conventions: -141 //: -142 //: 0. Initialize all primitive variables in functions and constructors. +140 //: 1. Minimize use of pointers and pointer arithmetic. Avoid 'new' and +141 //: 'delete' as far as possible. Rely on STL to perform memory management to +142 //: avoid use-after-free issues (and memory leaks). 143 //: -144 //: 1. Minimize use of pointers and pointer arithmetic. Avoid 'new' and -145 //: 'delete' as far as possible. Rely on STL to perform memory management to -146 //: avoid use-after-free issues (and memory leaks). -147 //: -148 //: 2. Avoid naked arrays to avoid out-of-bounds access. Never use operator[] -149 //: except with map. Use at() with STL vectors and so on. -150 //: -151 //: 3. Valgrind all the things. +144 //: 2. Avoid naked arrays to avoid out-of-bounds access. Never use operator[] +145 //: except with map. Use at() with STL vectors and so on. +146 //: +147 //: 3. Valgrind all the things. +148 //: +149 //: 4. Avoid unsigned numbers. Not strictly an undefined-behavior issue, but +150 //: the extra range doesn't matter, and it's one less confusing category of +151 //: interaction gotchas to worry about. 152 //: -153 //: 4. Avoid unsigned numbers. Not strictly an undefined-behavior issue, but -154 //: the extra range doesn't matter, and it's one less confusing category of -155 //: interaction gotchas to worry about. -156 //: -157 //: Corollary: don't use the size() method on containers, since it returns an -158 //: unsigned and that'll cause warnings about mixing signed and unsigned, -159 //: yadda-yadda. Instead use this macro below to perform an unsafe cast to -160 //: signed. We'll just give up immediately if a container's ever too large. -161 //: Basically, Mu is not concerned about this being a little slower than it -162 //: could be. (https://gist.github.com/rygorous/e0f055bfb74e3d5f0af20690759de5a7) -163 //: -164 //: Addendum to corollary: We're going to uniformly use int everywhere, to -165 //: indicate that we're oblivious to number size, and since Clang on 32-bit -166 //: platforms doesn't yet support multiplication over 64-bit integers, and -167 //: since multiplying two integers seems like a more common situation to end -168 //: up in than integer overflow. -169 :(before "End Includes") -170 #define SIZE(X) (assert((X).size() < (1LL<<(sizeof(int)*8-2))), static_cast<int>((X).size())) -171 -172 //: 5. Integer overflow is guarded against at runtime using the -ftrapv flag -173 //: to the compiler, supported by Clang (GCC version only works sometimes: -174 //: http://stackoverflow.com/questions/20851061/how-to-make-gcc-ftrapv-work). -175 :(before "atexit(reset)") -176 initialize_signal_handlers(); // not always necessary, but doesn't hurt -177 //? cerr << INT_MAX+1 << '\n'; // test overflow -178 //? assert(false); // test SIGABRT -179 :(code) -180 // based on https://spin.atomicobject.com/2013/01/13/exceptions-stack-traces-c -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); // assert() failure or integer overflow on linux (with -ftrapv) -187 sigaction(SIGILL, &action, NULL); // integer overflow on OS X (with -ftrapv) -188 } -189 void dump_and_exit(int sig, siginfo_t* /*unused*/, void* /*unused*/) { -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 //: 6. Map's operator[] being non-const is fucking evil. -211 :(before "Globals") // can't generate prototypes for these -212 // from http://stackoverflow.com/questions/152643/idiomatic-c-for-reading-from-a-const-map -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; +153 //: Corollary: don't use the size() method on containers, since it returns an +154 //: unsigned and that'll cause warnings about mixing signed and unsigned, +155 //: yadda-yadda. Instead use this macro below to perform an unsafe cast to +156 //: signed. We'll just give up immediately if a container's ever too large. +157 //: Basically, Mu is not concerned about this being a little slower than it +158 //: could be. (https://gist.github.com/rygorous/e0f055bfb74e3d5f0af20690759de5a7) +159 //: +160 //: Addendum to corollary: We're going to uniformly use int everywhere, to +161 //: indicate that we're oblivious to number size, and since Clang on 32-bit +162 //: platforms doesn't yet support multiplication over 64-bit integers, and +163 //: since multiplying two integers seems like a more common situation to end +164 //: up in than integer overflow. +165 :(before "End Includes") +166 #define SIZE(X) (assert((X).size() < (1LL<<(sizeof(int)*8-2))), static_cast<int>((X).size())) +167 +168 //: 5. Integer overflow is guarded against at runtime using the -ftrapv flag +169 //: to the compiler, supported by Clang (GCC version only works sometimes: +170 //: http://stackoverflow.com/questions/20851061/how-to-make-gcc-ftrapv-work). +171 :(before "atexit(reset)") +172 initialize_signal_handlers(); // not always necessary, but doesn't hurt +173 //? cerr << INT_MAX+1 << '\n'; // test overflow +174 //? assert(false); // test SIGABRT +175 :(code) +176 // based on https://spin.atomicobject.com/2013/01/13/exceptions-stack-traces-c +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); // assert() failure or integer overflow on linux (with -ftrapv) +183 sigaction(SIGILL, &action, NULL); // integer overflow on OS X (with -ftrapv) +184 } +185 void dump_and_exit(int sig, siginfo_t* /*unused*/, void* /*unused*/) { +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 //: 6. Map's operator[] being non-const is fucking evil. +207 :(before "Globals") // can't generate prototypes for these +208 // from http://stackoverflow.com/questions/152643/idiomatic-c-for-reading-from-a-const-map +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> 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 //: The contract: any container that relies on get_or_insert should never call -245 //: contains_key. -246 -247 //: 7. istreams are a royal pain in the arse. You have to be careful about -248 //: what subclass you try to putback into. You have to watch out for the pesky -249 //: failbit and badbit. Just avoid eof() and use this helper instead. -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> +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 //: The contract: any container that relies on get_or_insert should never call +241 //: contains_key. +242 +243 //: 7. istreams are a royal pain in the arse. You have to be careful about +244 //: what subclass you try to putback into. You have to watch out for the pesky +245 //: failbit and badbit. Just avoid eof() and use this helper instead. +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 <string.h> -268 #include <string> -269 using std::string; -270 -271 #include <algorithm> -272 using std::min; -273 using std::max; +267 #include <algorithm> +268 using std::min; +269 using std::max; -- cgit 1.4.1-2-gfad0