Skip to content

Commit f70c8a8

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 f70c8a8

File tree

4 files changed

+359
-1
lines changed

4 files changed

+359
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
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

Lines changed: 4 additions & 1 deletion
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 353 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,353 @@
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 (words > 0)
37+
{
38+
if (word & (START_TAPE | START_FILE | START_RECORD))
39+
fprintf (stderr, "Files: %d, Records: %d, Words: %d\n",
40+
files, records, words);
41+
}
42+
words++;
43+
if (word & (START_FILE | START_RECORD))
44+
records++;
45+
if (word & START_FILE)
46+
files++;
47+
}
48+
49+
static void
50+
output (word_t word)
51+
{
52+
#if 0
53+
if (word & START_TAPE)
54+
fprintf (stderr, "Start of tape\n");
55+
else if (word & START_FILE)
56+
fprintf (stderr, "Start of file\n");
57+
else if (word & START_RECORD)
58+
fprintf (stderr, "Start of record\n");
59+
fprintf (stderr, "Output: %012llo\n", word);
60+
#endif
61+
if (word == -1)
62+
return;
63+
write_word (stdout, word);
64+
marks = 0;
65+
}
66+
67+
static void end (void)
68+
{
69+
count (START_TAPE);
70+
flush_word (stdout);
71+
exit (0);
72+
}
73+
74+
static void skip_word (FILE *f, word_t n)
75+
{
76+
int i;
77+
78+
for (i = 0; i < n; i++)
79+
{
80+
count (data);
81+
data = get_word (f);
82+
if (data == -1)
83+
end ();
84+
}
85+
}
86+
87+
static void skip_record (FILE *f, word_t n)
88+
{
89+
int i;
90+
91+
for (i = 0; i < n; )
92+
{
93+
count (data);
94+
data = get_word (f);
95+
if (data == -1)
96+
end ();
97+
if (data & (START_RECORD | START_FILE))
98+
i++;
99+
}
100+
}
101+
102+
static void skip_file (FILE *f, word_t n)
103+
{
104+
int i;
105+
106+
for (i = 0; i < n; )
107+
{
108+
count (data);
109+
data = get_word (f);
110+
if (data == -1)
111+
end ();
112+
if (data & START_FILE)
113+
i++;
114+
}
115+
}
116+
117+
static void
118+
skip_all (FILE *f, word_t n)
119+
{
120+
(void)n;
121+
for (;;)
122+
{
123+
count (data);
124+
data = get_word (f);
125+
if (data == -1)
126+
end ();
127+
}
128+
}
129+
130+
static void insert_word (FILE *f, word_t n)
131+
{
132+
(void)f;
133+
fprintf (stderr, "Insert word\n");
134+
count (data);
135+
output (data);
136+
data = n;
137+
}
138+
139+
static void copy_word (FILE *f, word_t n)
140+
{
141+
int i;
142+
143+
for (i = 0; i < n; i++)
144+
{
145+
count (data);
146+
output (data);
147+
data = get_word (f);
148+
if (data == -1)
149+
end ();
150+
}
151+
}
152+
153+
static void copy_record (FILE *f, word_t n)
154+
{
155+
int i;
156+
157+
for (i = 0; i < n; )
158+
{
159+
count (data);
160+
output (data);
161+
data = get_word (f);
162+
if (data == -1)
163+
end ();
164+
if (data & (START_RECORD | START_FILE))
165+
i++;
166+
}
167+
}
168+
169+
static void copy_file (FILE *f, word_t n)
170+
{
171+
int i;
172+
173+
for (i = 0; i < n; )
174+
{
175+
count (data);
176+
output (data);
177+
data = get_word (f);
178+
if (data == -1)
179+
end ();
180+
if (data & START_FILE)
181+
i++;
182+
}
183+
}
184+
185+
static void
186+
copy_all (FILE *f, word_t n)
187+
{
188+
(void)n;
189+
for (;;)
190+
{
191+
count (data);
192+
output (data);
193+
data = get_word (f);
194+
if (data == -1)
195+
end ();
196+
}
197+
}
198+
199+
static void
200+
record (FILE *f, word_t n)
201+
{
202+
(void)f;
203+
(void)n;
204+
data |= START_RECORD;
205+
}
206+
207+
static void
208+
mark (FILE *f, word_t n)
209+
{
210+
(void)f;
211+
(void)n;
212+
marks++;
213+
if (marks == 1)
214+
data |= START_FILE;
215+
else if (marks >= 0)
216+
data |= START_TAPE;
217+
}
218+
219+
static void
220+
gap (FILE *f, word_t n)
221+
{
222+
(void)f;
223+
write_tape_gap (stdout, n);
224+
}
225+
226+
static void
227+
error (FILE *f, word_t n)
228+
{
229+
(void)f;
230+
write_tape_error (stdout, n);
231+
}
232+
233+
struct dispatch
234+
{
235+
const char *command;
236+
void (*action) (FILE *f, word_t n);
237+
};
238+
239+
static struct dispatch table[] =
240+
{
241+
{ "sw", skip_word },
242+
{ "sr", skip_record },
243+
{ "sf", skip_file },
244+
{ "sa", skip_all },
245+
{ "iw", insert_word },
246+
{ "cw", copy_word },
247+
{ "cr", copy_record },
248+
{ "cf", copy_file },
249+
{ "ca", copy_all },
250+
{ "r", record },
251+
{ "m", mark },
252+
{ "g", gap },
253+
{ "e", error }
254+
};
255+
256+
static void
257+
execute (FILE *f, char *command)
258+
{
259+
char *end;
260+
size_t i;
261+
262+
for (i = 0; i < sizeof table / sizeof table[0]; i++)
263+
{
264+
int n = strlen (table[i].command);
265+
if (strncmp (command, table[i].command, n) == 0) {
266+
unsigned arg = strtol (command + n, &end, 10);
267+
if (end == command + n)
268+
arg = 1;
269+
table[i].action (f, arg);
270+
}
271+
}
272+
}
273+
274+
static void
275+
convert_line (FILE *f, char **command)
276+
{
277+
while (*command)
278+
execute (f, *command++);
279+
end ();
280+
}
281+
282+
static void
283+
convert_stdin (FILE *f)
284+
{
285+
while (!feof (stdin))
286+
{
287+
char command[100];
288+
if (fgets (command, sizeof command, stdin))
289+
execute (f, command);
290+
}
291+
end ();
292+
}
293+
294+
static void
295+
usage (char **argv)
296+
{
297+
fprintf (stderr, "Usage: %s [-79] [-W<input word format>] [-O<output word format>] [<input files...>]\n\n", argv[0]);
298+
usage_word_format ();
299+
exit (1);
300+
}
301+
302+
int
303+
main (int argc, char **argv)
304+
{
305+
FILE *f;
306+
int opt;
307+
308+
output_word_format = &tape_word_format;
309+
310+
while ((opt = getopt (argc, argv, "79W:O:")) != -1)
311+
{
312+
switch (opt)
313+
{
314+
case '7':
315+
input_word_format = output_word_format = &tape7_word_format;
316+
break;
317+
case '9':
318+
input_word_format = output_word_format = &tape_word_format;
319+
break;
320+
case 'W':
321+
if (parse_input_word_format (optarg))
322+
usage (argv);
323+
break;
324+
case 'O':
325+
if (parse_output_word_format (optarg))
326+
usage (argv);
327+
break;
328+
default:
329+
usage (argv);
330+
}
331+
}
332+
333+
if (optind == argc || strcmp (argv[optind], "-") == 0)
334+
f = stdin;
335+
else
336+
{
337+
f = fopen (argv[optind++], "rb");
338+
if (f == NULL)
339+
{
340+
fprintf (stderr, "%s: Error opening %s: %s\n",
341+
argv[0], argv[optind - 1], strerror (errno));
342+
exit (1);
343+
}
344+
}
345+
346+
data = get_word (f);
347+
data |= START_TAPE | START_FILE | START_RECORD;
348+
if (optind == argc)
349+
convert_stdin (f);
350+
else
351+
convert_line (f, &argv[optind]);
352+
return 0;
353+
}

0 commit comments

Comments
 (0)