Skip to content

Commit 62fef4f

Browse files
committed
Tool to copy, remove, insert tape records, files, marks.
Usage: cut36 [-W<input word format>] [-O<output word format>] [-7] [-9] [input] [commands...] Read from an input file (or stdin), and write to stdout. Commands can be put on the command line, or typed to stdin. Commands take a numeric argument which defaults to 1. sw - skip word in input. sr - skip record in input. sf - skip file in input. sa - skip all input. cw - copy word from input to output. cr - copy record from input to output. cf - copy file from input to output. ca - copy all input to output. r - insert record boundary. m - insert tape mark.
1 parent c676d01 commit 62fef4f

File tree

4 files changed

+362
-1
lines changed

4 files changed

+362
-1
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
*~
22
*.o
33
cat36
4+
cut36
45
ipak
56
itsarc
67
dis10

Makefile

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ WORDS = aa-word.o alto-word.o bin-word.o cadr-word.o core-word.o \
1313
OBJS = pdp10-opc.o info.o dis.o symbols.o \
1414
timing.o timing_ka10.o timing_ki10.o memory.o weenix.o
1515

16-
UTILS = cat36 itsarc magdmp magfrm dskdmp dump \
16+
UTILS = cat36 cut36 itsarc magdmp magfrm dskdmp dump \
1717
macdmp macro-tapes tape-dir harscntopbm palx cross \
1818
ipak kldcp klfedr scrmbl unscr tvpic tito dart od10 \
1919
constantinople dumper mini-dumper linum tendmp
@@ -41,6 +41,9 @@ libwords.a: word.o $(WORDS)
4141
cat36: cat36.o libwords.a
4242
$(CC) $(CFLAGS) $^ -o $@
4343

44+
cut36: cut36.o libwords.a
45+
$(CC) $(CFLAGS) $^ -o $@
46+
4447
dump: dump.c $(OBJS) libfiles.a libwords.a
4548
$(CC) $(CFLAGS) $^ -o $@
4649

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
- Scramble or unscramble an encrypted file.
1515
- Make a picture file suitable for displaying on a Knight TV.
1616
- Write out a core image in some of the supported executable formats.
17+
- Copy, remove, insert tape records, files, marks.
1718
- Analyze a CONSTANTS area.
1819

1920
A Linux FUSE implementation of the networking filesystem protocol MLDEV

cut36.c

+356
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
/* Copyright (C) 2022 Lars Brinkhoff <lars@nocrew.org>
2+
3+
This program is free software: you can redistribute it and/or modify
4+
it under the terms of the GNU General Public License as published by
5+
the Free Software Foundation, either version 2 of the License, or
6+
(at your option) any later version.
7+
8+
This program is distributed in the hope that it will be useful,
9+
but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
GNU General Public License for more details.
12+
13+
You should have received a copy of the GNU General Public License
14+
along with this program. If not, see <http://www.gnu.org/licenses/>. */
15+
16+
#include <errno.h>
17+
#include <stdio.h>
18+
#include <stdlib.h>
19+
#include <string.h>
20+
#include <unistd.h>
21+
22+
#include "dis.h"
23+
24+
static word_t data;
25+
static int words = 0;
26+
static int records = 0;
27+
static int files = 0;
28+
static int marks = 0;
29+
30+
static void
31+
count (word_t word)
32+
{
33+
if (word == -1)
34+
return;
35+
36+
if (word & (START_TAPE | START_FILE | START_RECORD))
37+
fprintf (stderr, "Files: %d, Records: %d, Words: %d\n",
38+
files, records, words);
39+
words++;
40+
if (word & (START_FILE | START_RECORD))
41+
records++;
42+
if (word & START_FILE)
43+
files++;
44+
}
45+
46+
static void
47+
output (word_t word)
48+
{
49+
#if 0
50+
if (word & START_TAPE)
51+
fprintf (stderr, "Start of tape\n");
52+
else if (word & START_FILE)
53+
fprintf (stderr, "Start of file\n");
54+
else if (word & START_RECORD)
55+
fprintf (stderr, "Start of record\n");
56+
fprintf (stderr, "Output: %012llo\n", word);
57+
#endif
58+
if (word == -1)
59+
return;
60+
write_word (stdout, word);
61+
marks = 0;
62+
}
63+
64+
static void end (void)
65+
{
66+
if (data != -1)
67+
{
68+
count (data);
69+
output (data);
70+
}
71+
count (START_TAPE);
72+
flush_word (stdout);
73+
exit (0);
74+
}
75+
76+
static void skip_word (FILE *f, word_t n)
77+
{
78+
int i;
79+
80+
for (i = 0; i < n; i++)
81+
{
82+
count (data);
83+
data = get_word (f);
84+
if (data == -1)
85+
end ();
86+
}
87+
}
88+
89+
static void skip_record (FILE *f, word_t n)
90+
{
91+
int i;
92+
93+
for (i = 0; i < n; )
94+
{
95+
count (data);
96+
data = get_word (f);
97+
if (data == -1)
98+
end ();
99+
if (data & (START_RECORD | START_FILE))
100+
i++;
101+
}
102+
}
103+
104+
static void skip_file (FILE *f, word_t n)
105+
{
106+
int i;
107+
108+
for (i = 0; i < n; )
109+
{
110+
count (data);
111+
data = get_word (f);
112+
if (data == -1)
113+
end ();
114+
if (data & START_FILE)
115+
i++;
116+
}
117+
}
118+
119+
static void
120+
skip_all (FILE *f, word_t n)
121+
{
122+
(void)n;
123+
for (;;)
124+
{
125+
count (data);
126+
data = get_word (f);
127+
if (data == -1)
128+
end ();
129+
}
130+
}
131+
132+
static void insert_word (FILE *f, word_t n)
133+
{
134+
(void)f;
135+
fprintf (stderr, "Insert word\n");
136+
count (data);
137+
output (data);
138+
data = n;
139+
}
140+
141+
static void copy_word (FILE *f, word_t n)
142+
{
143+
int i;
144+
145+
for (i = 0; i < n; i++)
146+
{
147+
count (data);
148+
output (data);
149+
data = get_word (f);
150+
if (data == -1)
151+
end ();
152+
}
153+
}
154+
155+
static void copy_record (FILE *f, word_t n)
156+
{
157+
int i;
158+
159+
for (i = 0; i < n; )
160+
{
161+
count (data);
162+
output (data);
163+
data = get_word (f);
164+
if (data == -1)
165+
end ();
166+
if (data & (START_RECORD | START_FILE))
167+
i++;
168+
}
169+
}
170+
171+
static void copy_file (FILE *f, word_t n)
172+
{
173+
int i;
174+
175+
for (i = 0; i < n; )
176+
{
177+
count (data);
178+
output (data);
179+
data = get_word (f);
180+
if (data == -1)
181+
end ();
182+
if (data & START_FILE)
183+
i++;
184+
}
185+
}
186+
187+
static void
188+
copy_all (FILE *f, word_t n)
189+
{
190+
(void)n;
191+
for (;;)
192+
{
193+
count (data);
194+
output (data);
195+
data = get_word (f);
196+
if (data == -1)
197+
end ();
198+
}
199+
}
200+
201+
static void
202+
record (FILE *f, word_t n)
203+
{
204+
(void)f;
205+
(void)n;
206+
data |= START_RECORD;
207+
}
208+
209+
static void
210+
mark (FILE *f, word_t n)
211+
{
212+
(void)f;
213+
(void)n;
214+
marks++;
215+
if (marks == 1)
216+
data |= START_FILE;
217+
else if (marks >= 0)
218+
data |= START_TAPE;
219+
}
220+
221+
static void
222+
gap (FILE *f, word_t n)
223+
{
224+
(void)f;
225+
write_tape_gap (stdout, n);
226+
}
227+
228+
static void
229+
error (FILE *f, word_t n)
230+
{
231+
(void)f;
232+
write_tape_error (stdout, n);
233+
}
234+
235+
struct dispatch
236+
{
237+
const char *command;
238+
void (*action) (FILE *f, word_t n);
239+
};
240+
241+
static struct dispatch table[] =
242+
{
243+
{ "sw", skip_word },
244+
{ "sr", skip_record },
245+
{ "sf", skip_file },
246+
{ "sa", skip_all },
247+
{ "iw", insert_word },
248+
{ "cw", copy_word },
249+
{ "cr", copy_record },
250+
{ "cf", copy_file },
251+
{ "ca", copy_all },
252+
{ "r", record },
253+
{ "m", mark },
254+
{ "g", gap },
255+
{ "e", error }
256+
};
257+
258+
static void
259+
execute (FILE *f, char *command)
260+
{
261+
char *end;
262+
size_t i;
263+
264+
for (i = 0; i < sizeof table / sizeof table[0]; i++)
265+
{
266+
int n = strlen (table[i].command);
267+
if (strncmp (command, table[i].command, n) == 0) {
268+
unsigned arg = strtol (command + n, &end, 10);
269+
if (end == command + n)
270+
arg = 1;
271+
table[i].action (f, arg);
272+
}
273+
}
274+
}
275+
276+
static void
277+
convert_line (FILE *f, char **command)
278+
{
279+
while (*command)
280+
execute (f, *command++);
281+
end ();
282+
}
283+
284+
static void
285+
convert_stdin (FILE *f)
286+
{
287+
while (!feof (stdin))
288+
{
289+
char command[100];
290+
if (fgets (command, sizeof command, stdin))
291+
execute (f, command);
292+
}
293+
end ();
294+
}
295+
296+
static void
297+
usage (char **argv)
298+
{
299+
fprintf (stderr, "Usage: %s [-79] [-W<input word format>] [-O<output word format>] [<input files...>]\n\n", argv[0]);
300+
usage_word_format ();
301+
exit (1);
302+
}
303+
304+
int
305+
main (int argc, char **argv)
306+
{
307+
FILE *f;
308+
int opt;
309+
310+
output_word_format = &tape_word_format;
311+
312+
while ((opt = getopt (argc, argv, "79W:O:")) != -1)
313+
{
314+
switch (opt)
315+
{
316+
case '7':
317+
input_word_format = output_word_format = &tape7_word_format;
318+
break;
319+
case '9':
320+
input_word_format = output_word_format = &tape_word_format;
321+
break;
322+
case 'W':
323+
if (parse_input_word_format (optarg))
324+
usage (argv);
325+
break;
326+
case 'O':
327+
if (parse_output_word_format (optarg))
328+
usage (argv);
329+
break;
330+
default:
331+
usage (argv);
332+
}
333+
}
334+
335+
if (optind == argc)
336+
f = stdin;
337+
else
338+
{
339+
f = fopen (argv[optind++], "rb");
340+
if (f == NULL)
341+
{
342+
fprintf (stderr, "%s: Error opening %s: %s\n",
343+
argv[0], argv[optind - 1], strerror (errno));
344+
exit (1);
345+
}
346+
}
347+
348+
data = get_word (f);
349+
data |= START_TAPE | START_FILE | START_RECORD;
350+
fprintf (stderr, "Data: %llo\n", data);
351+
if (optind == argc)
352+
convert_stdin (f);
353+
else
354+
convert_line (f, &argv[optind]);
355+
return 0;
356+
}

0 commit comments

Comments
 (0)