it compiles...

This commit is contained in:
Kelvin Sherlock 2019-12-09 19:45:45 -05:00
parent a4dfcec1f1
commit 7048c59813
3 changed files with 98 additions and 12 deletions

View File

@ -15,7 +15,7 @@ clean:
o: o:
mkdir $< mkdir $<
rel-link: o/link.o o/mapped_file.o o/omf.o afp/libafp.a rel-link: o/link.o o/mapped_file.o o/omf.o o/set_file_type.o afp/libafp.a
$(LINK.o) $^ $(LDLIBS) -o $@ $(LINK.o) $^ $(LDLIBS) -o $@
o/mapped_file.o : mapped_file.cpp mapped_file.h unique_resource.h o/mapped_file.o : mapped_file.cpp mapped_file.h unique_resource.h

View File

@ -11,14 +11,20 @@
#include <cstdio> #include <cstdio>
#include <err.h> #include <err.h>
#include <sysexits.h>
#include <unistd.h>
#include <afp/finder_info.h> #include <afp/finder_info.h>
#include "mapped_file.h"
#include "omf.h" #include "omf.h"
#include "rel.h" #include "rel.h"
void save_omf(const std::string &path, std::vector<omf::segment> &segments, bool compress, bool expressload); void save_omf(const std::string &path, std::vector<omf::segment> &segments, bool compress, bool expressload);
int set_file_type(const std::string &path, uint16_t file_type, uint32_t aux_type, std::error_code &ec);
void set_file_type(const std::string &path, uint16_t file_type, uint32_t aux_type);
/* since span isn't standard yet */ /* since span isn't standard yet */
typedef std::basic_string_view<uint8_t> byte_view; typedef std::basic_string_view<uint8_t> byte_view;
@ -35,12 +41,15 @@ struct symbol {
bool defined = false; bool defined = false;
}; };
std::unordered_map<std::string, unsigned> symbol_map;
std::vector<symbol> symbol_table;
struct pending_reloc : public omf::reloc { struct pending_reloc : public omf::reloc {
unsigned id = 0; unsigned id = 0;
}; };
std::unordered_map<std::string, unsigned> symbol_map; std::vector<pending_reloc> relocations;
std::vector<symbol> symbol_table;
std::vector<omf::segment> segments; std::vector<omf::segment> segments;
@ -125,7 +134,7 @@ void process_labels(byte_view &data, cookie &cookie) {
void process_reloc(byte_view &data, cookie &cookie) { void process_reloc(byte_view &data, cookie &cookie) {
auto &seg_data = segments.back().data; auto &seg = segments.back();
for(;;) { for(;;) {
assert(data.size()); assert(data.size());
@ -192,9 +201,9 @@ void process_reloc(byte_view &data, cookie &cookie) {
external = flag & 0x10; external = flag & 0x10;
switch(size) { switch(size) {
case 3: value |= seg_data[offset+2] << 16; case 3: value |= seg.data[offset+2] << 16;
case 2: value |= seg_data[offset+1] << 8; case 2: value |= seg.data[offset+1] << 8;
case 1: value |= seg_data[offset+0]; case 1: value |= seg.data[offset+0];
} }
@ -215,6 +224,7 @@ void process_reloc(byte_view &data, cookie &cookie) {
r.value = value; r.value = value;
r.shift = shift; r.shift = shift;
symbol_table[r.id].count += 1;
relocations.emplace_back(r); relocations.emplace_back(r);
} else { } else {
uint32_t value = 0; uint32_t value = 0;
@ -253,7 +263,7 @@ void process_unit(const std::string &path) {
std::error_code ec; std::error_code ec;
mapped_file mf(path, mapped_file::readonly, ec); mapped_file mf(path, mapped_file::readonly, ec);
if (ec) { if (ec) {
errx(1, "Unable to open %s: %s" path.c_str(), ec.message().c_str()); errx(1, "Unable to open %s: %s", path.c_str(), ec.message().c_str());
} }
@ -277,7 +287,7 @@ void process_unit(const std::string &path) {
omf::segment &seg = segments.back(); omf::segment &seg = segments.back();
seg.data.append(mf.data(), mf.data() + offset); seg.data.insert(seg.data.end(), mf.data(), mf.data() + offset);
byte_view data(mf.data() + offset, mf.size() - offset); byte_view data(mf.data() + offset, mf.size() - offset);
@ -304,10 +314,12 @@ void process_unit(const std::string &path) {
void finalize(void) { void finalize(void) {
for (auto &r in relocations) { /* this needs to be updated if supporting multiple segments */
assert(r.id <= symbol_map.length()); auto &seg = segments.back();
const auto &label = symbol_map[rr.id];
for (auto &r : relocations) {
assert(r.id <= symbol_map.size());
const auto &label = symbol_table[r.id];
r.value = label.value; r.value = label.value;
seg.relocs.emplace_back(r); seg.relocs.emplace_back(r);
} }
@ -338,3 +350,52 @@ void print_symbols(void) {
fprintf(stdout, "%-20s: $%06x\n", lab.name.c_str(), lab.value); fprintf(stdout, "%-20s: $%06x\n", lab.name.c_str(), lab.value);
} }
} }
void usage(int ex) {
fputs("merlin-link [-o outfile] infile...\n", stderr);
exit(ex);
}
int main(int argc, char **argv) {
int c;
std::string gs_out = "gs.out";
while ((c = getopt(argc, argv, "o:")) != -1) {
switch(c) {
case 'o':
gs_out = optarg;
break;
case ':':
case '?':
default:
usage(EX_USAGE);
break;
}
}
argv += optind;
argc -= optind;
if (!argc) usage(EX_USAGE);
segments.emplace_back();
for (int i = 0; i < argc; ++i) {
char *path = argv[i];
try {
process_unit(path);
} catch (std::exception &ex) {
errx(EX_DATAERR, "%s: %s", path, ex.what());
}
}
try {
save_omf(gs_out, segments, true, true);
set_file_type(gs_out, 0xb3, 0x0000);
exit(0);
} catch (std::exception &ex) {
errx(EX_OSERR, "%s: %s", gs_out.c_str(), ex.what());
}
}

25
set_file_type.cpp Normal file
View File

@ -0,0 +1,25 @@
#include <string>
#include <stdint.h>
#include <system_error>
#include <afp/finder_info.h>
int set_file_type(const std::string &path, uint16_t file_type, uint32_t aux_type, std::error_code &ec) {
afp::finder_info fi;
if (!fi.open(path, afp::finder_info::read_write, ec))
return -1;
fi.set_prodos_file_type(file_type, aux_type);
if (!fi.write(ec))
return -1;
return 0;
}
void set_file_type(const std::string &path, uint16_t file_type, uint32_t aux_type) {
std::error_code ec;
if (set_file_type(path, file_type, aux_type, ec) < 0)
throw std::system_error(ec);
}