@@ -12,7 +12,6 @@ License: artistic2
12
12
=cut
13
13
14
14
use strict;
15
- use warnings;
16
15
17
16
use File::Basename qw( basename) ;
18
17
use Getopt::Std qw( getopts) ;
@@ -23,7 +22,7 @@ use constant EX_FAILURE => 1;
23
22
my $Program = basename($0 );
24
23
my $VERSION = ' 0.1' ;
25
24
26
- my (%opt , @chars , @cesc , $adr , $dump , $fmt , $nread , $curf , $skip );
25
+ my (%opt , @chars , @cesc , $adr , $dump , $fmt , $nread , $curf , $skip , $prev , $dupl );
27
26
28
27
sub VERSION_MESSAGE {
29
28
print " $Program version $VERSION \n " ;
@@ -58,6 +57,18 @@ sub doskip {
58
57
}
59
58
60
59
sub dump_c {
60
+ unless ($opt {' v' }) {
61
+ my $str = join ' ' , @chars ;
62
+ if ($str eq $prev ) {
63
+ print " *\n " unless $dupl ;
64
+ $dupl = 1;
65
+ $adr += scalar @chars ;
66
+ undef @chars ;
67
+ return ;
68
+ }
69
+ $dupl = 0;
70
+ $prev = $str ;
71
+ }
61
72
printf " $fmt " , $adr ;
62
73
foreach my $c (@chars ) {
63
74
if ($c =~ m /[[:print:] ]/ ) {
@@ -74,18 +85,121 @@ sub dump_c {
74
85
undef @chars ;
75
86
}
76
87
77
- sub dump_x {
78
- printf " $fmt " , $adr ;
88
+ sub dump_hex1 {
79
89
my $str = join ' ' , @chars ;
90
+ unless ($opt {' v' }) {
91
+ if ($str eq $prev ) {
92
+ print " *\n " unless $dupl ;
93
+ $dupl = 1;
94
+ $adr += scalar @chars ;
95
+ undef @chars ;
96
+ return ;
97
+ }
98
+ $dupl = 0;
99
+ $prev = $str ;
100
+ }
80
101
my $hex = unpack ' H*' , $str ;
81
102
$hex =~ s / ^(.{16})/ $1 / ;
82
103
$hex =~ s / (\S {2})/ $1 / g ;
83
104
$str =~ s / [^[:print:]]/ ./ g ;
105
+ printf " $fmt " , $adr ;
84
106
printf " %-51s|%s |\n " , $hex , $str ;
85
107
$adr += scalar @chars ;
86
108
undef @chars ;
87
109
}
88
110
111
+ sub dump_hex2 {
112
+ my $str = join ' ' , @chars ;
113
+ unless ($opt {' v' }) {
114
+ if ($str eq $prev ) {
115
+ print " *\n " unless $dupl ;
116
+ $dupl = 1;
117
+ $adr += scalar @chars ;
118
+ undef @chars ;
119
+ return ;
120
+ }
121
+ $dupl = 0;
122
+ $prev = $str ;
123
+ }
124
+ printf " $fmt " , $adr ;
125
+ my @words = unpack ' S*' , $str ;
126
+ foreach my $i (@words ) {
127
+ printf ' %04x ' , $i ;
128
+ }
129
+ print " \n " ;
130
+ $adr += scalar @chars ;
131
+ undef @chars ;
132
+ }
133
+
134
+ sub dump_dec2 {
135
+ my $str = join ' ' , @chars ;
136
+ unless ($opt {' v' }) {
137
+ if ($str eq $prev ) {
138
+ print " *\n " unless $dupl ;
139
+ $dupl = 1;
140
+ $adr += scalar @chars ;
141
+ undef @chars ;
142
+ return ;
143
+ }
144
+ $dupl = 0;
145
+ $prev = $str ;
146
+ }
147
+ printf " $fmt " , $adr ;
148
+ my @words = unpack ' S*' , $str ;
149
+ foreach my $i (@words ) {
150
+ printf ' %05d ' , $i ;
151
+ }
152
+ print " \n " ;
153
+ $adr += scalar @chars ;
154
+ undef @chars ;
155
+ }
156
+
157
+ sub dump_oct1 {
158
+ unless ($opt {' v' }) {
159
+ my $str = join ' ' , @chars ;
160
+ if ($str eq $prev ) {
161
+ print " *\n " unless $dupl ;
162
+ $dupl = 1;
163
+ $adr += scalar @chars ;
164
+ undef @chars ;
165
+ return ;
166
+ }
167
+ $dupl = 0;
168
+ $prev = $str ;
169
+ }
170
+ printf " $fmt " , $adr ;
171
+ foreach my $c (@chars ) {
172
+ my $i = ord $c ;
173
+ printf ' %03o ' , $i ;
174
+ }
175
+ print " \n " ;
176
+ $adr += scalar @chars ;
177
+ undef @chars ;
178
+ }
179
+
180
+ sub dump_oct2 {
181
+ my $str = join ' ' , @chars ;
182
+ unless ($opt {' v' }) {
183
+ if ($str eq $prev ) {
184
+ print " *\n " unless $dupl ;
185
+ $dupl = 1;
186
+ $adr += scalar @chars ;
187
+ undef @chars ;
188
+ return ;
189
+ }
190
+ $dupl = 0;
191
+ $prev = $str ;
192
+ }
193
+ printf " $fmt " , $adr ;
194
+ my @words = unpack ' S*' , $str ;
195
+ foreach my $i (@words ) {
196
+ printf ' %06o ' , $i ;
197
+ }
198
+ print " \n " ;
199
+ $adr += scalar @chars ;
200
+ undef @chars ;
201
+ }
202
+
89
203
sub dofile {
90
204
doskip() if $skip ;
91
205
my $c ;
@@ -128,8 +242,16 @@ sub revert {
128
242
}
129
243
130
244
sub xd {
245
+ $prev = ' ' ;
131
246
$adr = $nread = 0;
132
- if ($opt {' c' }) {
247
+ $fmt = ' %08lx' ;
248
+ $dump = \&dump_hex2;
249
+
250
+ if ($opt {' b' }) {
251
+ $dump = \&dump_oct1;
252
+ } elsif ($opt {' C' }) {
253
+ $dump = \&dump_hex1;
254
+ } elsif ($opt {' c' }) {
133
255
$fmt = ' %07lx' ;
134
256
$dump = \&dump_c;
135
257
$cesc [0] = ' \0 ' ;
@@ -140,9 +262,10 @@ sub xd {
140
262
$cesc [11] = ' \v ' ;
141
263
$cesc [12] = ' \f ' ;
142
264
$cesc [13] = ' \r ' ;
143
- } else {
144
- $fmt = ' %08lx' ;
145
- $dump = \&dump_x;
265
+ } elsif ($opt {' d' }) {
266
+ $dump = \&dump_dec2;
267
+ } elsif ($opt {' o' }) {
268
+ $dump = \&dump_oct2;
146
269
}
147
270
if (@ARGV ) {
148
271
while (@ARGV ) {
@@ -161,9 +284,9 @@ sub xd {
161
284
printf " $fmt \n " , $adr ;
162
285
}
163
286
164
- getopts(' cn:rs: ' , \%opt )
287
+ getopts(' bCcdn:ors:vx ' , \%opt )
165
288
or do {
166
- warn " usage: $Program [-cr ] [-n length] [-s skip] [file ...]\n " ;
289
+ warn " usage: $Program [-bCcdorvx ] [-n length] [-s skip] [file ...]\n " ;
167
290
exit EX_FAILURE;
168
291
};
169
292
@@ -187,34 +310,52 @@ hexdump - print input as hexadecimal
187
310
188
311
=head1 SYNOPSIS
189
312
190
- hexdump [-c ] [-n NUMBER] [-s NUMBER] [file ...]
313
+ hexdump [-bCcdovx ] [-n NUMBER] [-s NUMBER] [file ...]
191
314
192
315
hexdump [-r] [file ...]
193
316
194
317
=head1 DESCRIPTION
195
318
196
- Data is read from standard input if no file arguments are provided. The
197
- default output mode is canonical hex+ASCII. Each line begins with an offset
198
- number followed by a space-separated list of 16 hex bytes. Finally, printable
199
- input characters are listed between two '|' characters .
319
+ Input files are taken as a single stream of data and formatted as hexadecimal.
320
+ Standard input is used if no file arguments are provided.
321
+ Duplicate lines of input are filtered by default.
322
+ A '*' character is printed to indicate one or more duplicate input lines .
200
323
201
324
=head2 OPTIONS
202
325
203
326
The following options are available:
204
327
205
328
=over 4
206
329
330
+ =item -b
331
+
332
+ One-byte octal output.
333
+
334
+ =item -C
335
+
336
+ Output canonical hex+ASCII. Each line begins with an offset number followed
337
+ by a space-separated list of 16 hex bytes.
338
+ Printable input characters are listed between two '|' characters.
339
+
207
340
=item -c
208
341
209
342
Output a space-separated list of ASCII characters. Non-print characters
210
343
are listed in octal, or a C-escape code.
211
344
345
+ =item -d
346
+
347
+ Format output as two-byte decimal.
348
+
212
349
=item -n NUMBER
213
350
214
351
Terminate the process after reading a set NUMBER of input bytes.
215
352
The number argument must be given in decimal. Input skipped by the -s
216
353
option is not counted.
217
354
355
+ =item -o
356
+
357
+ Format output as two-byte octal.
358
+
218
359
=item -r
219
360
220
361
Revert a hex dump back to binary. Input is expected to be formatted as
@@ -223,24 +364,30 @@ each line are ignored. Input lines may have zero or more hex bytes;
223
364
running over 16 bytes is supported. Spaces between hex digits are ignored.
224
365
An odd number of hex digits on a line results in an error.
225
366
226
- Setting -r causes all other options to be ignored except -u. It is
227
- possible to specify multiple input files.
367
+ Setting -r causes all other options.
368
+ It is possible to specify multiple input files.
228
369
229
370
=item -s NUMBER
230
371
231
372
Skip a set NUMBER of bytes at the beginning of input. The number argument
232
373
must be given in decimal. The offset number printed on output is advanced
233
374
to reflect the skipped bytes.
234
375
376
+ =item -v
377
+
378
+ Duplicate lines of output are displayed.
379
+
380
+ =item -x
381
+
382
+ Format output as two-byte hexadecimal. This is the default.
383
+
235
384
=back
236
385
237
386
=head1 BUGS
238
387
239
388
No option exists for setting an output filename, so the -r option will
240
389
write binary data to a terminal if output is not redirected.
241
390
242
- No support for multi-byte hex display, or plain hex output.
243
-
244
391
=head1 AUTHOR
245
392
246
393
Written by Michael Mikonos.
0 commit comments