Skip to content

Commit e9d740c

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 269d3ed commit e9d740c

File tree

4 files changed

+330
-1
lines changed

4 files changed

+330
-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
@@ -12,7 +12,7 @@ WORDS = aa-word.o bin-word.o cadr-word.o core-word.o data8-word.o \
1212
OBJS = pdp10-opc.o info.o dis.o symbols.o \
1313
timing.o timing_ka10.o timing_ki10.o memory.o weenix.o
1414

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

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

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

0 commit comments

Comments
 (0)