/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1992-2012 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* David Korn
* AT&T Research
*
* od
*/
static const char usage[] =
"[-?\n@(#)$Id: od (AT&T Research) 2012-05-31 $\n]"
"[+NAME?od - dump files in octal or other formats]"
"[+DESCRIPTION?\bod\b dumps the contents of the input files in various "
"formats on the standard output. The standard input is read if \b-\b or "
"no files are specified. Each output line contains the file offset of "
"the data in the leftmost column, followed by one or more columns in the "
"specified format. If more than one format is specified then the "
"subsequent lines are listed with the offset column blank. Second and "
"subsequent occurrences of a repeated output line are replaced by a "
"single line with `*' in the first data column.]"
"[+?\b--format=c\b, \b--format=C\b and \b--format=O\b interpret bytes as "
"characters in the LC_CTYPE locale category. The three types differ only "
"in the C style escape sequences recognized; \b--format=C\b explicitly "
"allows future extensions. The backslash character is written as `\\' "
"and NUL is written as `\\0'. Other non-printable characters are written "
"as one three-digit octal number for each byte in the character. "
"Printable multi-byte characters are written in the area corresponding "
"to the first byte of the character; the two-character sequence `**' is "
"written in the area corresponding to each remaining byte in the "
"character; the remaining bytes for \b-p\b are written as ` '. If "
"\b--skip\b or \b--count\b position the file into the middle of a "
"multibyte character then the entire multibyte character is silently "
"treated as non-character bytes.]"
"[+?If the output format is specified by one of the obsolete forms (not "
"\b--format\b) then the last file argument is interpreted as an offset "
"expression if it matches the extended regular expression "
"\b+?[0-9]]+\\.?[bkm]]?(ll|LL)?\b . In this case the first \aoffset\a "
"bytes of the file are skipped. The optional \bb\b means bytes, \bk\b "
"means Kb, and \bm\b means Mb. \bll\b and \bLL\b are ignored for "
"compatibility with some systems.]"
"[A:address-radix?The file offset radix.]:[radix:=o]"
"{"
"[+d?decimal]"
"[+o?octal]"
"[+x?hexadecimal]"
"[+n?none - do not print offset]"
"}"
"[B:swap?Swap input bytes according to the bit mask \aop\a, which is the "
"inclusive or of:]#[op]"
"{"
"[+01?swap 8-bit bytes]"
"[+02?swap 16-bit words]"
"[+04?swap 32-bit longs]"
"[+0?swap for big endian testing]"
"}"
"[j:skip-bytes?Skip \bbytes\b bytes into the data before "
"formatting.]#[bytes]"
"[N:count|read-bytes?Output only \bbytes\b bytes of data.]#[bytes]"
"[m:map?\b--printable\b and \b--format=m\b bytes are converted from "
"\acodeset\a to the native codeset. The codesets are:]:[codeset]"
"{\fcodesets\f} [p:printable?Output the printable bytes (after \b--map\b "
"if specified), in the last data column. Non-printable byte values are "
"printed as `.'.]"
"[z:strings?Output NUL terminated strings of at least \alength\a "
"bytes.]#? [length:=3]"
"[t:format|type?The data item output \aformat\a and \asize\a. A decimal byte "
"count or size code may follow all but the \ba\b, \bc\b, \bC\b, \bm\b "
"and \bO\b formats.]:[format[size]]:=o2]"
"{\ftypes\f}"
"[T:test?Enable internal implementation specific tests.]:[test]"
"{"
"[+b\an\a?Allocate a fixed input buffer of size \an\a.]"
"[+m\an\a?Set the mapped input buffer size to \an\a.]"
"[+n?Turn off the \bSF_SHARE\b input buffer flag.]"
"}"
"[v:all|output-duplicates?Output all data.]"
"[w:per-line|width?The number of items to format per output line. "
"\aper-line\a must be a multiple of the least common multiple of the "
"sizes of the format types.]#[per-line]"
"[a?Equivalent to \b-ta\b.]"
"[b?Equivalent to \b-toC\b.]"
"[c?Equivalent to \b-tO\b.]"
"[C?Equivalent to \b-tO\b.]"
"[d?Equivalent to \b-tuS\b.]"
"[D?Equivalent to \b-tuL\b.]"
"[f?Equivalent to \b-tfF\b.]"
"[F?Equivalent to \b-tfD\b.]"
"[h?Equivalent to \b-txS\b.]"
"[i?Equivalent to \b-tdS\b.]"
"[l?Equivalent to \b-tdL\b.]"
"[o?Equivalent to \b-toS\b.]"
"[O?Equivalent to \b-toL\b.]"
"[s?Equivalent to \b-tdS\b.]"
"[S?Equivalent to \b-tdL\b.]"
"[u?Equivalent to \b-tuS\b.]"
"[U?Equivalent to \b-tuL\b.]"
"[x?Equivalent to \b-txS\b.]"
"[X?Equivalent to \b-txL\b.]"
"\n"
"\n[ file ... ] [ [+]offset[.|b|k|m|ll|LL] ]\n"
"\n"
"[+SEE ALSO?\bsed\b(1), \bstrings\b(1), \bswap\b(3), \bascii\b(5)]"
;
#include <cmd.h>
#include <sig.h>
#include <swap.h>
#include <ccode.h>
#include <ctype.h>
#include <iconv.h>
#include <vmalloc.h>
#include <ast_float.h>
#if _hdr_wctype
#include <wchar.h>
#include <wctype.h>
#else
#endif
#ifdef _ast_int8_t
#else
#endif
#if _typ_long_double
#define double_max long double
#else
#define double_max double
#endif
typedef union Mem_u
{
float m_float;
double m_double;
#if _typ_long_double
long double m_long_double;
#endif
} Mem_t;
typedef struct Size_s
{
char* desc;
int name;
int map;
int dflt;
const char* qual;
int size;
int prefix;
int digits;
int exponent;
} Size_t;
typedef struct Type_s
{
char* desc;
char name;
char mb;
const char* fill;
} Type_t;
struct Format_s
{
struct
{
int external;
int internal;
} size;
int fp;
int width;
int us;
int per;
};
struct State_s
{
int addr;
int block;
struct
{
char* base;
int noshare;
} buffer;
struct
{
char* data;
int mark;
} dup;
unsigned char* eob;
char* file;
unsigned char* map;
int mb;
int mbmax;
int mbp;
struct
{
char* data;
} peek;
int printable;
int size;
char* span;
int spansize;
int strings;
int style;
int swap;
int verbose;
int width;
};
{
"char", 'C', 0, 1, 0, 1,0,0,0,
0
};
{
"char", 'C', 0, 0, 0, 1,0,0,0,
"short", 'S', 0, 0, 0, sizeof(short),0,0,0,
"int", 'I', 0, 1, 0, sizeof(int),0,0,0,
"long", 'L', 0, 0, "l", sizeof(long),0,0,0,
"long long", 'D', 0, 0,
#ifdef _ast_int8_t
"ll", sizeof(int64_t),0,0,0,
#else
0, sizeof(long),0,0,0,
#endif
0
};
{
"long double", 'L', 'e', 0,
#if _typ_long_double
#else
#endif
0
};
{
"long double", 'L', 'a', 0,
#if _typ_long_double
#else
#endif
0
};
static void
{
register int c = *u;
static const char anames[] =
"nulsohstxetxeotenqackbel bs ht nl vt ff cr so si"
"dledc1dc2dc3dc4naksynetbcan emsubesc fs gs rs us"
" sp ! \" # $ % & ' ( ) * + , - . /"
" 0 1 2 3 4 5 6 7 8 9 : ; < = > ?"
" @ A B C D E F G H I J K L M N O"
" P Q R S T U V W X Y Z [ \\ ] ^ _"
" ` a b c d e f g h i j k l m n o"
" p q r s t u v w x y z { | } ~del";
c = 3 * (c & 0177);
}
static void
{
}
static void
{
unsigned char* v;
char* s;
wchar_t w;
int i;
int j;
{
return;
}
switch (*u)
{
case 0:
return;
case '\\':
return;
}
buf[0] = *(v = u);
{
for (j = 3 - mbwidth(w); j > 0; j--)
while (i--)
return;
}
buf[1] = 0;
/*
* posix shalls are sometimes an impediment to progress
*/
if (*s != '\\')
{
return;
}
switch (*(s + 1))
{
case 'a':
case 'b':
case 'f':
case 'n':
case 'r':
case 't':
case 'v':
return;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
return;
}
}
static void
{
unsigned char* v;
char* s;
wchar_t w;
int i;
int j;
{
return;
}
switch (*u)
{
case 0:
return;
case '\\':
return;
}
buf[0] = *(v = u);
{
for (j = 3 - mbwidth(w); j > 0; j--)
while (i--)
return;
}
buf[1] = 0;
if (*s != '\\')
{
return;
}
if (isdigit(*(s + 1)))
{
return;
}
}
static void
{
register char* s;
{
case 0:
return;
case '\\':
return;
}
buf[1] = 0;
if (*s != '\\')
{
return;
}
if (isdigit(*(s + 1)))
else
{
}
}
static void
{
unsigned char* v;
char* s;
wchar_t w;
int i;
int j;
{
return;
}
switch (*u)
{
case 0:
return;
case '\\':
return;
}
buf[0] = *(v = u);
{
for (j = 3 - mbwidth(w); j > 0; j--)
while (i--)
return;
}
buf[1] = 0;
/*
* posix shalls are sometimes an impediment to progress
*/
if (*s != '\\')
{
return;
}
switch (*(s + 1))
{
case 'b':
case 'f':
case 'n':
case 'r':
case 't':
return;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
return;
}
}
{
{
},
{
"hexadecimal floating point",
'A', 0, 0, 0, asize, 0, 0, 0, 0, 0
},
{
"binary character",
},
{
"locale character or backslash escape (\\a \\b \\f \\n \\r \\t \\v)",
},
{
"locale character or backslash escape (current and future escapes)",
},
{
"signed decimal",
},
{
"floating point",
'f', 0, 0, 0, fsize, 0, 0, 0, 0, 0
},
{
"\b--map\b mapped character or hexadecimal value if not printable",
},
{
"octal",
},
{
"locale character or backslash escape (\\b \\f \\n \\r \\t)",
},
{
"unsigned decimal",
},
{
"hexadecimal",
},
{
"printable bytes",
'z', 0, 0, 0, 0, 1, 0, 0, 0, 0
},
};
static void
{
}
static void
{
}
static void
{
}
static void
{
}
static void
{
}
static void
{
}
static void
{
}
static void
{
}
static void
{
}
static void
{
}
#if _typ_long_double
static void
{
}
#endif
/*
* add format type t to the format list
*/
static void
{
register int c;
uintmax_t m;
int prec;
int base;
int n;
int i;
char* e;
char* s;
while (c = *t++)
{
if (isspace(c) || c == ',')
continue;
{
return;
}
{
{
case 1:
break;
}
continue;
}
xp = 0;
if (isdigit(*t))
{
c = 0;
t = e;
}
else
{
c = isupper(*t) ? *t++ : 0;
n = 0;
}
for (;;)
{
{
if (c)
{
return;
}
{
return;
}
break;
}
if (n)
{
break;
zp++;
}
{
if (c != *t)
break;
t++;
zp++;
break;
}
break;
else
zp++;
}
{
return;
}
else
{
{
}
else
}
else
{
if (n > 1 && (n & (n - 1)))
{
c = (1 << i) - n;
n = (1 << i) - (1 << (i - 1));
}
prec = 0;
base = 0;
}
{
*e++ = '%';
while (*e = *s++)
e++;
if (prec)
if (base)
while (*e = *s++)
e++;
{
#if _typ_long_double
else
#endif
else
}
{
case 1:
break;
case 2:
break;
case 4:
break;
default:
break;
}
else
{
case 1:
break;
case 2:
break;
case 4:
break;
default:
break;
}
}
}
}
static Sfio_t*
{
for (;;)
{
if (**p)
return 0;
{
}
{
continue;
}
{
{
{
goto next;
}
{
goto next;
}
}
else
{
for (;;)
{
{
goto next;
}
else
{
break;
}
}
}
}
break;
next:
}
return ip;
}
static int
{
register unsigned char* u;
register ssize_t z;
unsigned long n;
{
{
{
}
return 0;
}
}
{
{
else
}
u = (unsigned char*)bp;
for (;;)
{
while (z-- > 0)
else
{
{
register int c;
unsigned char* v;
wchar_t w;
{
{
}
{
}
else
{
c = '.';
}
}
else
{
c = '.';
}
}
break;
}
}
return -1;
}
return 0;
}
static int
{
register char* s;
register char* e;
register char* x;
register char* span = 0;
register int c;
size_t n;
size_t m;
ssize_t r;
return 0;
for (;;)
{
{
}
else
for (;;)
{
if (s)
break;
if (n)
{
s = 0;
n = 0;
break;
}
}
{
{
s = 0;
n = 0;
}
}
if (span)
{
if (s)
{
if (m > n)
{
span += n;
continue;
}
span += m;
s += m;
n -= m;
}
{
while (m--)
*span++ = 0;
}
goto bad;
{
while (r--)
*span++ = *x++;
goto respan;
}
span = 0;
if (s && !n)
continue;
}
if (!s)
break;
x = s + n;
{
n = 0;
for (;;)
{
if (s >= x || (c = *s++) == 0 || c == '\n' || !isprint(c))
{
{
break;
break;
}
if (s >= x)
break;
n = 0;
}
else
n++;
}
}
else
{
if (s < e)
{
do
{
goto bad;
{
}
}
if (n = x - s)
{
}
}
}
return 0;
bad:
return -1;
}
/*
* optinfo() size description
*/
static int
{
register int n;
else
return n;
}
/*
* optget() info discipline function
*/
static int
{
register int i;
register int n;
n = 0;
switch (*s)
{
case 'c':
break;
case 't':
for (i = 0; i < elementsof(type); i++)
break;
}
return n;
}
int
{
register int n;
register char* s;
char* e;
int per;
{
return 1;
}
per = 0;
for (;;)
{
{
case 'A':
continue;
case 'B':
else
continue;
case 'j':
{
break;
}
continue;
case 'm':
else
continue;
case 'N':
continue;
case 'p':
continue;
case 't':
continue;
case 'T':
switch (*s)
{
case 'b':
case 'm':
n = *s++;
{
goto done;
}
if (*e)
break;
case 'n':
break;
default:
break;
}
continue;
case 'v':
continue;
case 'w':
continue;
case 'z':
continue;
case 'a':
case 'b':
case 'c':
case 'C':
case 'd':
case 'D':
case 'f':
case 'F':
case 'h':
case 'i':
case 'l':
case 'o':
case 'O':
case 's':
case 'S':
case 'u':
case 'U':
case 'x':
case 'X':
s = buf;
{
case 'b':
*s++ = 'o';
*s++ = 'C';
break;
case 'c':
case 'C':
*s++ = 'O';
break;
case 'D':
n = 'U';
break;
case 'd':
n = 'u';
break;
case 'h':
n = 'x';
break;
case 'i':
case 's':
n = 'd';
break;
case 'l':
case 'S':
n = 'D';
break;
}
if (s == buf)
{
if (isupper(n))
switch (*s++ = tolower(n))
{
case 'f':
*s++ = 'D';
break;
default:
*s++ = 'L';
break;
}
else
switch (*s++ = n)
{
case 'd':
case 'o':
case 's':
case 'u':
case 'x':
/* pronounce that! */
*s++ = 'S';
break;
case 'f':
*s++ = 'F';
break;
}
}
*s = 0;
continue;
case ':':
continue;
case '?':
continue;
}
break;
}
if (error_info.errors)
{
case 'n':
break;
case 0:
n = 'o';
/*FALLTHROUGH*/
case 'o':
goto base;
case 'd':
goto base;
case 'x':
/*FALLTHROUGH*/
base:
break;
default:
break;
}
if (error_info.errors)
goto done;
n -= (BASE_WIDTH + 1);
n = 1;
{
}
if (per)
n = per;
{
goto done;
}
{
e = "?(+)+([0-9])?(.)?([bkm])?(ll|LL)";
if (!*(argv + 1))
{
if (strmatch(s, e) && *s == '+')
argv++;
else s = 0;
}
else if (!*(argv + 2))
{
s = *(argv + 1);
*(argv + 1) = 0;
else s = 0;
}
else s = 0;
if (s)
{
if (*e == '.')
e++;
switch (*e)
{
case 'b':
break;
case 'k':
break;
case 'm':
break;
}
}
}
#ifdef SIGFPE
#endif
#ifdef SIGFPE
#endif
{
goto done;
}
{
}
done:
return error_info.errors != 0;
}