workaround missing charconv. also: print ! for missing symbols, ? for unused symbols.

This commit is contained in:
Kelvin Sherlock 2019-12-10 22:43:11 -05:00
parent 6fb0bf8532
commit 1ac35ec473

View File

@ -10,12 +10,14 @@
/* old version of stdlib have this stuff in utility */ /* old version of stdlib have this stuff in utility */
#if __has_include(<charconv>) #if __has_include(<charconv>)
#define HAVE_CHARCONV
#include <charconv> #include <charconv>
#endif #endif
#include <cstdint> #include <cstdint>
#include <cassert> #include <cassert>
#include <cstdio> #include <cstdio>
#include <cstdlib>
#include <err.h> #include <err.h>
#include <sysexits.h> #include <sysexits.h>
@ -360,29 +362,39 @@ void finalize(void) {
relocations.clear(); relocations.clear();
} }
static void print_symbols2(void) {
for (const auto &e : symbol_table) {
char q = ' ';
if (!e.count) q = '?';
if (!e.defined) q = '!';
fprintf(stdout, "%c %-20s=$%06x\n", q, e.name.c_str(), e.value);
}
}
void print_symbols(void) { void print_symbols(void) {
if (symbol_table.empty()) return; if (symbol_table.empty()) return;
/* alpha */ /* alpha */
fputs("\nSymbol table, alphabetical order:\n", stdout);
std::sort(symbol_table.begin(), symbol_table.end(), std::sort(symbol_table.begin(), symbol_table.end(),
[](const symbol &a, const symbol &b){ [](const symbol &a, const symbol &b){
return a.name < b.name; return a.name < b.name;
}); });
for (const auto &lab : symbol_table) { print_symbols2();
fprintf(stdout, "%-20s: $%06x\n", lab.name.c_str(), lab.value);
} fputs("\nSymbol table, numerical order:\n", stdout);
fputs("\n", stdout);
/* numeric */ /* numeric */
std::sort(symbol_table.begin(), symbol_table.end(), std::sort(symbol_table.begin(), symbol_table.end(),
[](const symbol &a, const symbol &b){ [](const symbol &a, const symbol &b){
return a.value < b.value; return a.value < b.value;
}); });
for (const auto &lab : symbol_table) { print_symbols2();
fprintf(stdout, "%-20s: $%06x\n", lab.name.c_str(), lab.value);
}
} }
@ -393,6 +405,26 @@ void usage(int ex) {
exit(ex); exit(ex);
} }
/* older std libraries lack charconv and std::from_chars */
bool parse_number(const char *begin, const char *end, uint32_t &value, int base = 10) {
#if defined(HAVE_CHARCONV)
auto r = std::from_chars(begin, end, value, base);
if (r.ec != std::errc() || r.ptr != end) return false;
#else
auto xerrno = errno;
errno = 0;
char *ptr = nullptr;
value = stroul(begin, &ptr, base);
std::swap(errno, xerrno);
if (xerrno || ptr != end) {
return false;
}
#endif
return true;
}
static void add_define(std::string str) { static void add_define(std::string str) {
/* -D key[=value] /* -D key[=value]
value = 0x, $, % or base 10 */ value = 0x, $, % or base 10 */
@ -422,9 +454,7 @@ static void add_define(std::string str) {
} }
break; break;
} }
auto end = str.data() + str.length(); if (!parse_number(str.data() + pos, str.data() + str.length(), value, base))
auto r = std::from_chars(str.data() + pos, end, value, base);
if (r.ec != std::errc() || r.ptr != end)
usage(EX_USAGE); usage(EX_USAGE);
str.resize(ix-1); str.resize(ix-1);