From e3b555b0cc3c6ef646c119fc3b0e885fb0643562 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Wed, 11 Jan 2017 20:17:06 -0500 Subject: [PATCH] -t xx,xxxx for filetype/auxtype. --- link.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++- optional.h | 26 ++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/link.cpp b/link.cpp index 5679248..4b9db6d 100644 --- a/link.cpp +++ b/link.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -1013,6 +1014,73 @@ bool one_file(const std::string &name) { return rv; } +#if 0 +bool parse_ft(const std::string &s) { + // xx + // xx:xxxx or xx,xxxx + + auto lambda = [](const optional &lhs, const uint8_t rhs) { + if (!lhs) return lhs; + if (rhs >= '0' && rhs <= '9') + return optional((*lhs << 4) + rhs); + if (rhs >= 'a' && rhs <= 'f') + return optional((*lhs << 4) + (rhs - 'a' + 10)); + if (rhs >= 'A' && rhs <= 'F') + return optional((*lhs << 4) + (rhs - 'A') + 10); + + return optional(); + }; + + optional ft; + optional at; + + if (s.length() == 2 || s.length() == 7) { + + ft = std::accumulate(s.begin(), s.begin() + 2, optional(0), lambda); + + if (s.length() == 7) { + ft = optional(); + if (s[2] == ':' || s[2] == ',') + at = std::accumulate(s.begin() + 3, s.end(), optional(0), lambda); + } else at = optional(0); + } + + if (at && ft) { + flags._file_type = *ft; + flags._aux_type = *at; + return true; + } + return false; +} + +#endif + + +bool parse_ft(const std::string &s) { + + if (s.length() != 2 && s.length() != 7) return false; + if (!std::all_of(s.begin(), s.begin() + 2, std::isxdigit)) return false; + if (s.length() == 7) { + if (s[2] != ',' && s[2] != ':') return false; + if (!std::all_of(s.begin() + 3, s.end(), std::isxdigit)) return false; + } + + auto lambda = [](int lhs, uint8_t rhs){ + lhs <<= 4; + if (rhs <= '9') return lhs + rhs - '0'; + return lhs + (rhs | 0x20) - 'a' + 10; + }; + + flags._file_type = std::accumulate(s.begin(), s.begin() + 2, 0, lambda); + flags._aux_type = 0; + + if (s.length() == 7) + flags._aux_type = std::accumulate(s.begin() + 3, s.end(), 0, lambda); + + return true; +} + + void help() { exit(0); } @@ -1039,7 +1107,9 @@ int main(int argc, char **argv) { case 'h': help(); break; case 't': { // -t xx[:xxxx] -- set file/auxtype. - std::string tmp=optarg; + if (!parse_ft(optarg)) { + errx(EX_USAGE, "Invalid -t argument: %s", optarg); + } break; } diff --git a/optional.h b/optional.h index b38ca32..e3fbd12 100644 --- a/optional.h +++ b/optional.h @@ -57,6 +57,32 @@ public: + template< class U = T > + optional& operator=( U&& value ) { + if (_engaged) { + auto &self = *reinterpret_cast(std::addressof(_data)); + self = std::forward(value); + } + else { + new(std::addressof(_data)) T(std::forward(value)); + _engaged = true; + } + return *this; + } + + optional& operator=(optional &&rhs) { + if (rhs._engaged) this->operator=(std::forward(*rhs)); + else reset(); + return *this; + } + + optional& operator=(const optional &rhs) { + if (rhs._engaged) this->operator=(*rhs); + else reset(); + return *this; + } + + ~optional() { reset(); }