git.haldean.org ana / 0c94360
lots of work around generated binary data files Haldean Brown 2 years ago
16 changed file(s) with 511 addition(s) and 468 deletion(s). Raw diff Collapse all Expand all
00 build
11 *.o
22 *.d
3 *.gen.cpp
4 imgui.ini
00 cxx_sources = \
11 src/ana.cpp \
2 src/font.gen.cpp \
23 src/node.cpp \
34 src/reallocarray.cpp \
45 src/shaders.cpp \
56 src/ui.cpp \
7 src/viewport.cpp \
68 lib/imgui/imgui.cpp \
79 lib/imgui/imgui_draw.cpp \
810 lib/imgui/imgui_widgets.cpp \
3638 mkdir -p build
3739 $(CXX) $(objects) $(LDFLAGS) -o $@
3840
41 XD = tool/xd.exe
42
43 $(XD): tool/xd-1.4/xd.o
44 $(CXX) $< -o $@
45
46 src/font.gen.cpp: data/InputMonoNarrow-Regular.ttf $(XD)
47 $(XD) -dfont_data $< $@
48
3949 -include $(patsubst %.o,%.d,$(objects))
4050
4151 clean:
42 rm -rf $(objects) build
52 rm -rf $(objects) build tool/xd-1.4/xd.o tool/xd.exe
4353 .PHONY: clean
+0
-7
lib/xd-1.4/.gitignore less more
0 xd.1
1 Makefile
2 index.html
3 images
4 log.txt
5 xd
6 xd.o
+0
-4
lib/xd-1.4/Tupfile less more
0 include_rules
1
2 : xd.c |> cl %f /c /Z7 /MD /Fo%o |> %B.o
3 : xd.o |> link %f /OUT:%o |> xd.exe
+0
-407
lib/xd-1.4/xd.c less more
0 /*
1
2 Extended dump and load utility
3
4 by John Walker
5 http://www.fourmilab.ch/
6
7 This program is in the public domain.
8
9 */
10
11 #define Version \
12 "1.4 -- October 2017"
13
14
15 #include <stdio.h>
16 #include <ctype.h>
17 #include <string.h>
18 #ifdef _WIN32
19 #include <fcntl.h>
20 #include <io.h>
21 #endif
22
23 #define FALSE 0
24 #define TRUE 1
25
26 #define EOS '\0'
27
28 static char addrformat[80] = "%6X";
29 static char scanaddr[80] = "%lx%c";
30
31 static char dataformat1[80] = "%02X";
32 static char scandata[80] = "%x%n%c";
33
34 static int bytesperline = 16, doublechar = FALSE,
35 dflen = 2, loading = FALSE, streaming = FALSE;
36 static unsigned long fileaddr;
37 static unsigned char lineecho[32];
38
39 /* OUTLINE -- Edit a line of binary data into the selected output
40 format. */
41
42 static void outline(out, dat, len)
43 FILE *out;
44 unsigned char *dat;
45 int len;
46 {
47 char oline[132];
48 int i;
49
50 sprintf(oline, addrformat, fileaddr);
51 strcat(oline, ":");
52 for (i = 0; i < len; i++) {
53 char outedit[80];
54
55 sprintf(outedit, dataformat1, dat[i]);
56 strcat(oline, (i == (bytesperline / 2)) ? " " : " ");
57 strcat(oline, outedit);
58 }
59
60 if (doublechar) {
61 char oc[2];
62 int shortfall = ((bytesperline - len) * (dflen + 1)) +
63 (len <= (bytesperline / 2) ? 1 : 0);
64
65 while (shortfall-- > 0) {
66 strcat(oline, " ");
67 }
68 oc[1] = EOS;
69 strcat(oline, " | ");
70 for (i = 0; i < len; i++) {
71 int b = dat[i];
72
73 /* Map non-printing characters to "." according to the
74 definitions for ISO 8859/1 Latin-1. */
75
76 if ((b < ' ') || (b > '~' && b < 160)) {
77 b = '.';
78 }
79
80 /* Many existing systems which support Latin-1 lack
81 a definition for character 160, the non-breaking
82 space. Translate this to a space to avoid
83 confusion. */
84
85 if (b == 160) {
86 b = ' ';
87 }
88 oc[0] = (char) b;
89 strcat(oline, oc);
90 }
91 }
92 strcat(oline, "\n");
93 fputs(oline, out);
94 }
95
96 /* INTERPLINE -- Interpret a line of input. */
97
98 static int interpline(line, lineno, out)
99 char *line;
100 int lineno;
101 FILE *out;
102 {
103 char *cp = line;
104 char c;
105 unsigned long lfaddr;
106 int gfaddr = FALSE;
107
108 /* Scan the line for a possible alternative format information
109 following a vertical bar and delete it. */
110
111 while ((c = *cp++) != EOS) {
112 if (c == '|') {
113 cp[-1] = EOS;
114 break;
115 }
116 }
117
118 /* Scan the line for a file address terminated by a colon. Save
119 the file address. */
120
121 cp = line;
122
123 while ((c = *cp++) != EOS) {
124 if (c == ':') {
125 int sa;
126 char tchar;
127
128 cp[-1] = EOS;
129 sa = sscanf(line, scanaddr, &lfaddr, &tchar);
130 if (sa == 0 || (sa > 1 && tchar != EOS)) {
131 fprintf(stderr,
132 "Bad file address \"%s\" on line %d:\n",
133 line, lineno);
134 return FALSE;
135 }
136 gfaddr = TRUE;
137 cp[-1] = ':';
138 break;
139 }
140 }
141 if (!gfaddr) {
142 cp = line;
143 }
144 if (!streaming) {
145 if (!gfaddr) {
146 fprintf(stderr, "File address missing on line %d:\n", lineno);
147 fprintf(stderr, "%s\n", line);
148 return FALSE;
149 }
150 if (lfaddr != fileaddr) {
151 fprintf(stderr, "File address sequence error on line %d.\n",
152 lineno);
153 fprintf(stderr, " Expected ");
154 fprintf(stderr, addrformat, fileaddr);
155 fprintf(stderr, ", received ");
156 fprintf(stderr, addrformat, lfaddr);
157 fprintf(stderr, ".\n");
158 fprintf(stderr, "%s\n", line);
159 return FALSE;
160 }
161 }
162
163 while ((c = *cp++) != EOS) {
164 if (!isspace(c)) {
165 int scanl, nscan, dvalue;
166 char termchar;
167
168 if (((scanl = sscanf(cp - 1, scandata, &dvalue, &nscan, &termchar)) == 0) ||
169 (dvalue < 0) || (dvalue > 255) ||
170 (scanl == 2 && !isspace(termchar))) {
171 fprintf(stderr, "Improper value, \"%s\" on line %d:\n",
172 cp - 1, lineno);
173 fprintf(stderr, "%s\n", line);
174 fprintf(stderr, "Bytes must be specified as digits separated by white space.\n");
175 return FALSE;
176 }
177 putc((char) dvalue, out);
178 fileaddr++;
179 cp += nscan;
180 }
181 }
182 return TRUE;
183 }
184
185 /* Main program */
186
187 int main(argc, argv)
188 int argc; char *argv[];
189 {
190 int i, b, bp, cdata = FALSE, f = 0;
191 char *cp, *clabel, opt;
192 FILE *in = stdin, *out = stdout;
193
194 for (i = 1; i < argc; i++) {
195 cp = argv[i];
196 if (*cp == '-') {
197 opt = *(++cp);
198 if (islower(opt)) {
199 opt = (char) toupper(opt);
200 }
201 switch (opt) {
202
203 case 'A': /* -Af -- Set address format */
204 opt = cp[1];
205 if (islower(opt)) {
206 opt = (char) toupper(opt);
207 }
208 switch (opt) {
209 case 'D':
210 strcpy(addrformat, "%8d");
211 strcpy(scanaddr, "%ld%c");
212 break;
213
214 case 'H':
215 case 'X':
216 strcpy(addrformat, "%6X");
217 strcpy(scanaddr, "%lx%c");
218 break;
219
220 case 'O':
221 strcpy(addrformat, "%8o");
222 strcpy(scanaddr, "%lo%c");
223 break;
224
225 default:
226 fprintf(stderr,
227 "Invalid address format '%c'. Must be D, H, or O.\n", cp[1]);
228 return 2;
229 }
230 break;
231
232 case 'C':
233 doublechar = TRUE;
234 break;
235
236 case 'D':
237 cdata = TRUE;
238 clabel = cp + 1;
239 break;
240
241 case 'L':
242 loading = TRUE;
243 break;
244
245 case 'N': /* -Nf -- Set numeric dump format */
246 opt = cp[1];
247 if (islower(opt)) {
248 opt = (char) toupper(opt);
249 }
250 switch (opt) {
251 case 'D':
252 strcpy(dataformat1, "%3d");
253 strcpy(scandata, "%d%n%c");
254 break;
255
256 case 'H':
257 case 'X':
258 strcpy(dataformat1, "%02X");
259 strcpy(scandata, "%x%n%c");
260 break;
261
262 case 'O':
263 strcpy(dataformat1, "%03o");
264 strcpy(scandata, "%o%n%c");
265 break;
266
267 default:
268 fprintf(stderr,
269 "Invalid numeric dump format '%c'. Must be D, H, or O.\n", cp[1]);
270 return 2;
271 }
272 break;
273
274 case 'S':
275 streaming = TRUE;
276 break;
277
278 case '?':
279 case 'H':
280 case 'U':
281 fprintf(stderr, "XD -- Extended dump. Call with xd [input [output]]\n");
282 fprintf(stderr, "\n");
283 fprintf(stderr, " Options:\n");
284 fprintf(stderr, " -af Print addresses in f = Decimal, Hex, or Octal\n");
285 fprintf(stderr, " -c Dump as ISO characters\n");
286 fprintf(stderr, " -dlabel Dump as a C data declaration\n");
287 fprintf(stderr, " -l Load file from hex dump\n");
288 fprintf(stderr, " -nf Numeric dump in f = Decimal, Hex, or Octal\n");
289 fprintf(stderr, " -s Stream load (don't check file addresses)\n");
290 fprintf(stderr, " -u Print this message\n");
291 fprintf(stderr, "\nBy John Walker, http://www.fourmilab.ch/\n");
292 fprintf(stderr,"Version %s\n", Version);
293 return 0;
294 }
295 } else {
296 switch (f) {
297 case 0:
298
299 /** Warning! On systems which distinguish text mode and
300 binary I/O (MS-DOS, Macintosh, etc.) the modes in these
301 open statements will have to be made conditional based
302 upon whether an encode or decode is being done, which
303 will have to be specified earlier. But it's worse: if
304 input or output is from standard input or output, the
305 mode will have to be changed on the fly, which is
306 generally system and compiler dependent. 'Twasn't me
307 who couldn't conform to Unix CR/LF convention, so
308 don't ask me to write the code to work around
309 Apple and Microsoft's incompatible standards.
310
311 This file contains code, conditional on _WIN32, which
312 sets binary mode using the method prescribed by
313 Microsoft Visual C 1.52 ("Monkey C"); this may
314 require modification if you're using a different
315 compiler or release of Monkey C. */
316
317 if ((in = fopen(cp, loading ? "r" : "rb")) == NULL) {
318 fprintf(stderr, "Cannot open input file %s\n", cp);
319 return 2;
320 }
321 f++;
322 break;
323
324 case 1:
325 if ((out = fopen(cp, loading ? "wb" : "w")) == NULL) {
326 fprintf(stderr, "Cannot open output file %s\n", cp);
327 return 2;
328 }
329 f++;
330 break;
331
332 default:
333 fprintf(stderr, "Too many file names specified.\n");
334 }
335 }
336 }
337
338 #ifdef _WIN32
339
340 /* If input is from standard input and we aren't loading
341 from a dump file, set the input file mode to binary. */
342
343 if ((in == stdin) && (!loading)) {
344 _setmode(_fileno(in), _O_BINARY);
345 }
346
347 /* If output is to standard output and we're loading a
348 binary file from a dump, set the output file mode to
349 binary. */
350
351 if ((out == stdout) && (loading)) {
352 _setmode(_fileno(out), _O_BINARY);
353 }
354 #endif
355
356 bp = 0;
357 fileaddr = 0;
358
359 if (loading) {
360 char in_line[256];
361 int lineno = 0;
362
363 while (fgets(in_line, (sizeof in_line) - 2, in)) {
364 lineno++;
365 if (!interpline(in_line, lineno, out)) {
366 fclose(out);
367 return 2;
368 }
369 }
370 } else {
371 if (cdata) {
372 char cout[80];
373
374 fprintf(out, "unsigned char %s[] = {\n",
375 clabel[0] == EOS ? "xd_data" : clabel);
376 strcpy(cout, " ");
377
378 while ((b = getc(in)) != EOF) {
379 if (strlen(cout) > 72) {
380 fprintf(out, "%s\n", cout);
381 strcpy(cout, " ");
382 }
383 sprintf(cout + strlen(cout), "%d,", b);
384 }
385 if (strlen(cout) > 4) {
386 cout[strlen(cout) - 1] = EOS; /* Strip trailing comma */
387 fprintf(out, "%s\n", cout);
388 }
389 fprintf(out, "};\n");
390 } else {
391 while ((b = getc(in)) != EOF) {
392 if (bp >= bytesperline) {
393 outline(out, lineecho, bp);
394 bp = 0;
395 fileaddr += bytesperline;
396 }
397 lineecho[bp++] = (char) b;
398 }
399
400 if (bp > 0) {
401 outline(out, lineecho, bp);
402 }
403 }
404 }
405 return 0;
406 }
1111 #include "node.hpp"
1212 #include "shaders.hpp"
1313 #include "ui.hpp"
14 #include "viewport.hpp"
1415
1516 void error_callback(int error, const char* description) {
1617 std::cerr << "[E] glfw error: " << description << std::endl;
5152 nodes.nodes.push_back(ana::node{glm::vec2(0, 0), glm::vec2(0.1, 0.2), "hello"});
5253 nodes.nodes.push_back(ana::node{glm::vec2(-0.5, -0.5), glm::vec2(0.2, 0.2), "hello"});
5354
54 ana::ui ui;
55 ana::viewport viewport;
5556
5657 ImGui::CreateContext();
57 //ImGuiIO &io = ImGui::GetIO();
58 ana::ui::init_imgui();
59
5860 ImGui_ImplGlfw_InitForOpenGL(window, true);
5961 ImGui_ImplOpenGL3_Init("#version 410");
6062
7981 case SDL_WINDOWEVENT:
8082 if (ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
8183 glViewport(0, 0, ev.window.data1, ev.window.data2);
82 ui.set_aspect(ev.window.data1, ev.window.data2);
84 viewport.set_aspect(ev.window.data1, ev.window.data2);
8385 }
8486 break;
8587
8688 case SDL_MOUSEWHEEL:
8789 if (!io.WantCaptureMouse && ev.wheel.y != 0) {
88 ui.view_step(ev.wheel.y);
90 viewport.view_step(ev.wheel.y);
8991 }
9092 break;
9193
9294 case SDL_MOUSEMOTION:
9395 if (!io.WantCaptureMouse && ev.motion.state & SDL_BUTTON_MMASK) {
94 ui.translate(-ev.motion.xrel, ev.motion.yrel);
96 viewport.translate(-ev.motion.xrel, ev.motion.yrel);
9597 }
9698 break;
9799 }
108110 glClearColor(0.15f, 0.12f, 0.1f, 1.0f);
109111 glClear(GL_COLOR_BUFFER_BIT);
110112
111 ana::shaders::draw(ui, nodes);
113 ana::shaders::draw(viewport, nodes);
112114 ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
113115
114116 glfwMakeContextCurrent(window);
0 #include <stddef.h>
1
2 extern unsigned char *font_data;
3 extern const size_t font_data_len;
161161 return true;
162162 }
163163
164 void draw(const ana::ui &ui, const ana::nodeset &nodes) {
164 void draw(const ana::viewport &viewport, const ana::nodeset &nodes) {
165165 static GLfloat *node_data = nullptr;
166166 static size_t node_data_size = 0;
167167
185185 glBufferData(GL_ARRAY_BUFFER, elems * sizeof(GLfloat), node_data, GL_DYNAMIC_DRAW); INSERT_GL_ERROR_CHECK;
186186
187187 glm::mat4 m = glm::ortho(
188 ui.center.x - ui.view, ui.center.x + ui.view,
189 ui.center.y - ui.view * ui.aspect, ui.center.y + ui.view * ui.aspect,
188 viewport.center.x - viewport.view, viewport.center.x + viewport.view,
189 viewport.center.y - viewport.view * viewport.aspect, viewport.center.y + viewport.view * viewport.aspect,
190190 -1.f, 1.f);
191191 glUniformMatrix4fv(node_viewport_attr, 1, GL_FALSE, glm::value_ptr(m));
192192
11
22 #include <GL/glew.h>
33 #include "node.hpp"
4 #include "ui.hpp"
4 #include "viewport.hpp"
55
66 namespace ana {
77 namespace shaders {
99 bool init(void);
1010 void destroy(void);
1111 void set_aspect(int w, int h);
12 void draw(const ana::ui &ui, const ana::nodeset &nodes);
12 void draw(const ana::viewport &ui, const ana::nodeset &nodes);
1313 }
1414 }
0 #include "font.hpp"
01 #include "ui.hpp"
2 #include "imgui.h"
13
24 namespace ana {
5 namespace ui {
36
4 void ui::set_aspect(int w, int h) {
5 width = w;
6 height = h;
7 aspect = (float) h / w;
8 }
9
10 void ui::view_step(int dir) {
11 if (dir > 0) {
12 view *= 1.2f;
13 if (view > 20) {
14 view = 20;
15 }
16 } else if (dir < 0) {
17 view /= 1.2f;
18 if (view < 0.05f) {
19 view = 0.05f;
20 }
21 }
22 }
23
24 void ui::translate(int xpixels, int ypixels) {
25 float x = 2.f * view * xpixels / width;
26 float y = 2.f * view * aspect * ypixels / height;
27 center.x += x;
28 center.y += y;
7 void init_imgui() {
8 ImGuiIO &io = ImGui::GetIO();
9 io.Fonts->AddFontFromMemoryTTF(font_data, font_data_len, 16);
2910 }
3011
3112 }
13 }
00 #pragma once
11
2 #include <glm/glm.hpp>
3
42 namespace ana {
5 struct ui {
6 float aspect = 1.f;
7 float view = 1.f;
8 int width = 1;
9 int height = 1;
10 glm::vec2 center{0.f, 0.f};
11
12 void set_aspect(int w, int h);
13 void view_step(int dir);
14 void translate(int xpixels, int ypixels);
15 };
3 namespace ui {
4 void init_imgui();
165 }
6 }
0 #include "viewport.hpp"
1
2 namespace ana {
3
4 void viewport::set_aspect(int w, int h) {
5 width = w;
6 height = h;
7 aspect = (float) h / w;
8 }
9
10 void viewport::view_step(int dir) {
11 if (dir > 0) {
12 view *= 1.2f;
13 if (view > 20) {
14 view = 20;
15 }
16 } else if (dir < 0) {
17 view /= 1.2f;
18 if (view < 0.05f) {
19 view = 0.05f;
20 }
21 }
22 }
23
24 void viewport::translate(int xpixels, int ypixels) {
25 float x = 2.f * view * xpixels / width;
26 float y = 2.f * view * aspect * ypixels / height;
27 center.x += x;
28 center.y += y;
29 }
30
31 }
0 #pragma once
1
2 #include <glm/glm.hpp>
3
4 namespace ana {
5 struct viewport {
6 float aspect = 1.f;
7 float view = 1.f;
8 int width = 1;
9 int height = 1;
10 glm::vec2 center{0.f, 0.f};
11
12 void set_aspect(int w, int h);
13 void view_step(int dir);
14 void translate(int xpixels, int ypixels);
15 };
16 }
0 xd.1
1 Makefile
2 index.html
3 images
4 log.txt
5 xd
6 xd.o
0 include_rules
1
2 : xd.c |> cl %f /c /Z7 /MD /Fo%o |> %B.o
3 : xd.o |> link %f /OUT:%o |> xd.exe
0 /*
1
2 Extended dump and load utility
3
4 by John Walker
5 http://www.fourmilab.ch/
6
7 This program is in the public domain.
8
9 */
10
11 #define Version \
12 "1.4 -- October 2017"
13
14
15 #include <stdio.h>
16 #include <ctype.h>
17 #include <string.h>
18 #ifdef _WIN32
19 #include <fcntl.h>
20 #include <io.h>
21 #endif
22
23 #define FALSE 0
24 #define TRUE 1
25
26 #define EOS '\0'
27
28 static char addrformat[80] = "%6X";
29 static char scanaddr[80] = "%lx%c";
30
31 static char dataformat1[80] = "%02X";
32 static char scandata[80] = "%x%n%c";
33
34 static int bytesperline = 16, doublechar = FALSE,
35 dflen = 2, loading = FALSE, streaming = FALSE;
36 static unsigned long fileaddr;
37 static unsigned char lineecho[32];
38
39 /* OUTLINE -- Edit a line of binary data into the selected output
40 format. */
41
42 static void outline(out, dat, len)
43 FILE *out;
44 unsigned char *dat;
45 int len;
46 {
47 char oline[132];
48 int i;
49
50 sprintf(oline, addrformat, fileaddr);
51 strcat(oline, ":");
52 for (i = 0; i < len; i++) {
53 char outedit[80];
54
55 sprintf(outedit, dataformat1, dat[i]);
56 strcat(oline, (i == (bytesperline / 2)) ? " " : " ");
57 strcat(oline, outedit);
58 }
59
60 if (doublechar) {
61 char oc[2];
62 int shortfall = ((bytesperline - len) * (dflen + 1)) +
63 (len <= (bytesperline / 2) ? 1 : 0);
64
65 while (shortfall-- > 0) {
66 strcat(oline, " ");
67 }
68 oc[1] = EOS;
69 strcat(oline, " | ");
70 for (i = 0; i < len; i++) {
71 int b = dat[i];
72
73 /* Map non-printing characters to "." according to the
74 definitions for ISO 8859/1 Latin-1. */
75
76 if ((b < ' ') || (b > '~' && b < 160)) {
77 b = '.';
78 }
79
80 /* Many existing systems which support Latin-1 lack
81 a definition for character 160, the non-breaking
82 space. Translate this to a space to avoid
83 confusion. */
84
85 if (b == 160) {
86 b = ' ';
87 }
88 oc[0] = (char) b;
89 strcat(oline, oc);
90 }
91 }
92 strcat(oline, "\n");
93 fputs(oline, out);
94 }
95
96 /* INTERPLINE -- Interpret a line of input. */
97
98 static int interpline(line, lineno, out)
99 char *line;
100 int lineno;
101 FILE *out;
102 {
103 char *cp = line;
104 char c;
105 unsigned long lfaddr;
106 int gfaddr = FALSE;
107
108 /* Scan the line for a possible alternative format information
109 following a vertical bar and delete it. */
110
111 while ((c = *cp++) != EOS) {
112 if (c == '|') {
113 cp[-1] = EOS;
114 break;
115 }
116 }
117
118 /* Scan the line for a file address terminated by a colon. Save
119 the file address. */
120
121 cp = line;
122
123 while ((c = *cp++) != EOS) {
124 if (c == ':') {
125 int sa;
126 char tchar;
127
128 cp[-1] = EOS;
129 sa = sscanf(line, scanaddr, &lfaddr, &tchar);
130 if (sa == 0 || (sa > 1 && tchar != EOS)) {
131 fprintf(stderr,
132 "Bad file address \"%s\" on line %d:\n",
133 line, lineno);
134 return FALSE;
135 }
136 gfaddr = TRUE;
137 cp[-1] = ':';
138 break;
139 }
140 }
141 if (!gfaddr) {
142 cp = line;
143 }
144 if (!streaming) {
145 if (!gfaddr) {
146 fprintf(stderr, "File address missing on line %d:\n", lineno);
147 fprintf(stderr, "%s\n", line);
148 return FALSE;
149 }
150 if (lfaddr != fileaddr) {
151 fprintf(stderr, "File address sequence error on line %d.\n",
152 lineno);
153 fprintf(stderr, " Expected ");
154 fprintf(stderr, addrformat, fileaddr);
155 fprintf(stderr, ", received ");
156 fprintf(stderr, addrformat, lfaddr);
157 fprintf(stderr, ".\n");
158 fprintf(stderr, "%s\n", line);
159 return FALSE;
160 }
161 }
162
163 while ((c = *cp++) != EOS) {
164 if (!isspace(c)) {
165 int scanl, nscan, dvalue;
166 char termchar;
167
168 if (((scanl = sscanf(cp - 1, scandata, &dvalue, &nscan, &termchar)) == 0) ||
169 (dvalue < 0) || (dvalue > 255) ||
170 (scanl == 2 && !isspace(termchar))) {
171 fprintf(stderr, "Improper value, \"%s\" on line %d:\n",
172 cp - 1, lineno);
173 fprintf(stderr, "%s\n", line);
174 fprintf(stderr, "Bytes must be specified as digits separated by white space.\n");
175 return FALSE;
176 }
177 putc((char) dvalue, out);
178 fileaddr++;
179 cp += nscan;
180 }
181 }
182 return TRUE;
183 }
184
185 /* Main program */
186
187 int main(argc, argv)
188 int argc; char *argv[];
189 {
190 int i, b, bp, cdata = FALSE, f = 0;
191 char *cp, *clabel, opt;
192 FILE *in = stdin, *out = stdout;
193
194 for (i = 1; i < argc; i++) {
195 cp = argv[i];
196 if (*cp == '-') {
197 opt = *(++cp);
198 if (islower(opt)) {
199 opt = (char) toupper(opt);
200 }
201 switch (opt) {
202
203 case 'A': /* -Af -- Set address format */
204 opt = cp[1];
205 if (islower(opt)) {
206 opt = (char) toupper(opt);
207 }
208 switch (opt) {
209 case 'D':
210 strcpy(addrformat, "%8d");
211 strcpy(scanaddr, "%ld%c");
212 break;
213
214 case 'H':
215 case 'X':
216 strcpy(addrformat, "%6X");
217 strcpy(scanaddr, "%lx%c");
218 break;
219
220 case 'O':
221 strcpy(addrformat, "%8o");
222 strcpy(scanaddr, "%lo%c");
223 break;
224
225 default:
226 fprintf(stderr,
227 "Invalid address format '%c'. Must be D, H, or O.\n", cp[1]);
228 return 2;
229 }
230 break;
231
232 case 'C':
233 doublechar = TRUE;
234 break;
235
236 case 'D':
237 cdata = TRUE;
238 clabel = cp + 1;
239 break;
240
241 case 'L':
242 loading = TRUE;
243 break;
244
245 case 'N': /* -Nf -- Set numeric dump format */
246 opt = cp[1];
247 if (islower(opt)) {
248 opt = (char) toupper(opt);
249 }
250 switch (opt) {
251 case 'D':
252 strcpy(dataformat1, "%3d");
253 strcpy(scandata, "%d%n%c");
254 break;
255
256 case 'H':
257 case 'X':
258 strcpy(dataformat1, "%02X");
259 strcpy(scandata, "%x%n%c");
260 break;
261
262 case 'O':
263 strcpy(dataformat1, "%03o");
264 strcpy(scandata, "%o%n%c");
265 break;
266
267 default:
268 fprintf(stderr,
269 "Invalid numeric dump format '%c'. Must be D, H, or O.\n", cp[1]);
270 return 2;
271 }
272 break;
273
274 case 'S':
275 streaming = TRUE;
276 break;
277
278 case '?':
279 case 'H':
280 case 'U':
281 fprintf(stderr, "XD -- Extended dump. Call with xd [input [output]]\n");
282 fprintf(stderr, "\n");
283 fprintf(stderr, " Options:\n");
284 fprintf(stderr, " -af Print addresses in f = Decimal, Hex, or Octal\n");
285 fprintf(stderr, " -c Dump as ISO characters\n");
286 fprintf(stderr, " -dlabel Dump as a C data declaration\n");
287 fprintf(stderr, " -l Load file from hex dump\n");
288 fprintf(stderr, " -nf Numeric dump in f = Decimal, Hex, or Octal\n");
289 fprintf(stderr, " -s Stream load (don't check file addresses)\n");
290 fprintf(stderr, " -u Print this message\n");
291 fprintf(stderr, "\nBy John Walker, http://www.fourmilab.ch/\n");
292 fprintf(stderr,"Version %s\n", Version);
293 return 0;
294 }
295 } else {
296 switch (f) {
297 case 0:
298
299 /** Warning! On systems which distinguish text mode and
300 binary I/O (MS-DOS, Macintosh, etc.) the modes in these
301 open statements will have to be made conditional based
302 upon whether an encode or decode is being done, which
303 will have to be specified earlier. But it's worse: if
304 input or output is from standard input or output, the
305 mode will have to be changed on the fly, which is
306 generally system and compiler dependent. 'Twasn't me
307 who couldn't conform to Unix CR/LF convention, so
308 don't ask me to write the code to work around
309 Apple and Microsoft's incompatible standards.
310
311 This file contains code, conditional on _WIN32, which
312 sets binary mode using the method prescribed by
313 Microsoft Visual C 1.52 ("Monkey C"); this may
314 require modification if you're using a different
315 compiler or release of Monkey C. */
316
317 if ((in = fopen(cp, loading ? "r" : "rb")) == NULL) {
318 fprintf(stderr, "Cannot open input file %s\n", cp);
319 return 2;
320 }
321 f++;
322 break;
323
324 case 1:
325 if ((out = fopen(cp, loading ? "wb" : "w")) == NULL) {
326 fprintf(stderr, "Cannot open output file %s\n", cp);
327 return 2;
328 }
329 f++;
330 break;
331
332 default:
333 fprintf(stderr, "Too many file names specified.\n");
334 }
335 }
336 }
337
338 #ifdef _WIN32
339
340 /* If input is from standard input and we aren't loading
341 from a dump file, set the input file mode to binary. */
342
343 if ((in == stdin) && (!loading)) {
344 _setmode(_fileno(in), _O_BINARY);
345 }
346
347 /* If output is to standard output and we're loading a
348 binary file from a dump, set the output file mode to
349 binary. */
350
351 if ((out == stdout) && (loading)) {
352 _setmode(_fileno(out), _O_BINARY);
353 }
354 #endif
355
356 bp = 0;
357 fileaddr = 0;
358
359 if (loading) {
360 char in_line[256];
361 int lineno = 0;
362
363 while (fgets(in_line, (sizeof in_line) - 2, in)) {
364 lineno++;
365 if (!interpline(in_line, lineno, out)) {
366 fclose(out);
367 return 2;
368 }
369 }
370 } else {
371 if (cdata) {
372 char cout[80];
373 unsigned long len = 0;
374
375 fprintf(out, "#include <stddef.h>\n");
376 fprintf(out, "unsigned char %s[] = {\n",
377 clabel[0] == EOS ? "xd_data" : clabel);
378 strcpy(cout, " ");
379
380 while ((b = getc(in)) != EOF) {
381 len++;
382 if (strlen(cout) > 72) {
383 fprintf(out, "%s\n", cout);
384 strcpy(cout, " ");
385 }
386 sprintf(cout + strlen(cout), "%d,", b);
387 }
388 if (strlen(cout) > 4) {
389 cout[strlen(cout) - 1] = EOS; /* Strip trailing comma */
390 fprintf(out, "%s\n", cout);
391 }
392 fprintf(out, "};\n");
393 fprintf(out, "size_t %s_len = %ul;\n", clabel[0] == EOS ? "xd_data" : clabel, len);
394 } else {
395 while ((b = getc(in)) != EOF) {
396 if (bp >= bytesperline) {
397 outline(out, lineecho, bp);
398 bp = 0;
399 fileaddr += bytesperline;
400 }
401 lineecho[bp++] = (char) b;
402 }
403
404 if (bp > 0) {
405 outline(out, lineecho, bp);
406 }
407 }
408 }
409 return 0;
410 }