Skip to content

Commit 4d29f2f

Browse files
authored
od: implement -a option (#646)
* BSD and GNU versions support -a for printing literal characters, with control character names printed * GNU version deliberately masks highest (8th) bit per byte, so we follow this * This is consistent with standards document[1] wording: "named characters from the International Reference Version (IRV) of the ISO/IEC 646:1991 standard. Only the least significant seven bits of each byte shall be used" * Standards document doesn't mention -a flag, but generally -a is taken to mean the same as "-t a" * Attempt to document the available options 1. http://ktiml.mff.cuni.cz/~kucerap/unix/susv4tc2/utilities/od.html
1 parent 500ac57 commit 4d29f2f

File tree

1 file changed

+129
-6
lines changed

1 file changed

+129
-6
lines changed

bin/od

Lines changed: 129 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ use constant EX_FAILURE => 1;
2323
use constant LINESZ => 16;
2424
use constant PRINTMAX => 126;
2525

26-
use vars qw/ $opt_A $opt_b $opt_c $opt_d $opt_f $opt_i $opt_j $opt_l $opt_N
27-
$opt_o $opt_v $opt_x /;
26+
use vars qw/ $opt_A $opt_a $opt_b $opt_c $opt_d $opt_f $opt_i $opt_j $opt_l
27+
$opt_N $opt_o $opt_v $opt_x /;
28+
29+
our $VERSION = '1.0';
2830

2931
my ($offset1, $radix, $data, @arr, $len, $lim);
3032
my ($lastline, $strfmt, $ml);
@@ -41,12 +43,49 @@ my %charescs = (
4143
92 => ' \\\\',
4244
);
4345

46+
my %charname = (
47+
0 => 'nul',
48+
1 => 'soh',
49+
2 => 'stx',
50+
3 => 'etx',
51+
4 => 'eot',
52+
5 => 'enq',
53+
6 => 'ack',
54+
7 => 'bel',
55+
8 => 'bs',
56+
9 => 'ht',
57+
10 => 'nl',
58+
11 => 'vt',
59+
12 => 'ff',
60+
13 => 'cr',
61+
14 => 'so',
62+
15 => 'si',
63+
16 => 'dle',
64+
17 => 'dc1',
65+
18 => 'dc2',
66+
19 => 'dc3',
67+
20 => 'dc4',
68+
21 => 'nak',
69+
22 => 'syn',
70+
23 => 'etb',
71+
24 => 'can',
72+
25 => 'em',
73+
26 => 'sub',
74+
27 => 'esc',
75+
28 => 'fs',
76+
29 => 'gs',
77+
30 => 'rs',
78+
31 => 'us',
79+
32 => 'sp',
80+
127 => 'del',
81+
);
82+
4483
$offset1 = 0;
4584
$lastline = '';
4685

4786
my $Program = basename($0);
4887

49-
getopts('A:bcdfij:lN:ovx') or help();
88+
getopts('A:abcdfij:lN:ovx') or help();
5089
if (defined $opt_A) {
5190
if ($opt_A !~ m/\A[doxn]\z/) {
5291
warn "$Program: unexpected radix: '$opt_A'\n";
@@ -75,7 +114,10 @@ if (defined $opt_N) {
75114
}
76115

77116
my $fmt;
78-
if ($opt_b) {
117+
if ($opt_a) {
118+
$fmt = \&char7bit;
119+
}
120+
elsif ($opt_b) {
79121
$fmt = \&octal1;
80122
}
81123
elsif ($opt_c) {
@@ -131,6 +173,11 @@ dump_line() if (defined $data);
131173
emit_offset(1);
132174
exit $rc;
133175

176+
sub VERSION_MESSAGE {
177+
print "$Program version $VERSION\n";
178+
exit EX_SUCCESS;
179+
}
180+
134181
sub limit_reached {
135182
return defined($lim) && $nread >= $lim;
136183
}
@@ -216,6 +263,21 @@ sub char1 {
216263
$strfmt = '%s';
217264
}
218265

266+
sub char7bit {
267+
@arr = ();
268+
my @arr1 = unpack 'C*', $data;
269+
for my $val (@arr1) {
270+
my $n = $val & 0x7f;
271+
if (exists $charname{$n}) {
272+
$arr[0] .= sprintf '%4s', $charname{$n};
273+
}
274+
else {
275+
$arr[0] .= " " . chr($n) . " ";
276+
}
277+
}
278+
$strfmt = '%s';
279+
}
280+
219281
sub udecimal {
220282
if (length($data) & 1) { # pad to 16 bit
221283
@arr = unpack 'S*', $data . "\0";
@@ -286,7 +348,7 @@ sub diffdata {
286348
}
287349

288350
sub help {
289-
print "usage: od [-bcdfiloxv] [-A radix] [-j skip_bytes] [-N limit_bytes] [file]...\n";
351+
print "usage: od [-abcdfiloxv] [-A radix] [-j skip_bytes] [-N limit_bytes] [file]...\n";
290352
exit EX_FAILURE;
291353
}
292354
__END__
@@ -297,7 +359,7 @@ od - dump files in octal and other formats
297359
298360
=head1 SYNOPSIS
299361
300-
B<od> [ I<-bcdfiloxv> ] [I<-j skip_n_bytes>] [I<-N read_n_bytes>] [ I<-A radix> ] [ F<file>... ]
362+
B<od> [ I<-abcdfiloxv> ] [I<-j skip_n_bytes>] [I<-N read_n_bytes>] [ I<-A radix> ] [ F<file>... ]
301363
302364
=head1 DESCRIPTION
303365
@@ -308,6 +370,67 @@ column of each line, followed by one or more columns of data from the
308370
file, in a format controlled by the options. By default, od prints the
309371
file offsets in octal and the file data as two-byte octal numbers.
310372
373+
=head2 OPTIONS
374+
375+
The following options are available:
376+
377+
=over 4
378+
379+
=item -A Radix
380+
381+
Select offset prefix format: 'd' for decimal, 'o' for octal, 'x' for hexadecimal, 'n' for none.
382+
383+
=item -a
384+
385+
Dump characters in 7-bit ASCII format, ignoring the highest bit of each byte.
386+
The names of ASCII control characters are displayed.
387+
388+
=item -b
389+
390+
Single-byte octal display.
391+
392+
=item -c
393+
394+
Display characters literally, with non-printable characters displayed as C escape sequences.
395+
396+
=item -d
397+
398+
Two-byte unsigned decimal display.
399+
400+
=item -f
401+
402+
Show input as floating point numbers in exponent form.
403+
404+
=item -i
405+
406+
Show two-byte signed integers.
407+
408+
=item -j Skip
409+
410+
Ignore the first Skip bytes of input.
411+
412+
=item -l
413+
414+
Show four-byte signed integers.
415+
416+
=item -N Bytes
417+
418+
Set the number of maximum input bytes read.
419+
420+
=item -o
421+
422+
Format input as two-byte octal numbers.
423+
424+
=item -x
425+
426+
Use two-byte hexadecimal format.
427+
428+
=item -v
429+
430+
Show all lines, even if they are identical to the previous line.
431+
432+
=back
433+
311434
=head1 SEE ALSO
312435
313436
od(1)

0 commit comments

Comments
 (0)