|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2021 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // X680x0 SRAM.DAT エディタ
9: //
10:
11: #include "sramedit.h"
12: #include <err.h>
13: #include <fcntl.h>
14: #include <unistd.h>
15: #include <sys/mman.h>
16:
17: [[noreturn]] static void usage();
18: static void calc_width();
19: static void show();
20: static void edit(int ac, char *av[]);
21:
22: static int width;
23: int debug;
24: uint8 *sram;
25:
26: int
27: main(int ac, char *av[])
28: {
29: const char *filename;
30: int c;
31: int fd;
32: int mode;
33: int prot;
34: size_t maplen;
35:
36: calc_width();
37:
38: while ((c = getopt(ac, av, "dh")) != -1) {
39: switch (c) {
40: case 'd':
41: debug++;
42: break;
43: case 'h':
44: default:
45: usage();
46: break;
47: }
48: }
49: ac -= optind;
50: av += optind;
51:
52: if (ac == 0) {
53: usage();
54: }
55:
56: filename = av[0];
57: ac--;
58: av++;
59:
60: if (ac == 0) {
61: // show
62: mode = O_RDONLY;
63: prot = PROT_READ;
64: } else {
65: // edit
66: mode = O_RDWR;
67: prot = PROT_READ | PROT_WRITE;
68: }
69:
70: fd = open(filename, mode);
71: if (fd < 0) {
72: err(1, "%s: open", filename);
73: }
74: maplen = 0x100;
75: int flag = MAP_FILE | MAP_SHARED;
76: void *m = mmap(NULL, maplen, prot, flag, fd, 0);
77: if (m == MAP_FAILED) {
78: err(1, "%s: mmap", filename);
79: }
80: sram = (uint8 *)m;
81:
82: if (ac == 0) {
83: show();
84: } else {
85: edit(ac, av);
86: }
87:
88: munmap(m, maplen);
89: close(fd);
90: return 0;
91: }
92:
93: static void
94: usage()
95: {
96: fprintf(stderr, "usage: %s <SRAM.DAT> .. show all\n",
97: getprogname());
98: fprintf(stderr, " %s <SRAM.DAT> <key=value> .. set\n",
99: getprogname());
100: exit(1);
101: }
102:
103: // グローバル変数 width に代入する
104: static void
105: calc_width()
106: {
107: width = 0;
108:
109: for (const auto& si : sraminfo) {
110: if (si.reader == NULL) {
111: continue;
112: }
113:
114: width = std::max(width, (int)strlen(si.name));
115: }
116: }
117:
118: static void
119: show1(const sraminfo_t& si)
120: {
121: std::string val = si.reader(si);
122: printf("$%02x: %-*s = %s\n", si.offset, width, si.name, val.c_str());
123: }
124:
125: static void
126: show()
127: {
128: for (const auto& si : sraminfo) {
129: if (si.reader) {
130: show1(si);
131: }
132: }
133: }
134:
135: static void
136: edit(int ac, char *av[])
137: {
138: int updated = 0;
139:
140: for (int i = 0; i < ac; i++) {
141: const char *s;
142: const char *e;
143: std::string key;
144: std::string val;
145:
146: s = av[i];
147: e = strchr(s, '=');
148: if (e) {
149: key = std::string(s, (e - s));
150: val = std::string(e + 1);
151: } else {
152: key = std::string(s);
153: }
154:
155: if (key.empty()) {
156: warnx("%s: key must be specified", av[i]);
157: return;
158: }
159:
160: bool found = false;
161: for (const auto& si : sraminfo) {
162: if (strcasecmp(key.c_str(), si.name) != 0) {
163: continue;
164: }
165:
166: if (val.empty()) {
167: // key のみなら、現在値と書式ヘルプを表示
168: printf("current value:\n\t");
169: show1(si);
170:
171: if (si.help != NULL) {
172: const std::string msg0 = si.help(si);
173: // 行頭にタブを追加
174: std::string msg = "\t";
175: for (auto c : msg0) {
176: msg += c;
177: if (c == '\n') {
178: msg += '\t';
179: }
180: }
181: printf("syntax:\n");
182: printf("%s\n", msg.c_str());
183: }
184: return;
185: } else {
186: // key=val なら更新
187: int result = (si.writer)(si, val);
188: if (result == -1) {
189: // エラーは向こうで表示済み
190: return;
191: }
192: show1(si);
193: // エラーでなければ更新件数を返している
194: updated += result;
195: found = true;
196: break;
197: }
198: }
199: if (!found) {
200: warnx("%s: key not found", av[i]);
201: return;
202: }
203: }
204:
205: if (updated == 0) {
206: printf("Nothing was updated\n");
207: } else {
208: printf("%d updated\n", updated);
209: }
210: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.