|
|
nono 0.2.0
//
// nono
// Copyright (C) 2021 nono project
// Licensed under nono-license.txt
//
//
// X680x0 SRAM.DAT エディタ
//
#include "sramedit.h"
#include <err.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
[[noreturn]] static void usage();
static void calc_width();
static void show();
static void edit(int ac, char *av[]);
static int width;
int debug;
uint8 *sram;
int
main(int ac, char *av[])
{
const char *filename;
int c;
int fd;
int mode;
int prot;
size_t maplen;
calc_width();
while ((c = getopt(ac, av, "dh")) != -1) {
switch (c) {
case 'd':
debug++;
break;
case 'h':
default:
usage();
break;
}
}
ac -= optind;
av += optind;
if (ac == 0) {
usage();
}
filename = av[0];
ac--;
av++;
if (ac == 0) {
// show
mode = O_RDONLY;
prot = PROT_READ;
} else {
// edit
mode = O_RDWR;
prot = PROT_READ | PROT_WRITE;
}
fd = open(filename, mode);
if (fd < 0) {
err(1, "%s: open", filename);
}
maplen = 0x100;
int flag = MAP_FILE | MAP_SHARED;
void *m = mmap(NULL, maplen, prot, flag, fd, 0);
if (m == MAP_FAILED) {
err(1, "%s: mmap", filename);
}
sram = (uint8 *)m;
if (ac == 0) {
show();
} else {
edit(ac, av);
}
munmap(m, maplen);
close(fd);
return 0;
}
static void
usage()
{
fprintf(stderr, "usage: %s <SRAM.DAT> .. show all\n",
getprogname());
fprintf(stderr, " %s <SRAM.DAT> <key=value> .. set\n",
getprogname());
exit(1);
}
// グローバル変数 width に代入する
static void
calc_width()
{
width = 0;
for (const auto& si : sraminfo) {
if (si.reader == NULL) {
continue;
}
width = std::max(width, (int)strlen(si.name));
}
}
static void
show1(const sraminfo_t& si)
{
std::string val = si.reader(si);
printf("$%02x: %-*s = %s\n", si.offset, width, si.name, val.c_str());
}
static void
show()
{
for (const auto& si : sraminfo) {
if (si.reader) {
show1(si);
}
}
}
static void
edit(int ac, char *av[])
{
int updated = 0;
for (int i = 0; i < ac; i++) {
const char *s;
const char *e;
std::string key;
std::string val;
s = av[i];
e = strchr(s, '=');
if (e) {
key = std::string(s, (e - s));
val = std::string(e + 1);
} else {
key = std::string(s);
}
if (key.empty()) {
warnx("%s: key must be specified", av[i]);
return;
}
bool found = false;
for (const auto& si : sraminfo) {
if (strcasecmp(key.c_str(), si.name) != 0) {
continue;
}
if (val.empty()) {
// key のみなら、現在値と書式ヘルプを表示
printf("current value:\n\t");
show1(si);
if (si.help != NULL) {
const std::string msg0 = si.help(si);
// 行頭にタブを追加
std::string msg = "\t";
for (auto c : msg0) {
msg += c;
if (c == '\n') {
msg += '\t';
}
}
printf("syntax:\n");
printf("%s\n", msg.c_str());
}
return;
} else {
// key=val なら更新
int result = (si.writer)(si, val);
if (result == -1) {
// エラーは向こうで表示済み
return;
}
show1(si);
// エラーでなければ更新件数を返している
updated += result;
found = true;
break;
}
}
if (!found) {
warnx("%s: key not found", av[i]);
return;
}
}
if (updated == 0) {
printf("Nothing was updated\n");
} else {
printf("%d updated\n", updated);
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.