1
0
Files
irix-657m-src/eoe/cmd/od/od.c
2022-09-29 17:59:04 +03:00

930 lines
18 KiB
C

/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
/* The copyright notice above does not evidence any */
/* actual or intended publication of such source code. */
/* Portions Copyright(c) 1988, Sun Microsystems Inc. */
/* All Rights Reserved */
#ident "$Revision: 1.15 $"
/*
* od -- octal (also hex, decimal, and character) dump
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <locale.h>
#include <pfmt.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <limits.h>
#include <assert.h>
#define BSIZE 512 /* standard buffer size */
#define KILO 1024
#define MEG 1048576
#define YES 1
#define NO 0
#define DBUFSIZE 16
#define LIST_INCR 32
struct dfmt {
char df_option; /* command line option */
int df_field; /* # of chars in a field */
int df_size; /* # of bytes displayed in a field */
int df_radix; /* conversion radix */
} **conv_vec;
unsigned int conv_vec_len;
unsigned int conv_vec_max;
unsigned int conv_vec_cur;
char **file_vec;
unsigned int file_vec_len;
unsigned int file_vec_max;
unsigned int file_vec_cur;
int file_vec_cur_opened = NO;
int file_vec_nul = YES;
/* The names of the structures are chosen for the options action
* e.g. u_s_oct - unsigned octal
* u_l_hex - unsigned long hex
*/
struct dfmt ncr = {'a', 3, sizeof(char), 8};
struct dfmt chr = {'c', 3, sizeof(char), 8};
struct dfmt dec_c = {'d', 4, sizeof(char), 10};
struct dfmt dec_s = {'d', 6, sizeof(short), 10};
struct dfmt dec_i = {'d', 11, sizeof(int), 10};
struct dfmt dec_l = {'d', 11, sizeof(long), 10};
struct dfmt flt_f = {'f', 14, sizeof(float), 10};
struct dfmt flt_d = {'f', 21, sizeof(double), 10};
struct dfmt flt_l = {'f', 21, sizeof(long double), 10};
struct dfmt oct_c = {'o', 3, sizeof(char), 8};
struct dfmt oct_s = {'o', 6, sizeof(short), 8};
struct dfmt oct_i = {'o', 11, sizeof(int), 8};
struct dfmt oct_l = {'o', 11, sizeof(long), 8};
struct dfmt udc_c = {'u', 3, sizeof(char), 10};
struct dfmt udc_s = {'u', 5, sizeof(short), 10};
struct dfmt udc_i = {'u', 10, sizeof(int), 10};
struct dfmt udc_l = {'u', 10, sizeof(long), 10};
struct dfmt hex_c = {'x', 2, sizeof(char), 16};
struct dfmt hex_s = {'x', 4, sizeof(short), 16};
struct dfmt hex_i = {'x', 8, sizeof(int), 16};
struct dfmt hex_l = {'x', 8, sizeof(long), 16};
#define PRINT_FMT_FLT "%14.7e"
#define PRINT_FMT_DBL "%21.14e"
#define PRINT_FMT_LDB "%21.14e"
char word[DBUFSIZE];
char lastword[DBUFSIZE];
int base = 010;
int max;
off64_t addr;
off64_t count;
int count_limit = 0;
int display=7;
char *opt_A_args[] = {
"d",
"o",
"x",
"n",
NULL
};
int opt_A_conv[] = { 10, 8, 16, -1 };
#define NAMED_CHARS_FIRST 0
#define NAMED_CHARS_LAST 040
#define NAMED_CHARS_OTHER_DEL 0177
#define NAMED_CHARS_OTHER_DEL_NAME "del"
char *named_chars[NAMED_CHARS_LAST-NAMED_CHARS_FIRST+1] = {
"nul", "soh", "stx", "etx",
"eot", "enq", "ack", "bel",
" bs", " ht", " nl", " vt",
" ff", " cr", " so", " si",
"dle", "dc1", "dc2", "dc3",
"dc4", "nak", "syn", "etb",
"can", " em", "sub", "esc",
" fs", " gs", " rs", " us",
" sp"
};
void line (off64_t a, char w[], int n);
int putx (char n[], struct dfmt *c);
void cput (int c);
void aput (int c);
void putn (unsigned long long n, unsigned int b, unsigned int c);
void pre (int f, int n);
void offset (char *s);
u_long string_to_ul (const char *str);
int file_vec_read (char *buf, off64_t max);
int file_vec_skip (off64_t skip);
void conv_add (struct dfmt *conv);
void conv_parse (char *arg);
char inputerror[] = "uxsgicore:5:Input error: %s (%s)\n";
void
usage()
{
pfmt(stderr, MM_ACTION,
":27:Usage:\tod [-bcdDfFhoOsSvxX] [file] [[+]offset[.][b]]\n\tod [-v] [-A addr_base] [-j skip] [-N count] [-t type_str] ... [file...]\n");
exit(1);
}
int
main(int argc, char **argv)
{
register char *p;
register n, f, same;
int showall = NO;
int opt;
char *sub_opt;
char *sub_val;
struct stat stat_buf;
int num_operands;
int new_options = NO;
char *loc;
(void)setlocale(LC_ALL, "");
(void)setcat("uxdfm");
(void)setlabel("UX:od");
#ifdef STANDALONE
if (argv[0][0] == '\0')
argc = getargv("od", &argv, 0);
#endif
conv_vec_max = LIST_INCR;
conv_vec_len = 0;
conv_vec_cur = 0;
if (!(conv_vec = (struct dfmt **)
malloc(conv_vec_max * sizeof(struct dfmt *)))) {
pfmt(stderr, MM_ERROR, ":3:Out of memory\n");
exit(2);
}
file_vec_max = LIST_INCR;
file_vec_len = 0;
file_vec_cur = 0;
if (!(file_vec = (char **) malloc(file_vec_max * sizeof(char *)))) {
pfmt(stderr, MM_ERROR, ":3:Out of memory\n");
exit(2);
}
while ((opt = getopt(argc, argv, "A:j:n:N:t:odsxhcbDfFOSXv")) != -1) {
switch(opt) {
case 'A':
sub_opt = optarg;
base = getsubopt(&sub_opt, opt_A_args, &sub_val);
if (base < 0 ||
getsubopt(&sub_opt, opt_A_args, &sub_val) >= 0)
usage();
base = opt_A_conv[base];
new_options = YES;
break;
case 'j':
addr = string_to_ul(optarg);
new_options = YES;
break;
case 'n':
case 'N':
count = string_to_ul(optarg);
count_limit = 1;
new_options = YES;
break;
case 't':
conv_parse(optarg);
new_options = YES;
break;
case 'o':
conv_add(&oct_s);
break;
case 'd':
conv_add(&udc_s);
break;
case 's':
conv_add(&dec_s);
break;
case 'x':
case 'h':
conv_add(&hex_s);
break;
case 'c':
conv_add(&chr);
break;
case 'b':
conv_add(&oct_c);
break;
case 'D':
conv_add(&udc_l);
break;
case 'f':
conv_add(&flt_f);
break;
case 'F':
conv_add(&flt_d);
break;
case 'O':
conv_add(&oct_l);
break;
case 'S':
conv_add(&dec_l);
break;
case 'X':
conv_add(&hex_l);
break;
case 'v':
showall = YES;
break;
default :
usage ();
}
}
if (conv_vec_len == 0) {
conv_add(&oct_s);
}
/* Calucate max number chars in line */
max = 0;
for (conv_vec_cur = 0; conv_vec_cur < conv_vec_len; conv_vec_cur++) {
f = (conv_vec[conv_vec_cur]->df_field + 1) *
(DBUFSIZE / conv_vec[conv_vec_cur]->df_size);
if (f > max)
max = f;
}
argc -= optind -1;
argv += optind;
/* parse multiple files to dump and remember them */
num_operands = argc - 1;
for (file_vec_len = 0; argc > 1; argc--, argv++) {
if (!new_options) {
if (**argv == '+') {
offset(*argv);
continue;
}
/* backward compatibility hack more or less
accepted by xpg4 */
if (num_operands == 2 && file_vec_len == 1) {
if ((isdigit(**argv)) ||
(**argv == 'x') || (**argv == '.') ||
(**argv == 'b') || (**argv == 'B') ||
(**argv == 'l' && **(argv+1) == 'l' &&
**(argv+2) == '\0') ||
(**argv == 'L' && **(argv+1) == 'L' &&
**(argv+2) == '\0')) {
offset(*argv);
continue;
}
}
}
if (stat(*argv, &stat_buf) == -1) {
pfmt(stderr, MM_ERROR,
":3:Cannot open %s: %s\n",
*argv, strerror(errno));
exit(2);
}
else {
if (file_vec_len == file_vec_max) {
file_vec_max += LIST_INCR;
file_vec = realloc(file_vec,
file_vec_max*sizeof(char *));
if (!file_vec) {
pfmt(stderr, MM_ERROR,
":3:Out of memory\n");
exit(2);
}
}
file_vec[file_vec_len++] = *argv;
file_vec_nul = NO;
}
}
/* skip -j xxx bytes if needed */
if (addr > 0) {
if (file_vec_skip(addr) != addr) {
pfmt(stderr, MM_ERROR, ":3:Unable to skip %d\n", addr);
exit(2);
}
}
for (same = -1; ; addr += n, count -= n) {
if (count_limit && count <= 0) break;
/* read from list of files */
n = file_vec_read(word, (sizeof(word)<count || !count_limit) ?
sizeof(word) : count);
if (n <= 0) break;
if (same>=0 && !showall) {
for (f=0; f<DBUFSIZE; f++)
if (lastword[f] != word[f])
goto notsame;
if (same==0) {
printf("*\n");
same = 1;
}
continue;
}
notsame:
line(addr, word, (n+sizeof(word[0])-1)/sizeof(word[0]));
same = 0;
for (f=0; f<DBUFSIZE; f++)
lastword[f] = word[f];
for (f=0; f<DBUFSIZE; f++)
word[f] = 0;
}
if (ferror(stdin)) {
pfmt(stderr, MM_ERROR, inputerror, strerror(errno),
(file_vec_nul && file_vec_cur_opened) ?
"stdin" : file_vec[file_vec_cur-1]);
exit (2);
}
if (base > 0)
putn(addr, base, display);
putchar('\n');
/* buffering from stdio screwed this up, set it back now */
if (file_vec_nul)
lseek64(0, ftell(stdin), SEEK_SET);
exit(0);
}
void
line(off64_t a, char w[], int n)
{
register i, f;
f = 1;
for (conv_vec_cur = 0; conv_vec_cur < conv_vec_len; conv_vec_cur++) {
if (base > 0) {
if(f) {
putn(a, base, display);
f = 0;
} else
putchar('\t');
}
i = 0;
while (i<n) {
i += putx(w+i, conv_vec[conv_vec_cur]);
}
putchar('\n');
}
}
int
putx(char n[], struct dfmt *c)
{
int ret = 0;
long long val;
switch(c->df_option) {
case 'a':
pre(c->df_field, c->df_size);
aput(*n);
return c->df_size;
case 'c':
pre(c->df_field, c->df_size);
cput(*n);
return c->df_size;
case 'f':
pre(c->df_field, c->df_size);
if (c->df_size == sizeof(float)) {
float *fn = (float *)n;
printf(PRINT_FMT_FLT,*fn);
}
else if (c->df_size == sizeof(double)) {
double dn;
memcpy(&dn, n, sizeof(dn));
printf(PRINT_FMT_DBL,dn);
}
else if (c->df_size == sizeof(long double)) {
long double ldn;
memcpy(&ldn, n, sizeof(ldn));
printf(PRINT_FMT_LDB, ldn);
}
else
assert(0);
return c->df_size;
case 'o':
case 'u':
case 'x':
pre(c->df_field, c->df_size);
if (c->df_size == sizeof(char)) {
unsigned char *cn = (unsigned char *)n;
putn((long long)*cn, c->df_radix, c->df_field);
}
else if (c->df_size == sizeof(short)) {
unsigned short *sn = (unsigned short *)n;
putn((long long)*sn, c->df_radix, c->df_field);
}
else if (c->df_size == sizeof(int)) {
unsigned int *in = (unsigned int *)n;
putn((long long)*in, c->df_radix, c->df_field);
}
else if (c->df_size == sizeof(long)) {
unsigned long *ln = (unsigned long *)n;
putn((long long)*ln, c->df_radix, c->df_field);
}
else
assert(0);
return c->df_size;
case 'd':
putchar(' ');
if (c->df_size == sizeof(char)) {
unsigned char *uc = (unsigned char *)n;
if (*uc > CHAR_MAX) {
pre(c->df_field, c->df_size);
putchar('-');
*uc = (~(*uc) + 1) & UCHAR_MAX;
}
else
pre(c->df_field-1, c->df_size);
putn((long long)*uc, c->df_radix, c->df_field-1);
}
else if (c->df_size == sizeof(short)) {
unsigned short *us = (unsigned short *)n;
if (*us > SHRT_MAX) {
pre(c->df_field, c->df_size);
putchar('-');
*us = (~(*us) + 1) & USHRT_MAX;
}
else
pre(c->df_field-1, c->df_size);
putn((long long)*us, c->df_radix, c->df_field-1);
}
else if (c->df_size == sizeof(int)) {
unsigned int *ui = (unsigned int *)n;
if (*ui > INT_MAX) {
pre(c->df_field, c->df_size);
putchar('-');
*ui = (~(*ui) + 1) & UINT_MAX;
}
else
pre(c->df_field-1, c->df_size);
putn((long long)*ui, c->df_radix, c->df_field-1);
}
else if (c->df_size == sizeof(long)) {
unsigned long *ul = (unsigned long *)n;
if (*ul > LONG_MAX) {
pre(c->df_field, c->df_size);
putchar('-');
*ul = (~(*ul) + 1) & ULONG_MAX;
}
else
pre(c->df_field-1, c->df_size);
putn((long long)*ul, c->df_radix, c->df_field-1);
}
else
assert(0);
return c->df_size;
}
assert( 0 ); /* never reached */
return 0;
}
void
cput(int c)
{
c &= 0377;
if(c >= 0200 && MB_CUR_MAX > 1)
putn((long long)c,8,3); /* Multi Envir. with Multi byte char */
else{
if(isprint(c)) {
printf(" ");
putchar(c);
return;
}
switch(c) {
case '\0':
printf(" \\0");
break;
case '\a':
printf(" \\a");
break;
case '\b':
printf(" \\b");
break;
case '\f':
printf(" \\f");
break;
case '\n':
printf(" \\n");
break;
case '\r':
printf(" \\r");
break;
case '\t':
printf(" \\t");
break;
case '\v':
printf(" \\v");
break;
default:
putn((long long)c, 8, 3);
}
}
}
void
aput(int c)
{
c &= 0377;
if (c >= NAMED_CHARS_FIRST && c <= NAMED_CHARS_LAST) {
printf("%s", named_chars[c]);
}
else if (c == NAMED_CHARS_OTHER_DEL) {
printf(NAMED_CHARS_OTHER_DEL_NAME);
}
else if (isprint(c)){
printf(" ");
putchar(c);
return;
}
else {
putn((long long)c, 8, 3);
}
}
void
putn(unsigned long long n, unsigned int b, unsigned int c)
{
register unsigned long long d;
if(!c)
return;
putn(n/b, b, c-1);
d = n%b;
if (d > 9)
putchar(d-10+'a');
else
putchar(d+'0');
}
void
pre(int f, int n)
{
int i,m;
m = (max/(DBUFSIZE/n)) - f;
for(i=0; i<m; i++)
putchar(' ');
}
void
offset(char *s)
{
register char *p;
off64_t a;
register int d;
if (*s=='+')
s++;
if (*s=='x') {
s++;
base = 16;
} else if (*s=='0' && s[1]=='x') {
s += 2;
base = 16;
} else if (*s == '0')
base = 8;
p = s;
while(*p) {
if (*p++=='.')
base = 10;
}
for (a=0; *s; s++) {
d = *s;
if(d>='0' && d<='9')
a = a*base + d - '0';
else if (d>='a' && d<='f' && base==16)
a = a*base + d + 10 - 'a';
else
break;
}
if (*s == '.')
s++;
if(*s=='b' || *s=='B'){
a *= BSIZE;
s++;
}
if(*s=='l'|| *s=='L'){
s++;
if(*s=='l' || *s=='L')
display=15;
}
addr = a;
}
u_long
string_to_ul(const char *str)
{
char *token;
unsigned long num;
errno = 0;
num = strtoul(str, &token, 0);
if (errno)
usage();
if (token) {
switch(*token) {
case 'b':
num *= BSIZE;
break;
case 'k':
num *= KILO;
break;
case 'm':
num *= MEG;
break;
default:
if (!(isspace(*token) || *token == '\0'))
usage();
}
}
return num;
}
int
file_vec_read(char *buf, off64_t max)
{
off64_t num = 0;
off64_t left = max;
off64_t n;
while (num != max) {
if (!file_vec_cur_opened) {
if ((!file_vec_nul && file_vec_cur == file_vec_len) ||
(file_vec_nul && file_vec_cur == 1))
break;
if (!file_vec_nul &&
freopen(file_vec[file_vec_cur],"r",stdin) == NULL) {
pfmt(stderr, MM_ERROR,
":3:Cannot open %s: %s\n",
file_vec[file_vec_cur],
strerror(errno));
exit(2);
}
file_vec_cur_opened = YES;
file_vec_cur++;
}
if ((n = fread(buf+num, 1, left, stdin)) <= 0) {
if (ferror(stdin))
break;
if (!file_vec_nul) fclose(stdin);
file_vec_cur_opened = NO;
}
else {
num += n;
left -= n;
}
}
return num;
}
int
file_vec_skip(off64_t skip)
{
off64_t num = 0;
off64_t left = skip;
off64_t n;
struct stat stat_buf;
while (num != skip) {
if (!file_vec_cur_opened) {
if ((!file_vec_nul && file_vec_cur == file_vec_len) ||
(file_vec_nul && file_vec_cur == 1))
break;
if (!file_vec_nul &&
freopen(file_vec[file_vec_cur],"r",stdin) == NULL) {
pfmt(stderr, MM_ERROR,
":3:Cannot open %s: %s\n",
file_vec[file_vec_cur],
strerror(errno));
exit(2);
}
/* else, simply use stdin */
if (fstat(0, &stat_buf) < 0) {
pfmt(stderr, MM_ERROR,
":3:Cannot stat %s: %s\n",
file_vec[file_vec_cur],
strerror(errno));
exit(2);
}
file_vec_cur_opened = YES;
file_vec_cur++;
if (stat_buf.st_mode == S_IFREG) {
if (left > stat_buf.st_size){
num += stat_buf.st_size;
left -= stat_buf.st_size;
if (!file_vec_nul) fclose(stdin);
file_vec_cur_opened = NO;
continue;
}
else {
fseek64(stdin, left, 0);
num += left;
left = 0;
continue;
}
}
}
if (getchar() != EOF) {
num++;
left--;
}
else{
if (!file_vec_nul) fclose(stdin);
file_vec_cur_opened = NO;
}
}
return num;
}
void
conv_add(struct dfmt *conv)
{
if (conv_vec_len == conv_vec_max) {
conv_vec_max += LIST_INCR;
conv_vec = (struct dfmt **) realloc(conv_vec,
conv_vec_max*sizeof(struct dfmt *));
if (!conv_vec) {
pfmt(stderr, MM_ERROR, ":3:Out of memory\n");
exit(2);
}
}
conv_vec[conv_vec_len++] = conv;
}
void
conv_parse(char *arg)
{
char *c;
for (c = arg; *c != '\0'; c++) {
switch(*c) {
/* num : d f o u x
F D L : f
CSIL : d o u x
*/
case 'a':
conv_add(&ncr);
break;
case 'c':
conv_add(&chr);
break;
case 'f':
c++;
if (*c == 'L' || *c == sizeof(long double) + '0')
conv_add(&flt_l);
else if (*c == 'F' || *c == sizeof(float) + '0')
conv_add(&flt_f);
else {
if (*c != 'D' && *c != sizeof(double)+'0') c--;
conv_add(&flt_d);
}
break;
case 'd':
c++;
if (*c == 'C' || *c == sizeof(char) + '0')
conv_add(&dec_c);
else if (*c == 'S' || *c == sizeof(short) +'0')
conv_add(&dec_s);
else if (*c == 'L' || *c == sizeof(long) + '0')
conv_add(&dec_l);
else {
if (*c != 'I' && *c != sizeof(int) + '0') c--;
conv_add(&dec_i);
}
break;
case 'o':
c++;
if (*c == 'C' || *c == sizeof(char) + '0')
conv_add(&oct_c);
else if (*c == 'S' || *c == sizeof(short) +'0')
conv_add(&oct_s);
else if (*c == 'L' || *c == sizeof(long) + '0')
conv_add(&oct_l);
else {
if (*c != 'I' && *c != sizeof(int) + '0') c--;
conv_add(&oct_i);
}
break;
case 'u':
c++;
if (*c == 'C' || *c == sizeof(char) + '0')
conv_add(&udc_c);
else if (*c == 'S' || *c == sizeof(short) +'0')
conv_add(&udc_s);
else if (*c == 'L' || *c == sizeof(long) + '0')
conv_add(&udc_l);
else {
if (*c != 'I' && *c != sizeof(int) + '0') c--;
conv_add(&udc_i);
}
break;
case 'x':
c++;
if (*c == 'C' || *c == sizeof(char) + '0')
conv_add(&hex_c);
else if (*c == 'S' || *c == sizeof(short) +'0')
conv_add(&hex_s);
else if (*c == 'L' || *c == sizeof(long) + '0')
conv_add(&hex_l);
else {
if (*c != 'I' && *c != sizeof(int) + '0') c--;
conv_add(&hex_i);
}
break;
default:
usage();
}
}
}