/* od -- dump files in octal and other formats This is the od utility
Copyright (C) 1992-2018 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */ The GNUv3 license
/* Written by Jim Meyering. */
#include <config.h> Provides system specific information
#include <stdio.h> Provides standard I/O capability
#include <assert.h> ...!includes auto-comment...
#include <getopt.h> ...!includes auto-comment...
#include <sys/types.h> Provides system data types
#include "system.h" ...!includes auto-comment...
#include "argmatch.h" ...!includes auto-comment...
#include "die.h" ...!includes auto-comment...
#include "error.h" ...!includes auto-comment...
#include "ftoastr.h" ...!includes auto-comment...
#include "quote.h" ...!includes auto-comment...
#include "stat-size.h" ...!includes auto-comment...
#include "xbinary-io.h" ...!includes auto-comment...
#include "xprintf.h" ...!includes auto-comment...
#include "xstrtol.h" ...!includes auto-comment...
/* The official name of this program (e.g., no 'g' prefix). */
#define PROGRAM_NAME "od" Line 37
#define AUTHORS proper_name ("Jim Meyering") Line 39
/* The default number of input bytes per output line. */
#define DEFAULT_BYTES_PER_BLOCK 16 Line 42
#if HAVE_UNSIGNED_LONG_LONG_INT Line 44
typedef unsigned long long int unsigned_long_long_int; Line 45
#else Line 46
/* This is just a place-holder to avoid a few '#if' directives.
In this case, the type isn't actually used. */
typedef unsigned long int unsigned_long_long_int; Line 49
#endif Line 50
enum size_spec Line 52
{
NO_SIZE, Line 54
CHAR, Line 55
SHORT, Line 56
INT, Line 57
LONG, Line 58
LONG_LONG, Line 59
/* FIXME: add INTMAX support, too */
FLOAT_SINGLE, Line 61
FLOAT_DOUBLE, Line 62
FLOAT_LONG_DOUBLE, Line 63
N_SIZE_SPECS Line 64
}; Block 1
enum output_format Line 67
{
SIGNED_DECIMAL, Line 69
UNSIGNED_DECIMAL, Line 70
OCTAL, Line 71
HEXADECIMAL, Line 72
FLOATING_POINT, Line 73
NAMED_CHARACTER, Line 74
CHARACTER Line 75
}; Block 2
#define MAX_INTEGRAL_TYPE_SIZE sizeof (unsigned_long_long_int) Line 78
/* The maximum number of bytes needed for a format string, including
the trailing nul. Each format string expects a variable amount of
padding (guaranteed to be at least 1 plus the field width), then an
element that will be formatted in the field. */
enum Line 84
{
FMT_BYTES_ALLOCATED = Line 86
(sizeof "%*.99" - 1 Line 87
+ MAX (sizeof "ld", Line 88
MAX (sizeof PRIdMAX, Line 89
MAX (sizeof PRIoMAX, Line 90
MAX (sizeof PRIuMAX, Line 91
sizeof PRIxMAX))))) Line 92
}; Block 3
/* Ensure that our choice for FMT_BYTES_ALLOCATED is reasonable. */
verify (MAX_INTEGRAL_TYPE_SIZE * CHAR_BIT / 3 <= 99); Line 96
/* Each output format specification (from '-t spec' or from
old-style options) is represented by one of these structures. */
struct tspec Line 100
{
enum output_format fmt; Line 102
enum size_spec size; /* Type of input object. */ Line 103
/* FIELDS is the number of fields per line, BLANK is the number of
fields to leave blank. WIDTH is width of one field, excluding
leading space, and PAD is total pad to divide among FIELDS.
PAD is at least as large as FIELDS. */
void (*print_function) (size_t fields, size_t blank, void const *data, Line 108
char const *fmt, int width, int pad); Line 109
char fmt_string[FMT_BYTES_ALLOCATED]; /* Of the style "%*d". */ Line 110
bool hexl_mode_trailer; Line 111
int field_width; /* Minimum width of a field, excluding leading space. */ Line 112
int pad_width; /* Total padding to be divided among fields. */ Line 113
}; Block 4
/* Convert the number of 8-bit bytes of a binary representation to
the number of characters (digits + sign if the type is signed)
required to represent the same quantity in the specified base/type.
For example, a 32-bit (4-byte) quantity may require a field width
as wide as the following for these types:
11 unsigned octal
11 signed decimal
10 unsigned decimal
8 unsigned hexadecimal */
static unsigned int const bytes_to_oct_digits[] = Line 126
{0, 3, 6, 8, 11, 14, 16, 19, 22, 25, 27, 30, 32, 35, 38, 41, 43}; Line 127
static unsigned int const bytes_to_signed_dec_digits[] = Line 129
{1, 4, 6, 8, 11, 13, 16, 18, 20, 23, 25, 28, 30, 33, 35, 37, 40}; Line 130
static unsigned int const bytes_to_unsigned_dec_digits[] = Line 132
{0, 3, 5, 8, 10, 13, 15, 17, 20, 22, 25, 27, 29, 32, 34, 37, 39}; Line 133
static unsigned int const bytes_to_hex_digits[] = Line 135
{0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32}; Line 136
/* It'll be a while before we see integral types wider than 16 bytes,
but if/when it happens, this check will catch it. Without this check,
a wider type would provoke a buffer overrun. */
verify (MAX_INTEGRAL_TYPE_SIZE < ARRAY_CARDINALITY (bytes_to_hex_digits)); Line 141
/* Make sure the other arrays have the same length. */
verify (sizeof bytes_to_oct_digits == sizeof bytes_to_signed_dec_digits); Line 144
verify (sizeof bytes_to_oct_digits == sizeof bytes_to_unsigned_dec_digits); Line 145
verify (sizeof bytes_to_oct_digits == sizeof bytes_to_hex_digits); Line 146
/* Convert enum size_spec to the size of the named type. */
static const int width_bytes[] = Line 149
{
-1,
sizeof (char), Line 152
sizeof (short int), Line 153
sizeof (int), Line 154
sizeof (long int), Line 155
sizeof (unsigned_long_long_int), Line 156
sizeof (float), Line 157
sizeof (double), Line 158
sizeof (long double) Line 159
};
/* Ensure that for each member of 'enum size_spec' there is an
initializer in the width_bytes array. */
verify (ARRAY_CARDINALITY (width_bytes) == N_SIZE_SPECS); Line 164
/* Names for some non-printing characters. */
static char const charname[33][4] = Line 167
{
"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", Line 169
"bs", "ht", "nl", "vt", "ff", "cr", "so", "si", Line 170
"dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", Line 171
"can", "em", "sub", "esc", "fs", "gs", "rs", "us", Line 172
"sp" Line 173
}; Block 10
/* Address base (8, 10 or 16). */
static int address_base; Line 177
/* The number of octal digits required to represent the largest
address value. */
#define MAX_ADDRESS_LENGTH \ Line 181
((sizeof (uintmax_t) * CHAR_BIT + CHAR_BIT - 1) / 3) Line 182
/* Width of a normal address. */
static int address_pad_len; Line 185
/* Minimum length when detecting --strings. */
static size_t string_min; Line 188
/* True when in --strings mode. */
static bool flag_dump_strings; Line 191
/* True if we should recognize the older non-option arguments
that specified at most one file and optional arguments specifying
offset and pseudo-start address. */
static bool traditional; Line 196
/* True if an old-style 'pseudo-address' was specified. */
static bool flag_pseudo_start; Line 199
/* The difference between the old-style pseudo starting address and
the number of bytes to skip. */
static uintmax_t pseudo_offset; Line 203
/* Function that accepts an address and an optional following char,
and prints the address and char to stdout. */
static void (*format_address) (uintmax_t, char); Line 207
/* The number of input bytes to skip before formatting and writing. */
static uintmax_t n_bytes_to_skip = 0; Line 210
/* When false, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all
input is formatted. */
static bool limit_bytes_to_format = false; Line 214
/* The maximum number of bytes that will be formatted. */
static uintmax_t max_bytes_to_format; Line 217
/* The offset of the first byte after the last byte to be formatted. */
static uintmax_t end_offset; Line 220
/* When true and two or more consecutive blocks are equal, format
only the first block and output an asterisk alone on the following
line to indicate that identical blocks have been elided. */
static bool abbreviate_duplicate_blocks = true; Line 225
/* An array of specs describing how to format each input block. */
static struct tspec *spec; Line 228
/* The number of format specs. */
static size_t n_specs; Line 231
/* The allocated length of SPEC. */
static size_t n_specs_allocated; Line 234
/* The number of input bytes formatted per output line. It must be
a multiple of the least common multiple of the sizes associated with
the specified output types. It should be as large as possible, but
no larger than 16 -- unless specified with the -w option. */
static size_t bytes_per_block; Line 240
/* Human-readable representation of *file_list (for error messages).
It differs from file_list[-1] only when file_list[-1] is "-". */
static char const *input_filename; Line 244
/* A NULL-terminated list of the file-arguments from the command line. */
static char const *const *file_list; Line 247
/* Initializer for file_list if no file-arguments
were specified on the command line. */
static char const *const default_file_list[] = {"-", NULL}; Line 251
/* The input stream associated with the current file. */
static FILE *in_stream; Line 254
/* If true, at least one of the files we read was standard input. */
static bool have_read_stdin; Line 257
/* Map the size in bytes to a type identifier. */
static enum size_spec integral_type_size[MAX_INTEGRAL_TYPE_SIZE + 1]; Line 260
#define MAX_FP_TYPE_SIZE sizeof (long double) Line 262
static enum size_spec fp_type_size[MAX_FP_TYPE_SIZE + 1]; Line 263
#ifndef WORDS_BIGENDIAN Line 265
# define WORDS_BIGENDIAN 0 Line 266
#endif Line 267
/* Use native endianess by default. */
static bool input_swap; Line 270
static char const short_options[] = "A:aBbcDdeFfHhIij:LlN:OoS:st:vw::Xx"; Line 272
/* For long options that have no equivalent short option, use a
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
enum Line 276
{
TRADITIONAL_OPTION = CHAR_MAX + 1, Line 278
ENDIAN_OPTION, Line 279
}; Block 12
enum endian_type Line 282
{
endian_little, Line 284
endian_big Line 285
}; Block 13
static char const *const endian_args[] = Line 288
{
"little", "big", NULL Line 290
}; Block 14
static enum endian_type const endian_types[] = Line 293
{
endian_little, endian_big Line 295
}; Block 15
static struct option const long_options[] = Line 298
{
{"skip-bytes", required_argument, NULL, 'j'}, Line 300
{"address-radix", required_argument, NULL, 'A'}, Line 301
{"read-bytes", required_argument, NULL, 'N'}, Line 302
{"format", required_argument, NULL, 't'}, Line 303
{"output-duplicates", no_argument, NULL, 'v'}, Line 304
{"strings", optional_argument, NULL, 'S'}, Line 305
{"traditional", no_argument, NULL, TRADITIONAL_OPTION}, Line 306
{"width", optional_argument, NULL, 'w'}, Line 307
{"endian", required_argument, NULL, ENDIAN_OPTION }, Line 308
{GETOPT_HELP_OPTION_DECL}, Line 310
{GETOPT_VERSION_OPTION_DECL}, Line 311
{NULL, 0, NULL, 0} Line 312
}; Block 16
void Line 315
usage (int status) Line 316
{
if (status != EXIT_SUCCESS) Line 318
emit_try_help (); ...!common auto-comment...
else Line 320
{
printf (_("\ Line 322
Usage: %s [OPTION]... [FILE]...\n\ Line 323
or: %s [-abcdfilosx]... [FILE] [[+]OFFSET[.][b]]\n\ Line 324
or: %s --traditional [OPTION]... [FILE] [[+]OFFSET[.][b] [+][LABEL][.][b]]\n\Line 325
"), Line 326
program_name, program_name, program_name); Line 327
fputs (_("\n\ Line 328
Write an unambiguous representation, octal bytes by default,\n\ Line 329
of FILE to standard output. With more than one FILE argument,\n\ Line 330
concatenate them in the listed order to form the input.\n\ Line 331
"), stdout); Line 332
emit_stdin_note (); ...!common auto-comment...
fputs (_("\ Line 336
\n\
If first and second call formats both apply, the second format is assumed\n\ Line 338
if the last operand begins with + or (if there are 2 operands) a digit.\n\ Line 339
An OFFSET operand means -j OFFSET. LABEL is the pseudo-address\n\ Line 340
at first byte printed, incremented when dump is progressing.\n\ Line 341
For OFFSET and LABEL, a 0x or 0X prefix indicates hexadecimal;\n\ Line 342
suffixes may be . for octal and b for multiply by 512.\n\ Line 343
"), stdout); Line 344
emit_mandatory_arg_note (); ...!common auto-comment...
fputs (_("\ Line 348
-A, --address-radix=RADIX output format for file offsets; RADIX is one\n\ Line 349
of [doxn], for Decimal, Octal, Hex or None\n\ Line 350
--endian={big|little} swap input bytes according the specified order\n\ Line 351
-j, --skip-bytes=BYTES skip BYTES input bytes first\n\ Line 352
"), stdout); Line 353
fputs (_("\ Line 354
-N, --read-bytes=BYTES limit dump to BYTES input bytes\n\ Line 355
-S BYTES, --strings[=BYTES] output strings of at least BYTES graphic chars;\ Line 356
\n\
3 is implied when BYTES is not specified\n\ Line 358
-t, --format=TYPE select output format or formats\n\ Line 359
-v, --output-duplicates do not use * to mark line suppression\n\ Line 360
-w[BYTES], --width[=BYTES] output BYTES bytes per output line;\n\ Line 361
32 is implied when BYTES is not specified\n\ Line 362
--traditional accept arguments in third form above\n\ Line 363
"), stdout); Line 364
fputs (HELP_OPTION_DESCRIPTION, stdout); Line 365
fputs (VERSION_OPTION_DESCRIPTION, stdout); Line 366
fputs (_("\ Line 367
\n\
\n\
Traditional format specifications may be intermixed; they accumulate:\n\ Line 370
-a same as -t a, select named characters, ignoring high-order bit\n\ Line 371
-b same as -t o1, select octal bytes\n\ Line 372
-c same as -t c, select printable characters or backslash escapes\n\ Line 373
-d same as -t u2, select unsigned decimal 2-byte units\n\ Line 374
"), stdout); Line 375
fputs (_("\ Line 376
-f same as -t fF, select floats\n\ Line 377
-i same as -t dI, select decimal ints\n\ Line 378
-l same as -t dL, select decimal longs\n\ Line 379
-o same as -t o2, select octal 2-byte units\n\ Line 380
-s same as -t d2, select decimal 2-byte units\n\ Line 381
-x same as -t x2, select hexadecimal 2-byte units\n\ Line 382
"), stdout); Line 383
fputs (_("\ Line 384
\n\
\n\
TYPE is made up of one or more of these specifications:\n\ Line 387
a named character, ignoring high-order bit\n\ Line 388
c printable character or backslash escape\n\ Line 389
"), stdout); Line 390
fputs (_("\ Line 391
d[SIZE] signed decimal, SIZE bytes per integer\n\ Line 392
f[SIZE] floating point, SIZE bytes per float\n\ Line 393
o[SIZE] octal, SIZE bytes per integer\n\ Line 394
u[SIZE] unsigned decimal, SIZE bytes per integer\n\ Line 395
x[SIZE] hexadecimal, SIZE bytes per integer\n\ Line 396
"), stdout); Line 397
fputs (_("\ Line 398
\n\
SIZE is a number. For TYPE in [doux], SIZE may also be C for\n\ Line 400
sizeof(char), S for sizeof(short), I for sizeof(int) or L for\n\ Line 401
sizeof(long). If TYPE is f, SIZE may also be F for sizeof(float), D\n\ Line 402
for sizeof(double) or L for sizeof(long double).\n\ Line 403
"), stdout); Line 404
fputs (_("\ Line 405
\n\
Adding a z suffix to any type displays printable characters at the end of\n\ Line 407
each output line.\n\ Line 408
"), stdout); Line 409
fputs (_("\ Line 410
\n\
\n\
BYTES is hex with 0x or 0X prefix, and may have a multiplier suffix:\n\ Line 413
b 512\n\ Line 414
KB 1000\n\ Line 415
K 1024\n\ Line 416
MB 1000*1000\n\ Line 417
M 1024*1024\n\ Line 418
and so on for G, T, P, E, Z, Y.\n\ Line 419
Binary prefixes can be used, too: KiB=K, MiB=M, and so on.\n\ Line 420
"), stdout); Line 421
emit_ancillary_info (PROGRAM_NAME); Line 422
}
exit (status); Line 424
} Block 17
/* Define the print functions. */
#define PRINT_FIELDS(N, T, FMT_STRING, ACTION) \ Line 429
static void \ Line 430
N (size_t fields, size_t blank, void const *block, \ Line 431
char const *FMT_STRING, int width, int pad) \ Line 432
{ \ Line 433
T const *p = block; \ Line 434
uintmax_t i; \ Line 435
int pad_remaining = pad; \ Line 436
for (i = fields; blank < i; i--) \ Line 437
{ \ Line 438
int next_pad = pad * (i - 1) / fields; \ Line 439
int adjusted_width = pad_remaining - next_pad + width; \ Line 440
T x; \ Line 441
if (input_swap && sizeof (T) > 1) \ Line 442
{ \ Line 443
size_t j; \ Line 444
union { \ Line 445
T x; \ Line 446
char b[sizeof (T)]; \ Line 447
} u; \ Line 448
for (j = 0; j < sizeof (T); j++) \ Line 449
u.b[j] = ((const char *) p)[sizeof (T) - 1 - j]; \ Line 450
x = u.x; \ Line 451
} \ Line 452
else \ Line 453
x = *p; \ Line 454
p++; \ Line 455
ACTION; \ Line 456
pad_remaining = next_pad; \ Line 457
} \ Line 458
} Block 18
#define PRINT_TYPE(N, T) \ Line 461
PRINT_FIELDS (N, T, fmt_string, xprintf (fmt_string, adjusted_width, x)) Line 462
#define PRINT_FLOATTYPE(N, T, FTOASTR, BUFSIZE) \ Line 464
PRINT_FIELDS (N, T, fmt_string _GL_UNUSED, \ Line 465
char buf[BUFSIZE]; \ Line 466
FTOASTR (buf, sizeof buf, 0, 0, x); \ Line 467
xprintf ("%*s", adjusted_width, buf)) Line 468
PRINT_TYPE (print_s_char, signed char) Line 470
PRINT_TYPE (print_char, unsigned char) Line 471
PRINT_TYPE (print_s_short, short int) Line 472
PRINT_TYPE (print_short, unsigned short int) Line 473
PRINT_TYPE (print_int, unsigned int) Line 474
PRINT_TYPE (print_long, unsigned long int) Line 475
PRINT_TYPE (print_long_long, unsigned_long_long_int) Line 476
PRINT_FLOATTYPE (print_float, float, ftoastr, FLT_BUFSIZE_BOUND) Line 478
PRINT_FLOATTYPE (print_double, double, dtoastr, DBL_BUFSIZE_BOUND) Line 479
PRINT_FLOATTYPE (print_long_double, long double, ldtoastr, LDBL_BUFSIZE_BOUND) Line 480
#undef PRINT_TYPE Line 482
#undef PRINT_FLOATTYPE Line 483
static void Line 485
dump_hexl_mode_trailer (size_t n_bytes, const char *block) Line 486
{
fputs (" >", stdout); Line 488
for (size_t i = n_bytes; i > 0; i--) Line 489
{
unsigned char c = *block++; Line 491
unsigned char c2 = (isprint (c) ? c : '.'); Line 492
putchar (c2); Line 493
}
putchar ('<'); Line 495
} Block 19
static void Line 498
print_named_ascii (size_t fields, size_t blank, void const *block, Line 499
const char *unused_fmt_string _GL_UNUSED, Line 500
int width, int pad) Line 501
{
unsigned char const *p = block; Line 503
uintmax_t i; Line 504
int pad_remaining = pad; Line 505
for (i = fields; blank < i; i--) Line 506
{
int next_pad = pad * (i - 1) / fields; Line 508
int masked_c = *p++ & 0x7f; Line 509
const char *s; Line 510
char buf[2]; Line 511
if (masked_c == 127) Line 513
s = "del"; Line 514
else if (masked_c <= 040) Line 515
s = charname[masked_c]; Line 516
else Line 517
{
buf[0] = masked_c; Line 519
buf[1] = 0; Line 520
s = buf; Line 521
}
xprintf ("%*s", pad_remaining - next_pad + width, s); Line 524
pad_remaining = next_pad; Line 525
}
} Block 20
static void Line 529
print_ascii (size_t fields, size_t blank, void const *block, Line 530
const char *unused_fmt_string _GL_UNUSED, int width, Line 531
int pad) Line 532
{
unsigned char const *p = block; Line 534
uintmax_t i; Line 535
int pad_remaining = pad; Line 536
for (i = fields; blank < i; i--) Line 537
{
int next_pad = pad * (i - 1) / fields; Line 539
unsigned char c = *p++; Line 540
const char *s; Line 541
char buf[4]; Line 542
switch (c) Line 544
{
case '\0': Line 546
s = "\\0"; Line 547
break; Line 548
case '\a': Line 550
s = "\\a"; Line 551
break; Line 552
case '\b': Line 554
s = "\\b"; Line 555
break; Line 556
case '\f': Line 558
s = "\\f"; Line 559
break; Line 560
case '\n': Line 562
s = "\\n"; Line 563
break; Line 564
case '\r': Line 566
s = "\\r"; Line 567
break; Line 568
case '\t': Line 570
s = "\\t"; Line 571
break; Line 572
case '\v': Line 574
s = "\\v"; Line 575
break; Line 576
default: Line 578
sprintf (buf, (isprint (c) ? "%c" : "%03o"), c); Line 579
s = buf; Line 580
}
xprintf ("%*s", pad_remaining - next_pad + width, s); Line 583
pad_remaining = next_pad; Line 584
}
} Block 21
/* Convert a null-terminated (possibly zero-length) string S to an
unsigned long integer value. If S points to a non-digit set *P to S,
*VAL to 0, and return true. Otherwise, accumulate the integer value of
the string of digits. If the string of digits represents a value
larger than ULONG_MAX, don't modify *VAL or *P and return false.
Otherwise, advance *P to the first non-digit after S, set *VAL to
the result of the conversion and return true. */
static bool Line 596
simple_strtoul (const char *s, const char **p, unsigned long int *val) Line 597
{
unsigned long int sum; Line 599
sum = 0; Line 601
while (ISDIGIT (*s)) Line 602
{
int c = *s++ - '0'; Line 604
if (sum > (ULONG_MAX - c) / 10) Line 605
return false; Line 606
sum = sum * 10 + c; Line 607
}
*p = s; Line 609
*val = sum; Line 610
return true; Line 611
} Block 22
/* If S points to a single valid modern od format string, put
a description of that format in *TSPEC, make *NEXT point at the
character following the just-decoded format (if *NEXT is non-NULL),
and return true. If S is not valid, don't modify *NEXT or *TSPEC,
give a diagnostic, and return false. For example, if S were
"d4afL" *NEXT would be set to "afL" and *TSPEC would be
{
fmt = SIGNED_DECIMAL;
size = INT or LONG; (whichever integral_type_size[4] resolves to)
print_function = print_int; (assuming size == INT)
field_width = 11;
fmt_string = "%*d";
}
pad_width is determined later, but is at least as large as the
number of fields printed per row.
S_ORIG is solely for reporting errors. It should be the full format
string argument.
*/
static bool Line 633
decode_one_format (const char *s_orig, const char *s, const char **next, Line 634
struct tspec *tspec) Line 635
{
enum size_spec size_spec; Line 637
unsigned long int size; Line 638
enum output_format fmt; Line 639
void (*print_function) (size_t, size_t, void const *, char const *, Line 640
int, int); Line 641
const char *p; Line 642
char c; Line 643
int field_width; Line 644
assert (tspec != NULL); Line 646
switch (*s) Line 648
{
case 'd': Line 650
case 'o': Line 651
case 'u': Line 652
case 'x': Line 653
c = *s; Line 654
++s; Line 655
switch (*s) Line 656
{
case 'C': Line 658
++s; Line 659
size = sizeof (char); Line 660
break; Line 661
case 'S': Line 663
++s; Line 664
size = sizeof (short int); Line 665
break; Line 666
case 'I': Line 668
++s; Line 669
size = sizeof (int); Line 670
break; Line 671
case 'L': Line 673
++s; Line 674
size = sizeof (long int); Line 675
break; Line 676
default: Line 678
if (! simple_strtoul (s, &p, &size)) Line 679
{
/* The integer at P in S would overflow an unsigned long int.
A digit string that long is sufficiently odd looking
that the following diagnostic is sufficient. */
error (0, 0, _("invalid type string %s"), quote (s_orig)); Line 684
return false; Line 685
}
if (p == s) Line 687
size = sizeof (int); Line 688
else Line 689
{
if (MAX_INTEGRAL_TYPE_SIZE < size Line 691
|| integral_type_size[size] == NO_SIZE) Line 692
{
error (0, 0, _("invalid type string %s;\nthis system" Line 694
" doesn't provide a %lu-byte integral type"), Line 695
quote (s_orig), size); Line 696
return false; Line 697
}
s = p; Line 699
}
break; Line 701
}
#define ISPEC_TO_FORMAT(Spec, Min_format, Long_format, Max_format) \ Line 704
((Spec) == LONG_LONG ? (Max_format) \ Line 705
: ((Spec) == LONG ? (Long_format) \ Line 706
: (Min_format))) \ Line 707
size_spec = integral_type_size[size]; Line 709
switch (c) Line 711
{
case 'd': Line 713
fmt = SIGNED_DECIMAL; Line 714
field_width = bytes_to_signed_dec_digits[size]; Line 715
sprintf (tspec->fmt_string, "%%*%s", Line 716
ISPEC_TO_FORMAT (size_spec, "d", "ld", PRIdMAX)); Line 717
break; Line 718
case 'o': Line 720
fmt = OCTAL; Line 721
sprintf (tspec->fmt_string, "%%*.%d%s", Line 722
(field_width = bytes_to_oct_digits[size]), Line 723
ISPEC_TO_FORMAT (size_spec, "o", "lo", PRIoMAX)); Line 724
break; Line 725
case 'u': Line 727
fmt = UNSIGNED_DECIMAL; Line 728
field_width = bytes_to_unsigned_dec_digits[size]; Line 729
sprintf (tspec->fmt_string, "%%*%s", Line 730
ISPEC_TO_FORMAT (size_spec, "u", "lu", PRIuMAX)); Line 731
break; Line 732
case 'x': Line 734
fmt = HEXADECIMAL; Line 735
sprintf (tspec->fmt_string, "%%*.%d%s", Line 736
(field_width = bytes_to_hex_digits[size]), Line 737
ISPEC_TO_FORMAT (size_spec, "x", "lx", PRIxMAX)); Line 738
break; Line 739
default: Line 741
abort (); ...!common auto-comment...
}
assert (strlen (tspec->fmt_string) < FMT_BYTES_ALLOCATED); Line 745
switch (size_spec) Line 747
{
case CHAR: Line 749
print_function = (fmt == SIGNED_DECIMAL Line 750
? print_s_char Line 751
: print_char); Line 752
break; Line 753
case SHORT: Line 755
print_function = (fmt == SIGNED_DECIMAL Line 756
? print_s_short Line 757
: print_short); Line 758
break; Line 759
case INT: Line 761
print_function = print_int; Line 762
break; Line 763
case LONG: Line 765
print_function = print_long; Line 766
break; Line 767
case LONG_LONG: Line 769
print_function = print_long_long; Line 770
break; Line 771
default: Line 773
abort (); ...!common auto-comment...
}
break; Line 776
case 'f': Line 778
fmt = FLOATING_POINT; Line 779
++s; Line 780
switch (*s) Line 781
{
case 'F': Line 783
++s; Line 784
size = sizeof (float); Line 785
break; Line 786
case 'D': Line 788
++s; Line 789
size = sizeof (double); Line 790
break; Line 791
case 'L': Line 793
++s; Line 794
size = sizeof (long double); Line 795
break; Line 796
default: Line 798
if (! simple_strtoul (s, &p, &size)) Line 799
{
/* The integer at P in S would overflow an unsigned long int.
A digit string that long is sufficiently odd looking
that the following diagnostic is sufficient. */
error (0, 0, _("invalid type string %s"), quote (s_orig)); Line 804
return false; Line 805
}
if (p == s) Line 807
size = sizeof (double); Line 808
else Line 809
{
if (size > MAX_FP_TYPE_SIZE Line 811
|| fp_type_size[size] == NO_SIZE) Line 812
{
error (0, 0, Line 814
_("invalid type string %s;\n" Line 815
"this system doesn't provide a %lu-byte" Line 816
" floating point type"), Line 817
quote (s_orig), size); Line 818
return false; Line 819
}
s = p; Line 821
}
break; Line 823
}
size_spec = fp_type_size[size]; Line 825
{
struct lconv const *locale = localeconv (); Line 828
size_t decimal_point_len = Line 829
(locale->decimal_point[0] ? strlen (locale->decimal_point) : 1); Line 830
switch (size_spec) Line 832
{
case FLOAT_SINGLE: Line 834
print_function = print_float; Line 835
field_width = FLT_STRLEN_BOUND_L (decimal_point_len); Line 836
break; Line 837
case FLOAT_DOUBLE: Line 839
print_function = print_double; Line 840
field_width = DBL_STRLEN_BOUND_L (decimal_point_len); Line 841
break; Line 842
case FLOAT_LONG_DOUBLE: Line 844
print_function = print_long_double; Line 845
field_width = LDBL_STRLEN_BOUND_L (decimal_point_len); Line 846
break; Line 847
default: Line 849
abort (); ...!common auto-comment...
}
break; Line 853
}
case 'a': Line 856
++s; Line 857
fmt = NAMED_CHARACTER; Line 858
size_spec = CHAR; Line 859
print_function = print_named_ascii; Line 860
field_width = 3; Line 861
break; Line 862
case 'c': Line 864
++s; Line 865
fmt = CHARACTER; Line 866
size_spec = CHAR; Line 867
print_function = print_ascii; Line 868
field_width = 3; Line 869
break; Line 870
default: Line 872
error (0, 0, _("invalid character '%c' in type string %s"), Line 873
*s, quote (s_orig)); Line 874
return false; Line 875
}
tspec->size = size_spec; Line 878
tspec->fmt = fmt; Line 879
tspec->print_function = print_function; Line 880
tspec->field_width = field_width; Line 882
tspec->hexl_mode_trailer = (*s == 'z'); Line 883
if (tspec->hexl_mode_trailer) Line 884
s++; Line 885
if (next != NULL) Line 887
*next = s; Line 888
return true; Line 890
} Block 23
/* Given a list of one or more input filenames FILE_LIST, set the global
file pointer IN_STREAM and the global string INPUT_FILENAME to the
first one that can be successfully opened. Modify FILE_LIST to
reference the next filename in the list. A file name of "-" is
interpreted as standard input. If any file open fails, give an error
message and return false. */
static bool Line 900
open_next_file (void) Line 901
{
bool ok = true; Line 903
do
{
input_filename = *file_list; Line 907
if (input_filename == NULL) Line 908
return ok; Line 909
++file_list; Line 910
if (STREQ (input_filename, "-")) Line 912
{
input_filename = _("standard input"); Line 914
in_stream = stdin; Line 915
have_read_stdin = true; Line 916
xset_binary_mode (STDIN_FILENO, O_BINARY); Line 917
}
else Line 919
{
in_stream = fopen (input_filename, (O_BINARY ? "rb" : "r")); Line 921...!syscalls auto-comment...
if (in_stream == NULL) Line 922
{
error (0, errno, "%s", quotef (input_filename)); Line 924
ok = false; Line 925
}
}
}
while (in_stream == NULL); Line 929
if (limit_bytes_to_format && !flag_dump_strings) Line 931
setvbuf (in_stream, NULL, _IONBF, 0); Line 932
return ok; Line 934
} Block 24
/* Test whether there have been errors on in_stream, and close it if
it is not standard input. Return false if there has been an error
on in_stream or stdout; return true otherwise. This function will
report more than one error only if both a read and a write error
have occurred. IN_ERRNO, if nonzero, is the error number
corresponding to the most recent action for IN_STREAM. */
static bool Line 944
check_and_close (int in_errno) Line 945...!syscalls auto-comment...
{
bool ok = true; Line 947
if (in_stream != NULL) Line 949
{
if (ferror (in_stream)) Line 951
{
error (0, in_errno, _("%s: read error"), quotef (input_filename)); Line 953
if (! STREQ (file_list[-1], "-")) Line 954
fclose (in_stream); Line 955...!syscalls auto-comment...
ok = false; Line 956
}
else if (! STREQ (file_list[-1], "-") && fclose (in_stream) != 0) Line 958...!syscalls auto-comment...
{
error (0, errno, "%s", quotef (input_filename)); Line 960
ok = false; Line 961
}
in_stream = NULL; Line 964
}
if (ferror (stdout)) Line 967
{
error (0, 0, _("write error")); Line 969
ok = false; Line 970
}
return ok; Line 973
} Block 25
/* Decode the modern od format string S. Append the decoded
representation to the global array SPEC, reallocating SPEC if
necessary. Return true if S is valid. */
static bool Line 980
decode_format_string (const char *s) Line 981
{
const char *s_orig = s; Line 983
assert (s != NULL); Line 984
while (*s != '\0') Line 986
{
const char *next; Line 988
if (n_specs_allocated <= n_specs) Line 990
spec = X2NREALLOC (spec, &n_specs_allocated); Line 991
if (! decode_one_format (s_orig, s, &next, &spec[n_specs])) Line 993
return false; Line 994
assert (s != next); Line 996
s = next; Line 997
++n_specs; Line 998
}
return true; Line 1001
} Block 26
/* Given a list of one or more input filenames FILE_LIST, set the global
file pointer IN_STREAM to position N_SKIP in the concatenation of
those files. If any file operation fails or if there are fewer than
N_SKIP bytes in the combined input, give an error message and return
false. When possible, use seek rather than read operations to
advance IN_STREAM. */
static bool Line 1011
skip (uintmax_t n_skip) Line 1012
{
bool ok = true; Line 1014
int in_errno = 0; Line 1015
if (n_skip == 0) Line 1017
return true; Line 1018
while (in_stream != NULL) /* EOF. */ Line 1020
{
struct stat file_stats; Line 1022
/* First try seeking. For large offsets, this extra work is
worthwhile. If the offset is below some threshold it may be
more efficient to move the pointer by reading. There are two
issues when trying to seek:
- the file must be seekable.
- before seeking to the specified position, make sure
that the new position is in the current file.
Try to do that by getting file's size using fstat.
But that will work only for regular files. */
if (fstat (fileno (in_stream), &file_stats) == 0) Line 1034...!syscalls auto-comment......!syscalls auto-comment...
{
/* The st_size field is valid for regular files.
If the number of bytes left to skip is larger than
the size of the current file, we can decrement n_skip
and go on to the next file. Skip this optimization also
when st_size is no greater than the block size, because
some kernels report nonsense small file sizes for
proc-like file systems. */
if (usable_st_size (&file_stats) Line 1043
&& ST_BLKSIZE (file_stats) < file_stats.st_size) Line 1044
{
if ((uintmax_t) file_stats.st_size < n_skip) Line 1046
n_skip -= file_stats.st_size; Line 1047
else Line 1048
{
if (fseeko (in_stream, n_skip, SEEK_CUR) != 0) Line 1050
{
in_errno = errno; Line 1052
ok = false; Line 1053
}
n_skip = 0; Line 1055
}
}
/* If it's not a regular file with nonnegative size,
or if it's so small that it might be in a proc-like file system,
position the file pointer by reading. */
else Line 1063
{
char buf[BUFSIZ]; Line 1065
size_t n_bytes_read, n_bytes_to_read = BUFSIZ; Line 1066
while (0 < n_skip) Line 1068
{
if (n_skip < n_bytes_to_read) Line 1070
n_bytes_to_read = n_skip; Line 1071
n_bytes_read = fread (buf, 1, n_bytes_to_read, in_stream); Line 1072...!syscalls auto-comment...
n_skip -= n_bytes_read; Line 1073
if (n_bytes_read != n_bytes_to_read) Line 1074
{
if (ferror (in_stream)) Line 1076
{
in_errno = errno; Line 1078
ok = false; Line 1079
n_skip = 0; Line 1080
break; Line 1081
}
if (feof (in_stream)) Line 1083
break; Line 1084
}
}
}
if (n_skip == 0) Line 1089
break; Line 1090
}
else /* cannot fstat() file */ Line 1093
{
error (0, errno, "%s", quotef (input_filename)); Line 1095
ok = false; Line 1096
}
ok &= check_and_close (in_errno); Line 1099...!syscalls auto-comment...
ok &= open_next_file (); Line 1101
}
if (n_skip != 0) Line 1104
die (EXIT_FAILURE, 0, _("cannot skip past end of combined input")); Line 1105
return ok; Line 1107
} Block 27
static void Line 1110
format_address_none (uintmax_t address _GL_UNUSED, Line 1111
char c _GL_UNUSED) Line 1112
{
}
static void Line 1116
format_address_std (uintmax_t address, char c) Line 1117
{
char buf[MAX_ADDRESS_LENGTH + 2]; Line 1119
char *p = buf + sizeof buf; Line 1120
char const *pbound; Line 1121
*--p = '\0'; Line 1123
*--p = c; Line 1124
pbound = p - address_pad_len; Line 1125
/* Use a special case of the code for each base. This is measurably
faster than generic code. */
switch (address_base) Line 1129
{
case 8: Line 1131
do
*--p = '0' + (address & 7); Line 1133
while ((address >>= 3) != 0); Line 1134
break; Line 1135
case 10: Line 1137
do
*--p = '0' + (address % 10); Line 1139
while ((address /= 10) != 0); Line 1140
break; Line 1141
case 16: Line 1143
do
*--p = "0123456789abcdef"[address & 15]; Line 1145
while ((address >>= 4) != 0); Line 1146
break; Line 1147
}
while (pbound < p) Line 1150
*--p = '0'; Line 1151
fputs (p, stdout); Line 1153
} Block 29
static void Line 1156
format_address_paren (uintmax_t address, char c) Line 1157
{
putchar ('('); Line 1159
format_address_std (address, ')'); Line 1160
if (c) Line 1161
putchar (c); Line 1162
} Block 30
static void Line 1165
format_address_label (uintmax_t address, char c) Line 1166
{
format_address_std (address, ' '); Line 1168
format_address_paren (address + pseudo_offset, c); Line 1169
} Block 31
/* Write N_BYTES bytes from CURR_BLOCK to standard output once for each
of the N_SPEC format specs. CURRENT_OFFSET is the byte address of
CURR_BLOCK in the concatenation of input files, and it is printed
(optionally) only before the output line associated with the first
format spec. When duplicate blocks are being abbreviated, the output
for a sequence of identical input blocks is the output for the first
block followed by an asterisk alone on a line. It is valid to compare
the blocks PREV_BLOCK and CURR_BLOCK only when N_BYTES == BYTES_PER_BLOCK.
That condition may be false only for the last input block. */
static void Line 1182
write_block (uintmax_t current_offset, size_t n_bytes, Line 1183
const char *prev_block, const char *curr_block) Line 1184
{
static bool first = true; Line 1186
static bool prev_pair_equal = false; Line 1187
#define EQUAL_BLOCKS(b1, b2) (memcmp (b1, b2, bytes_per_block) == 0) Line 1189
if (abbreviate_duplicate_blocks Line 1191
&& !first && n_bytes == bytes_per_block Line 1192
&& EQUAL_BLOCKS (prev_block, curr_block)) Line 1193
{
if (prev_pair_equal) Line 1195
{
/* The two preceding blocks were equal, and the current
block is the same as the last one, so print nothing. */
}
else Line 1200
{
printf ("*\n"); Line 1202
prev_pair_equal = true; Line 1203
}
}
else Line 1206
{
prev_pair_equal = false; Line 1208
for (size_t i = 0; i < n_specs; i++) Line 1209
{
int datum_width = width_bytes[spec[i].size]; Line 1211
int fields_per_block = bytes_per_block / datum_width; Line 1212
int blank_fields = (bytes_per_block - n_bytes) / datum_width; Line 1213
if (i == 0) Line 1214
format_address (current_offset, '\0'); Line 1215
else Line 1216
printf ("%*s", address_pad_len, ""); Line 1217
(*spec[i].print_function) (fields_per_block, blank_fields, Line 1218
curr_block, spec[i].fmt_string, Line 1219
spec[i].field_width, spec[i].pad_width); Line 1220
if (spec[i].hexl_mode_trailer) Line 1221
{
/* space-pad out to full line width, then dump the trailer */
int field_width = spec[i].field_width; Line 1224
int pad_width = (spec[i].pad_width * blank_fields Line 1225
/ fields_per_block); Line 1226
printf ("%*s", blank_fields * field_width + pad_width, ""); Line 1227
dump_hexl_mode_trailer (n_bytes, curr_block); Line 1228
}
putchar ('\n'); Line 1230
}
}
first = false; Line 1233
} Block 32
/* Read a single byte into *C from the concatenation of the input files
named in the global array FILE_LIST. On the first call to this
function, the global variable IN_STREAM is expected to be an open
stream associated with the input file INPUT_FILENAME. If IN_STREAM
is at end-of-file, close it and update the global variables IN_STREAM
and INPUT_FILENAME so they correspond to the next file in the list.
Then try to read a byte from the newly opened file. Repeat if
necessary until EOF is reached for the last file in FILE_LIST, then
set *C to EOF and return. Subsequent calls do likewise. Return
true if successful. */
static bool Line 1247
read_char (int *c) Line 1248
{
bool ok = true; Line 1250
*c = EOF; Line 1252
while (in_stream != NULL) /* EOF. */ Line 1254
{
*c = fgetc (in_stream); Line 1256
if (*c != EOF) Line 1258
break; Line 1259
ok &= check_and_close (errno); Line 1261...!syscalls auto-comment...
ok &= open_next_file (); Line 1263
}
return ok; Line 1266
} Block 33
/* Read N bytes into BLOCK from the concatenation of the input files
named in the global array FILE_LIST. On the first call to this
function, the global variable IN_STREAM is expected to be an open
stream associated with the input file INPUT_FILENAME. If all N
bytes cannot be read from IN_STREAM, close IN_STREAM and update
the global variables IN_STREAM and INPUT_FILENAME. Then try to
read the remaining bytes from the newly opened file. Repeat if
necessary until EOF is reached for the last file in FILE_LIST.
On subsequent calls, don't modify BLOCK and return true. Set
*N_BYTES_IN_BUFFER to the number of bytes read. If an error occurs,
it will be detected through ferror when the stream is about to be
closed. If there is an error, give a message but continue reading
as usual and return false. Otherwise return true. */
static bool Line 1283
read_block (size_t n, char *block, size_t *n_bytes_in_buffer) Line 1284
{
bool ok = true; Line 1286
assert (0 < n && n <= bytes_per_block); Line 1288
*n_bytes_in_buffer = 0; Line 1290
while (in_stream != NULL) /* EOF. */ Line 1292
{
size_t n_needed; Line 1294
size_t n_read; Line 1295
n_needed = n - *n_bytes_in_buffer; Line 1297
n_read = fread (block + *n_bytes_in_buffer, 1, n_needed, in_stream); Line 1298...!syscalls auto-comment...
*n_bytes_in_buffer += n_read; Line 1300
if (n_read == n_needed) Line 1302
break; Line 1303
ok &= check_and_close (errno); Line 1305...!syscalls auto-comment...
ok &= open_next_file (); Line 1307
}
return ok; Line 1310
} Block 34
/* Return the least common multiple of the sizes associated
with the format specs. */
static int _GL_ATTRIBUTE_PURE Line 1316
get_lcm (void) Line 1317
{
int l_c_m = 1; Line 1319
for (size_t i = 0; i < n_specs; i++) Line 1321
l_c_m = lcm (l_c_m, width_bytes[spec[i].size]); Line 1322
return l_c_m; Line 1323
} Block 35
/* If S is a valid traditional offset specification with an optional
leading '+' return true and set *OFFSET to the offset it denotes. */
static bool Line 1329
parse_old_offset (const char *s, uintmax_t *offset) Line 1330
{
int radix; Line 1332
if (*s == '\0') Line 1334
return false; Line 1335
/* Skip over any leading '+'. */
if (s[0] == '+') Line 1338
++s; Line 1339
/* Determine the radix we'll use to interpret S. If there is a '.',
it's decimal, otherwise, if the string begins with '0X'or '0x',
it's hexadecimal, else octal. */
if (strchr (s, '.') != NULL) Line 1344
radix = 10; Line 1345
else Line 1346
{
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) Line 1348
radix = 16; Line 1349
else Line 1350
radix = 8; Line 1351
}
return xstrtoumax (s, NULL, radix, offset, "Bb") == LONGINT_OK; Line 1354
} Block 36
/* Read a chunk of size BYTES_PER_BLOCK from the input files, write the
formatted block to standard output, and repeat until the specified
maximum number of bytes has been read or until all input has been
processed. If the last block read is smaller than BYTES_PER_BLOCK
and its size is not a multiple of the size associated with a format
spec, extend the input block with zero bytes until its length is a
multiple of all format spec sizes. Write the final block. Finally,
write on a line by itself the offset of the byte after the last byte
read. Accumulate return values from calls to read_block and
check_and_close, and if any was false, return false.
Otherwise, return true. */
static bool Line 1369
dump (void) Line 1370
{
char *block[2]; Line 1372
uintmax_t current_offset; Line 1373
bool idx = false; Line 1374
bool ok = true; Line 1375
size_t n_bytes_read; Line 1376
block[0] = xnmalloc (2, bytes_per_block); Line 1378
block[1] = block[0] + bytes_per_block; Line 1379
current_offset = n_bytes_to_skip; Line 1381
if (limit_bytes_to_format) Line 1383
{
while (1) Line 1385
{
size_t n_needed; Line 1387
if (current_offset >= end_offset) Line 1388
{
n_bytes_read = 0; Line 1390
break; Line 1391
}
n_needed = MIN (end_offset - current_offset, Line 1393
(uintmax_t) bytes_per_block); Line 1394
ok &= read_block (n_needed, block[idx], &n_bytes_read); Line 1395
if (n_bytes_read < bytes_per_block) Line 1396
break; Line 1397
assert (n_bytes_read == bytes_per_block); Line 1398
write_block (current_offset, n_bytes_read, Line 1399
block[!idx], block[idx]); Line 1400
current_offset += n_bytes_read; Line 1401
idx = !idx; Line 1402
}
}
else Line 1405
{
while (1) Line 1407
{
ok &= read_block (bytes_per_block, block[idx], &n_bytes_read); Line 1409
if (n_bytes_read < bytes_per_block) Line 1410
break; Line 1411
assert (n_bytes_read == bytes_per_block); Line 1412
write_block (current_offset, n_bytes_read, Line 1413
block[!idx], block[idx]); Line 1414
current_offset += n_bytes_read; Line 1415
idx = !idx; Line 1416
}
}
if (n_bytes_read > 0) Line 1420
{
int l_c_m; Line 1422
size_t bytes_to_write; Line 1423
l_c_m = get_lcm (); Line 1425
/* Ensure zero-byte padding up to the smallest multiple of l_c_m that
is at least as large as n_bytes_read. */
bytes_to_write = l_c_m * ((n_bytes_read + l_c_m - 1) / l_c_m); Line 1429
memset (block[idx] + n_bytes_read, 0, bytes_to_write - n_bytes_read); Line 1431
write_block (current_offset, n_bytes_read, block[!idx], block[idx]); Line 1432
current_offset += n_bytes_read; Line 1433
}
format_address (current_offset, '\n'); Line 1436
if (limit_bytes_to_format && current_offset >= end_offset) Line 1438
ok &= check_and_close (0); Line 1439...!syscalls auto-comment...
free (block[0]); Line 1441
return ok; Line 1443
} Block 37
/* STRINGS mode. Find each "string constant" in the input.
A string constant is a run of at least 'string_min' ASCII
graphic (or formatting) characters terminated by a null.
Based on a function written by Richard Stallman for a
traditional version of od. Return true if successful. */
static bool Line 1452
dump_strings (void) Line 1453
{
size_t bufsize = MAX (100, string_min); Line 1455
char *buf = xmalloc (bufsize); Line 1456
uintmax_t address = n_bytes_to_skip; Line 1457
bool ok = true; Line 1458
while (1) Line 1460
{
size_t i; Line 1462
int c; Line 1463
/* See if the next 'string_min' chars are all printing chars. */
tryline: Line 1466
if (limit_bytes_to_format Line 1468
&& (end_offset < string_min || end_offset - string_min <= address)) Line 1469
break; Line 1470
for (i = 0; i < string_min; i++) Line 1472
{
ok &= read_char (&c); Line 1474
address++; Line 1475
if (c < 0) Line 1476
{
free (buf); Line 1478
return ok; Line 1479
}
if (! isprint (c)) Line 1481
/* Found a non-printing. Try again starting with next char. */
goto tryline; Line 1483
buf[i] = c; Line 1484
}
/* We found a run of 'string_min' printable characters.
Now see if it is terminated with a null byte. */
while (!limit_bytes_to_format || address < end_offset) Line 1489
{
if (i == bufsize) Line 1491
{
buf = X2REALLOC (buf, &bufsize); Line 1493
}
ok &= read_char (&c); Line 1495
address++; Line 1496
if (c < 0) Line 1497
{
free (buf); Line 1499
return ok; Line 1500
}
if (c == '\0') Line 1502
break; /* It is; print this string. */ Line 1503
if (! isprint (c)) Line 1504
goto tryline; /* It isn't; give up on this string. */ Line 1505
buf[i++] = c; /* String continues; store it all. */ Line 1506
}
/* If we get here, the string is all printable and null-terminated,
so print it. It is all in 'buf' and 'i' is its length. */
buf[i] = 0; Line 1511
format_address (address - i - 1, ' '); Line 1512
for (i = 0; (c = buf[i]); i++) Line 1514
{
switch (c) Line 1516
{
case '\a': Line 1518
fputs ("\\a", stdout); Line 1519
break; Line 1520
case '\b': Line 1522
fputs ("\\b", stdout); Line 1523
break; Line 1524
case '\f': Line 1526
fputs ("\\f", stdout); Line 1527
break; Line 1528
case '\n': Line 1530
fputs ("\\n", stdout); Line 1531
break; Line 1532
case '\r': Line 1534
fputs ("\\r", stdout); Line 1535
break; Line 1536
case '\t': Line 1538
fputs ("\\t", stdout); Line 1539
break; Line 1540
case '\v': Line 1542
fputs ("\\v", stdout); Line 1543
break; Line 1544
default: Line 1546
putc (c, stdout); Line 1547
}
}
putchar ('\n'); Line 1550
}
/* We reach this point only if we search through
(max_bytes_to_format - string_min) bytes before reaching EOF. */
free (buf); Line 1556
ok &= check_and_close (0); Line 1558...!syscalls auto-comment...
return ok; Line 1559
} Block 38
int
main (int argc, char **argv) Line 1563
{
int n_files; Line 1565
size_t i; Line 1566
int l_c_m; Line 1567
size_t desired_width IF_LINT ( = 0); Line 1568
bool modern = false; Line 1569
bool width_specified = false; Line 1570
bool ok = true; Line 1571
size_t width_per_block = 0; Line 1572
static char const multipliers[] = "bEGKkMmPTYZ0"; Line 1573
/* The old-style 'pseudo starting address' to be printed in parentheses
after any true address. */
uintmax_t pseudo_start IF_LINT ( = 0); Line 1577
initialize_main (&argc, &argv); VMS-specific entry point handling wildcard expansion
set_program_name (argv[0]); Retains program name and discards path
setlocale (LC_ALL, ""); Sets up internationalization (i18n)
bindtextdomain (PACKAGE, LOCALEDIR); Assigns i18n directorySets text domain for _() [gettext()] function
textdomain (PACKAGE); Sets text domain for _() [gettext()] function
atexit (close_stdout); Close stdout on exit (see gnulib)
for (i = 0; i <= MAX_INTEGRAL_TYPE_SIZE; i++) Line 1587
integral_type_size[i] = NO_SIZE; Line 1588
integral_type_size[sizeof (char)] = CHAR; Line 1590
integral_type_size[sizeof (short int)] = SHORT; Line 1591
integral_type_size[sizeof (int)] = INT; Line 1592
integral_type_size[sizeof (long int)] = LONG; Line 1593
#if HAVE_UNSIGNED_LONG_LONG_INT Line 1594
/* If 'long int' and 'long long int' have the same size, it's fine
to overwrite the entry for 'long' with this one. */
integral_type_size[sizeof (unsigned_long_long_int)] = LONG_LONG; Line 1597
#endif Line 1598
for (i = 0; i <= MAX_FP_TYPE_SIZE; i++) Line 1600
fp_type_size[i] = NO_SIZE; Line 1601
fp_type_size[sizeof (float)] = FLOAT_SINGLE; Line 1603
/* The array entry for 'double' is filled in after that for 'long double'
so that if they are the same size, we avoid any overhead of
long double computation in libc. */
fp_type_size[sizeof (long double)] = FLOAT_LONG_DOUBLE; Line 1607
fp_type_size[sizeof (double)] = FLOAT_DOUBLE; Line 1608
n_specs = 0; Line 1610
n_specs_allocated = 0; Line 1611
spec = NULL; Line 1612
format_address = format_address_std; Line 1614
address_base = 8; Line 1615
address_pad_len = 7; Line 1616
flag_dump_strings = false; Line 1617
while (true) Line 1619
{
uintmax_t tmp; Line 1621
enum strtol_error s_err; Line 1622
int oi = -1; Line 1623
int c = getopt_long (argc, argv, short_options, long_options, &oi); Line 1624
if (c == -1) Line 1625
break; Line 1626
switch (c) Line 1628
{
case 'A': Line 1630
modern = true; Line 1631
switch (optarg[0]) Line 1632
{
case 'd': Line 1634
format_address = format_address_std; Line 1635
address_base = 10; Line 1636
address_pad_len = 7; Line 1637
break; Line 1638
case 'o': Line 1639
format_address = format_address_std; Line 1640
address_base = 8; Line 1641
address_pad_len = 7; Line 1642
break; Line 1643
case 'x': Line 1644
format_address = format_address_std; Line 1645
address_base = 16; Line 1646
address_pad_len = 6; Line 1647
break; Line 1648
case 'n': Line 1649
format_address = format_address_none; Line 1650
address_pad_len = 0; Line 1651
break; Line 1652
default: Line 1653
die (EXIT_FAILURE, 0, Line 1654
_("invalid output address radix '%c';\ Line 1655
it must be one character from [doxn]"), Line 1656
optarg[0]); Line 1657
break; Line 1658
}
break; Line 1660
case 'j': Line 1662
modern = true; Line 1663
s_err = xstrtoumax (optarg, NULL, 0, &n_bytes_to_skip, multipliers); Line 1664
if (s_err != LONGINT_OK) Line 1665
xstrtol_fatal (s_err, oi, c, long_options, optarg); Line 1666
break; Line 1667
case 'N': Line 1669
modern = true; Line 1670
limit_bytes_to_format = true; Line 1671
s_err = xstrtoumax (optarg, NULL, 0, &max_bytes_to_format, Line 1673
multipliers); Line 1674
if (s_err != LONGINT_OK) Line 1675
xstrtol_fatal (s_err, oi, c, long_options, optarg); Line 1676
break; Line 1677
case 'S': Line 1679
modern = true; Line 1680
if (optarg == NULL) Line 1681
string_min = 3; Line 1682
else Line 1683
{
s_err = xstrtoumax (optarg, NULL, 0, &tmp, multipliers); Line 1685
if (s_err != LONGINT_OK) Line 1686
xstrtol_fatal (s_err, oi, c, long_options, optarg); Line 1687
/* The minimum string length may be no larger than SIZE_MAX,
since we may allocate a buffer of this size. */
if (SIZE_MAX < tmp) Line 1691
die (EXIT_FAILURE, 0, _("%s is too large"), quote (optarg)); Line 1692
string_min = tmp; Line 1694
}
flag_dump_strings = true; Line 1696
break; Line 1697
case 't': Line 1699
modern = true; Line 1700
ok &= decode_format_string (optarg); Line 1701
break; Line 1702
case 'v': Line 1704
modern = true; Line 1705
abbreviate_duplicate_blocks = false; Line 1706
break; Line 1707
case TRADITIONAL_OPTION: Line 1709
traditional = true; Line 1710
break; Line 1711
case ENDIAN_OPTION: Line 1713
switch (XARGMATCH ("--endian", optarg, endian_args, endian_types)) Line 1714
{
case endian_big: Line 1716
input_swap = ! WORDS_BIGENDIAN; Line 1717
break; Line 1718
case endian_little: Line 1719
input_swap = WORDS_BIGENDIAN; Line 1720
break; Line 1721
}
break; Line 1723
/* The next several cases map the traditional format
specification options to the corresponding modern format
specs. GNU od accepts any combination of old- and
new-style options. Format specification options accumulate.
The obsolescent and undocumented formats are compatible
with FreeBSD 4.10 od. */
#define CASE_OLD_ARG(old_char,new_string) \ Line 1732
case old_char: \ Line 1733
ok &= decode_format_string (new_string); \ Line 1734
break Line 1735
CASE_OLD_ARG ('a', "a"); Line 1737
CASE_OLD_ARG ('b', "o1"); Line 1738
CASE_OLD_ARG ('c', "c"); Line 1739
CASE_OLD_ARG ('D', "u4"); /* obsolescent and undocumented */ Line 1740
CASE_OLD_ARG ('d', "u2"); Line 1741
case 'F': /* obsolescent and undocumented alias */ Line 1742
CASE_OLD_ARG ('e', "fD"); /* obsolescent and undocumented */ Line 1743
CASE_OLD_ARG ('f', "fF"); Line 1744
case 'X': /* obsolescent and undocumented alias */ Line 1745
CASE_OLD_ARG ('H', "x4"); /* obsolescent and undocumented */ Line 1746
CASE_OLD_ARG ('i', "dI"); Line 1747
case 'I': case 'L': /* obsolescent and undocumented aliases */ Line 1748
CASE_OLD_ARG ('l', "dL"); Line 1749
CASE_OLD_ARG ('O', "o4"); /* obsolesent and undocumented */ Line 1750
case 'B': /* obsolescent and undocumented alias */ Line 1751
CASE_OLD_ARG ('o', "o2"); Line 1752
CASE_OLD_ARG ('s', "d2"); Line 1753
case 'h': /* obsolescent and undocumented alias */ Line 1754
CASE_OLD_ARG ('x', "x2"); Line 1755
#undef CASE_OLD_ARG Line 1757
case 'w': Line 1759
modern = true; Line 1760
width_specified = true; Line 1761
if (optarg == NULL) Line 1762
{
desired_width = 32; Line 1764
}
else Line 1766
{
uintmax_t w_tmp; Line 1768
s_err = xstrtoumax (optarg, NULL, 10, &w_tmp, ""); Line 1769
if (s_err != LONGINT_OK) Line 1770
xstrtol_fatal (s_err, oi, c, long_options, optarg); Line 1771
if (SIZE_MAX < w_tmp) Line 1772
die (EXIT_FAILURE, 0, _("%s is too large"), quote (optarg)); Line 1773
desired_width = w_tmp; Line 1774
}
break; Line 1776
case_GETOPT_HELP_CHAR; Line 1778
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); Line 1780
default: Line 1782
usage (EXIT_FAILURE); Line 1783
break; Line 1784
}
}
if (!ok) Line 1788
return EXIT_FAILURE; Line 1789
if (flag_dump_strings && n_specs > 0) Line 1791
die (EXIT_FAILURE, 0, Line 1792
_("no type may be specified when dumping strings")); Line 1793
n_files = argc - optind; Line 1795
/* If the --traditional option is used, there may be from
0 to 3 remaining command line arguments; handle each case
separately.
od [file] [[+]offset[.][b] [[+]label[.][b]]]
The offset and label have the same syntax.
If --traditional is not given, and if no modern options are
given, and if the offset begins with + or (if there are two
operands) a digit, accept only this form, as per POSIX:
od [file] [[+]offset[.][b]]
*/
if (!modern || traditional) Line 1809
{
uintmax_t o1; Line 1811
uintmax_t o2; Line 1812
switch (n_files) Line 1814
{
case 1: Line 1816
if ((traditional || argv[optind][0] == '+') Line 1817
&& parse_old_offset (argv[optind], &o1)) Line 1818
{
n_bytes_to_skip = o1; Line 1820
--n_files; Line 1821
++argv; Line 1822
}
break; Line 1824
case 2: Line 1826
if ((traditional || argv[optind + 1][0] == '+' Line 1827
|| ISDIGIT (argv[optind + 1][0])) Line 1828
&& parse_old_offset (argv[optind + 1], &o2)) Line 1829
{
if (traditional && parse_old_offset (argv[optind], &o1)) Line 1831
{
n_bytes_to_skip = o1; Line 1833
flag_pseudo_start = true; Line 1834
pseudo_start = o2; Line 1835
argv += 2; Line 1836
n_files -= 2; Line 1837
}
else Line 1839
{
n_bytes_to_skip = o2; Line 1841
--n_files; Line 1842
argv[optind + 1] = argv[optind]; Line 1843
++argv; Line 1844
}
}
break; Line 1847
case 3: Line 1849
if (traditional Line 1850
&& parse_old_offset (argv[optind + 1], &o1) Line 1851
&& parse_old_offset (argv[optind + 2], &o2)) Line 1852
{
n_bytes_to_skip = o1; Line 1854
flag_pseudo_start = true; Line 1855
pseudo_start = o2; Line 1856
argv[optind + 2] = argv[optind]; Line 1857
argv += 2; Line 1858
n_files -= 2; Line 1859
}
break; Line 1861
}
if (traditional && 1 < n_files) Line 1864
{
error (0, 0, _("extra operand %s"), quote (argv[optind + 1])); Line 1866
error (0, 0, "%s", Line 1867
_("compatibility mode supports at most one file")); Line 1868
usage (EXIT_FAILURE); Line 1869
}
}
if (flag_pseudo_start) Line 1873
{
if (format_address == format_address_none) Line 1875
{
address_base = 8; Line 1877
address_pad_len = 7; Line 1878
format_address = format_address_paren; Line 1879
}
else Line 1881
format_address = format_address_label; Line 1882
}
if (limit_bytes_to_format) Line 1885
{
end_offset = n_bytes_to_skip + max_bytes_to_format; Line 1887
if (end_offset < n_bytes_to_skip) Line 1888
die (EXIT_FAILURE, 0, _("skip-bytes + read-bytes is too large")); Line 1889
}
if (n_specs == 0) Line 1892
decode_format_string ("oS"); Line 1893
if (n_files > 0) Line 1895
{
/* Set the global pointer FILE_LIST so that it
references the first file-argument on the command-line. */
file_list = (char const *const *) &argv[optind]; Line 1900
}
else Line 1902
{
/* No files were listed on the command line.
Set the global pointer FILE_LIST so that it
references the null-terminated list of one name: "-". */
file_list = default_file_list; Line 1908
}
/* open the first input file */
ok = open_next_file (); Line 1912
if (in_stream == NULL) Line 1913
goto cleanup; Line 1914
/* skip over any unwanted header bytes */
ok &= skip (n_bytes_to_skip); Line 1917
if (in_stream == NULL) Line 1918
goto cleanup; Line 1919
pseudo_offset = (flag_pseudo_start ? pseudo_start - n_bytes_to_skip : 0); Line 1921
/* Compute output block length. */
l_c_m = get_lcm (); Line 1924
if (width_specified) Line 1926
{
if (desired_width != 0 && desired_width % l_c_m == 0) Line 1928
bytes_per_block = desired_width; Line 1929
else Line 1930
{
error (0, 0, _("warning: invalid width %lu; using %d instead"), Line 1932
(unsigned long int) desired_width, l_c_m); Line 1933
bytes_per_block = l_c_m; Line 1934
}
}
else Line 1937
{
if (l_c_m < DEFAULT_BYTES_PER_BLOCK) Line 1939
bytes_per_block = l_c_m * (DEFAULT_BYTES_PER_BLOCK / l_c_m); Line 1940
else Line 1941
bytes_per_block = l_c_m; Line 1942
}
/* Compute padding necessary to align output block. */
for (i = 0; i < n_specs; i++) Line 1946
{
int fields_per_block = bytes_per_block / width_bytes[spec[i].size]; Line 1948
int block_width = (spec[i].field_width + 1) * fields_per_block; Line 1949
if (width_per_block < block_width) Line 1950
width_per_block = block_width; Line 1951
}
for (i = 0; i < n_specs; i++) Line 1953
{
int fields_per_block = bytes_per_block / width_bytes[spec[i].size]; Line 1955
int block_width = spec[i].field_width * fields_per_block; Line 1956
spec[i].pad_width = width_per_block - block_width; Line 1957
}
#ifdef DEBUG Line 1960
printf ("lcm=%d, width_per_block=%"PRIuMAX"\n", l_c_m, Line 1961
(uintmax_t) width_per_block); Line 1962
for (i = 0; i < n_specs; i++) Line 1963
{
int fields_per_block = bytes_per_block / width_bytes[spec[i].size]; Line 1965
assert (bytes_per_block % width_bytes[spec[i].size] == 0); Line 1966
assert (1 <= spec[i].pad_width / fields_per_block); Line 1967
printf ("%d: fmt=\"%s\" in_width=%d out_width=%d pad=%d\n", Line 1968
i, spec[i].fmt_string, width_bytes[spec[i].size], Line 1969
spec[i].field_width, spec[i].pad_width); Line 1970
}
#endif Line 1972
ok &= (flag_dump_strings ? dump_strings () : dump ()); Line 1974
cleanup: Line 1976
if (have_read_stdin && fclose (stdin) == EOF) Line 1978...!syscalls auto-comment...
die (EXIT_FAILURE, errno, _("standard input")); Line 1979
return ok ? EXIT_SUCCESS : EXIT_FAILURE; Line 1981
} Block 39