1413 lines
48 KiB
C
1413 lines
48 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
hd.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the functions that implement the hd program.
|
||
This program displays the contents of files in decimal, hexadecimal
|
||
and character formats. The contents of the files are displayed in
|
||
records of 16 bytes each. Associated to each record, there is an
|
||
address that represents the offset of the first byte in the
|
||
record relative to the begining of the file. Each record can also be
|
||
displayed as printable ASCII characters.
|
||
hd can be called with the following arguments:
|
||
|
||
-ad: displays the address of each record in decimal;
|
||
-ax: displays the address of each record in hex;
|
||
-ch: displays bytes as ASCII characters;
|
||
-cC: displays bytes as ASCII C characters (\n, \t, etc);
|
||
-ce: displays bytes as ASCII codes (EOT, CR, SOH, etc);
|
||
-cr: displays bytes as ASCII control characters (^A, ^N, etc);
|
||
-bd: interprets data in each record as byte, and displays
|
||
each byte as a decimal number;
|
||
-bx: interprets data in each record as byte, and displays
|
||
each byte as an hex number;
|
||
-wd: interprets data in each record as word, and displays
|
||
each word as a decimal number;
|
||
-wx: interprets data in each record as word, and displays
|
||
each word as an hex number;
|
||
-ld: interprets data in each record as double words, and displays
|
||
each double word as a decimal number;
|
||
-wx: interprets data in each record as a double word, and displays
|
||
each double word as an hex number;
|
||
-A: Displays data in each record also as printable ASCII
|
||
characters at the end of each line.
|
||
-s <offset>: defines the offset of the first byte to be displayed;
|
||
-n <bumber>: defines the number of bytes to be displayed;
|
||
-i does not print redundant lines;
|
||
-?, -h or -H: displays a help message.
|
||
|
||
If no argument is defined, hd assumes as default: -ax -A -bx
|
||
|
||
|
||
Authors:
|
||
|
||
Jaime F. Sasson (jaimes) 12-Nov-1990
|
||
David J. Gilman (davegi) 12-Nov-1990
|
||
|
||
Environment:
|
||
|
||
C run time library
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
|
||
|
||
#include <stdio.h>
|
||
#include <assert.h>
|
||
#include <ctype.h>
|
||
#include <conio.h>
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
#include "hd.h"
|
||
|
||
#define FALSE 0
|
||
|
||
|
||
/*************************************************************************
|
||
*
|
||
* G L O B A L V A R I A B L E S
|
||
*
|
||
*************************************************************************/
|
||
|
||
|
||
unsigned long Offset = 0; // -s option
|
||
unsigned Count = 0; // -n option
|
||
BASE AddrFormat; // -a option
|
||
FORMAT DispFormat; // -c, -b, -w or -l options
|
||
YESNO DumpAscii; // -A option
|
||
int IgnoreRedundantLines; // -i option
|
||
|
||
unsigned char auchBuffer[BUFFER_SIZE]; // Buffer that contains data read
|
||
// from the file being displayed
|
||
|
||
unsigned long cbBytesInBuffer; // Total number of bytes in the
|
||
// buffer
|
||
|
||
unsigned char* puchPointer; // Points to the next character in
|
||
// the buffer to be read
|
||
|
||
unsigned long cStringSize; // Size of a string pointed by a
|
||
// pointer in the ASCII table used
|
||
// for the translation (asciiChar,
|
||
// asciiC, asciiCode or asciiCtrl)
|
||
// The contents of this variable is
|
||
// meaningful only if -ch, -cC, -ce
|
||
// or -cr was specified.
|
||
// It is meaningless in all other
|
||
// cases (no ascii translation is
|
||
// being performed, and the ascii
|
||
// tables are not needed)
|
||
|
||
|
||
/*************************************************************************
|
||
*
|
||
* A S C I I C O N V E R S I O N T A B L E S
|
||
*
|
||
*************************************************************************/
|
||
|
||
|
||
char* asciiChar[ ] = {
|
||
" ", " ", " ", " ", " ", " ", " ", " ",
|
||
" ", " ", " ", " ", " ", " ", " ", " ",
|
||
" ", " ", " ", " ", " ", " ", " ", " ",
|
||
" ", " ", " ", " ", " ", " ", " ", " ",
|
||
" ", "! ", "\" ", "# ", "$ ", "% ", "& ", "' ",
|
||
"( ", ") ", "* ", "+ ", "' ", "- ", ". ", "/ ",
|
||
"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 ", "{ ", "| ", "} ", "~ ", "_ ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", " "
|
||
};
|
||
|
||
|
||
|
||
char* asciiC[ ] = {
|
||
" ", " ", " ", " ", " ", " ", " ", "\\a ",
|
||
"\\b ", "\\t ", "\\n ", "\\v ", "\\f ", " ", " ", " ",
|
||
" ", " ", " ", " ", " ", " ", " ", " ",
|
||
" ", " ", " ", " ", " ", " ", " ", " ",
|
||
" ", "! ", "\\\" ", "# ", "$ ", "% ", "& ", "\' ",
|
||
"( ", ") ", "* ", "+ ", "' ", "- ", ". ", "/ ",
|
||
"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 ", "{ ", "| ", "} ", "~ ", "_ ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", " "
|
||
};
|
||
|
||
|
||
|
||
char* asciiCode[ ] = {
|
||
"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
|
||
"BS ", "HT ", "LF ", "VT ", "FF ", "CR ", "SO ", "SI ",
|
||
"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
|
||
"CAN", "EM ", "SUB", "ESC", "FS ", "GS ", "RS ", "US ",
|
||
" ", "! ", "\" ", "# ", "$ ", "% ", "& ", "' ",
|
||
"( ", ") ", "* ", "+ ", "' ", "- ", ". ", "/ ",
|
||
"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 ", "{ ", "| ", "} ", "~ ", "_ ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", " "
|
||
};
|
||
|
||
|
||
char* asciiCtrl[ ] = {
|
||
"^@ ", "^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 ", "^[ ", "^\\ ", "^] ", "^^ ", "^_ ",
|
||
" ", "! ", "\" ", "# ", "$ ", "% ", "& ", "' ",
|
||
"( ", ") ", "* ", "+ ", "' ", "- ", ". ", "/ ",
|
||
"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 ", "{ ", "| ", "} ", "~ ", "_ ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ",
|
||
"<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", "<EFBFBD> ", " "
|
||
};
|
||
|
||
|
||
|
||
|
||
void
|
||
ConvertASCII (
|
||
char line[],
|
||
unsigned char buf[],
|
||
unsigned long cb,
|
||
char* pTable[]
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine converts the bytes received in a buffer
|
||
into an ASCII representation (Char, C, Code or CTRL).
|
||
|
||
|
||
Arguments:
|
||
|
||
line - Buffer that will receive the converted characters.
|
||
|
||
buf - A buffer that contains the data to be converted.
|
||
|
||
cb - Number of bytes in the buffer
|
||
|
||
pTable - Pointer to the table to be used in the conversion
|
||
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
|
||
{
|
||
unsigned long ulIndex;
|
||
|
||
sprintf( line,
|
||
MSG_DATA_ASCII_FMT,
|
||
pTable[ buf[ 0 ]], pTable[ buf[ 1 ]],
|
||
pTable[ buf[ 2 ]], pTable[ buf[ 3 ]],
|
||
pTable[ buf[ 4 ]], pTable[ buf[ 5 ]],
|
||
pTable[ buf[ 6 ]], pTable[ buf[ 7 ]],
|
||
pTable[ buf[ 8 ]], pTable[ buf[ 9 ]],
|
||
pTable[ buf[ 10 ]], pTable[ buf[ 11 ]],
|
||
pTable[ buf[ 12 ]], pTable[ buf[ 13 ]],
|
||
pTable[ buf[ 14 ]], pTable[ buf[ 15 ]]);
|
||
//
|
||
// If the number of bytes in the buffer is less than the maximum size
|
||
// of the record, then delete the characters that were converted
|
||
// but are not to be displayed.
|
||
//
|
||
if (cb < RECORD_SIZE) {
|
||
//
|
||
// -1: to eliminate the \0
|
||
// +1: to count the SPACE character between two strings
|
||
//
|
||
ulIndex = (sizeof( MSG_ADDR_FIELD ) - 1 ) + cb*(cStringSize + 1);
|
||
while ( line[ ulIndex ] != NUL ) {
|
||
line[ ulIndex ] = SPACE;
|
||
ulIndex++;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
void
|
||
ConvertBYTE (
|
||
char line[],
|
||
unsigned char buf[],
|
||
unsigned long cb,
|
||
unsigned long ulBase
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine converts each byte received in a buffer
|
||
into a number. The base used in the conversion is received as
|
||
parameter.
|
||
|
||
|
||
|
||
Arguments:
|
||
|
||
line - Buffer that will receive the converted characters.
|
||
|
||
buf - A buffer that contains the data to be converted.
|
||
|
||
cb - Number of bytes in the buffer
|
||
|
||
ulBase - Defines the base to be used in the conversion
|
||
|
||
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
|
||
{
|
||
unsigned long ulIndex;
|
||
char* pchMsg;
|
||
unsigned long ulNumberOfDigits;
|
||
|
||
switch( ulBase ) {
|
||
|
||
case DEC:
|
||
ulNumberOfDigits = 3; // needs 3 decimal digits to
|
||
// represent a byte
|
||
pchMsg = MSG_DATA_BYTE_DEC_FMT; // message that contains the format
|
||
break;
|
||
|
||
case HEX:
|
||
ulNumberOfDigits = 2; // needs 2 hexdigits to
|
||
// represent a byte
|
||
pchMsg = MSG_DATA_BYTE_HEX_FMT; // message that contains the format
|
||
break;
|
||
|
||
default:
|
||
printf( "Unknown base\n" );
|
||
assert( FALSE );
|
||
break;
|
||
}
|
||
|
||
sprintf( line,
|
||
pchMsg,
|
||
buf[ 0 ], buf[ 1 ],
|
||
buf[ 2 ], buf[ 3 ],
|
||
buf[ 4 ], buf[ 5 ],
|
||
buf[ 6 ], buf[ 7 ],
|
||
buf[ 8 ], buf[ 9 ],
|
||
buf[ 10 ], buf[ 11 ],
|
||
buf[ 12 ], buf[ 13 ],
|
||
buf[ 14 ], buf[ 15 ]);
|
||
//
|
||
// If this is the last record to be displayed, then delete the
|
||
// characters that were translated but are not to be displayed.
|
||
//
|
||
if (cb < RECORD_SIZE) {
|
||
ulIndex = (sizeof( MSG_ADDR_FIELD ) - 1 ) +
|
||
cb*(ulNumberOfDigits + 1 );
|
||
while ( line[ ulIndex ] != NUL ) {
|
||
line[ ulIndex ] = SPACE;
|
||
ulIndex++;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
void
|
||
ConvertWORD (
|
||
char line[],
|
||
unsigned char buf[],
|
||
unsigned long cb,
|
||
unsigned long ulBase
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine converts the data received in a buffer
|
||
into numbers. The data in the buffer are interpreted as words.
|
||
If the buffer contains an odd number of bytes, then the last byte
|
||
is converted as a byte, not as word.
|
||
The base used in the conversion is received as parameter.
|
||
|
||
|
||
|
||
Arguments:
|
||
|
||
line - Buffer that will receive the converted characters.
|
||
|
||
buf - A buffer that contains the data to be converted.
|
||
|
||
cb - Number of bytes in the buffer
|
||
|
||
ulBase - Defines the base to be used in the conversion
|
||
|
||
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
|
||
{
|
||
unsigned long ulIndex;
|
||
char* pchMsg;
|
||
char* pchMsgHalf;
|
||
unsigned long ulNumberOfDigits;
|
||
|
||
switch( ulBase ) {
|
||
|
||
case DEC:
|
||
ulNumberOfDigits = 5; // needs 5 decimal digits to
|
||
// represent a word
|
||
pchMsg = MSG_DATA_WORD_DEC_FMT; // message with the string
|
||
// format
|
||
pchMsgHalf = MSG_SINGLE_BYTE_DEC_FMT; // message with the format of
|
||
break; // half a word in decimal
|
||
|
||
case HEX:
|
||
ulNumberOfDigits = 4; // needs 4 hex digits to
|
||
// represent a word
|
||
pchMsg = MSG_DATA_WORD_HEX_FMT; // message the string format
|
||
pchMsgHalf = MSG_SINGLE_BYTE_HEX_FMT; // message with the format of
|
||
// half a word in hex
|
||
break;
|
||
|
||
default:
|
||
printf( "Unknown base\n" );
|
||
assert( FALSE );
|
||
break;
|
||
}
|
||
|
||
sprintf( line,
|
||
pchMsg,
|
||
(( unsigned short* ) ( buf )) [ 0 ],
|
||
(( unsigned short* ) ( buf )) [ 1 ],
|
||
(( unsigned short* ) ( buf )) [ 2 ],
|
||
(( unsigned short* ) ( buf )) [ 3 ],
|
||
(( unsigned short* ) ( buf )) [ 4 ],
|
||
(( unsigned short* ) ( buf )) [ 5 ],
|
||
(( unsigned short* ) ( buf )) [ 6 ],
|
||
(( unsigned short* ) ( buf )) [ 7 ]);
|
||
//
|
||
// If this record contains less bytes than the maximum record size,
|
||
// then it is the last record to be displayed. In this case we have
|
||
// to verify if the record contains an even number of bytes. If it
|
||
// doesn't, then the last byte must be interpreted as a byte and not
|
||
// as a word.
|
||
// Also, the characters that were converted but are not to be displayed,
|
||
// have to be deleted.
|
||
//
|
||
if (cb < RECORD_SIZE) {
|
||
ulIndex = (sizeof( MSG_ADDR_FIELD ) - 1 ) +
|
||
(cb/2)*(ulNumberOfDigits + 1 );
|
||
if (cb%2 != 0) {
|
||
ulIndex += sprintf( line + ulIndex,
|
||
pchMsgHalf,
|
||
buf[ cb-1 ]);
|
||
line[ ulIndex ] = SPACE;
|
||
}
|
||
//
|
||
// Delete characters that are not to be displayed
|
||
//
|
||
while ( line[ ulIndex ] != NUL ) {
|
||
line[ ulIndex ] = SPACE;
|
||
ulIndex++;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
void
|
||
ConvertDWORD (
|
||
char line[],
|
||
unsigned char buf[],
|
||
unsigned long cb,
|
||
unsigned long ulBase
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine converts the data received in a buffer
|
||
into numbers. The data in the buffer is interpreted as double words.
|
||
If the buffer contains less bytes than the maximum size of the record,
|
||
then it is the last record, and we may need to convert again the last
|
||
3 bytes in the buffer.
|
||
If the number of bytes in the buffer is not multiple of 4, then the
|
||
last bytes in the buffer are converted as a byte, word, or word and
|
||
byte, as appropriate.
|
||
The characters that were converted but are not to be displayed have to
|
||
be removed from the buffer.
|
||
The base used in the conversion is received as parameter.
|
||
|
||
|
||
|
||
Arguments:
|
||
|
||
line - Buffer that will receive the converted characters.
|
||
|
||
buf - A buffer that contains the data to be converted.
|
||
|
||
cb - Number of bytes in the buffer
|
||
|
||
ulBase - Defines the base to be used in the conversion
|
||
|
||
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
|
||
{
|
||
unsigned long ulIndex;
|
||
char* pchMsg;
|
||
char* pchMsgByte;
|
||
char* pchMsgWord;
|
||
char* pchMsgWordByte;
|
||
unsigned long ulNumberOfDigits;
|
||
|
||
switch( ulBase ) {
|
||
|
||
case DEC:
|
||
ulNumberOfDigits = 10; // needs 10 decimal digits to
|
||
// represent a dword
|
||
pchMsg = MSG_DATA_DWORD_DEC_FMT; // message with the string
|
||
// format
|
||
pchMsgByte = MSG_SINGLE_BYTE_DEC_FMT; // message with the format
|
||
// of a single byte in
|
||
// decimal
|
||
pchMsgWord = MSG_SINGLE_WORD_DEC_FMT; // message that contains
|
||
// the format of a single
|
||
// word in decimal
|
||
pchMsgWordByte = MSG_WORD_BYTE_DEC_FMT;
|
||
break;
|
||
|
||
case HEX:
|
||
ulNumberOfDigits = 8; // needs 8 hex digits to
|
||
// represent a dword
|
||
pchMsg = MSG_DATA_DWORD_HEX_FMT; // message the string format
|
||
pchMsgByte = MSG_SINGLE_BYTE_HEX_FMT; // message with the format
|
||
// of a single byte in hex
|
||
pchMsgWord = MSG_SINGLE_WORD_HEX_FMT; // message with the format
|
||
// of a single word in hex
|
||
pchMsgWordByte = MSG_WORD_BYTE_HEX_FMT;
|
||
break;
|
||
|
||
default:
|
||
printf( "Unknown base\n" );
|
||
assert( FALSE );
|
||
break;
|
||
}
|
||
|
||
sprintf( line,
|
||
pchMsg,
|
||
(( unsigned long* ) ( buf )) [ 0 ],
|
||
(( unsigned long* ) ( buf )) [ 1 ],
|
||
(( unsigned long* ) ( buf )) [ 2 ],
|
||
(( unsigned long* ) ( buf )) [ 3 ]);
|
||
//
|
||
// If the buffer contains less bytes than the maximum record size,
|
||
// the it is the last buffer to be displayed. In this case, check if
|
||
// if the buffer contains a number o bytes that is multiple of 4.
|
||
// If it doesn't, then converts the last bytes as a byte, a word, or
|
||
// a word and a byte, as appropriate.
|
||
//
|
||
if (cb < RECORD_SIZE) {
|
||
ulIndex = (sizeof( MSG_ADDR_FIELD ) - 1 ) +
|
||
(cb/4)*(ulNumberOfDigits + 1 );
|
||
switch( cb%4 ) {
|
||
|
||
case 1:
|
||
ulIndex += sprintf( line + ulIndex,
|
||
pchMsgByte,
|
||
buf[ cb-1 ]);
|
||
line[ ulIndex ] = SPACE;
|
||
break;
|
||
|
||
case 2:
|
||
ulIndex += sprintf( line + ulIndex,
|
||
pchMsg,
|
||
(( unsigned short* ) ( buf )) [ (cb/2) - 1 ]);
|
||
line[ ulIndex ] = SPACE;
|
||
break;
|
||
|
||
case 3:
|
||
ulIndex += sprintf( line + ulIndex,
|
||
pchMsgWordByte,
|
||
(( unsigned short* ) ( buf )) [ (cb/2) - 1],
|
||
buf[ cb-1 ]);
|
||
line[ ulIndex ] = SPACE;
|
||
break;
|
||
|
||
default: // buf contains multiple of 4 bytes
|
||
break;
|
||
}
|
||
//
|
||
// Delete the charecters that were converted but are not to be
|
||
// displayed.
|
||
//
|
||
while ( line[ ulIndex ] != NUL) {
|
||
line[ ulIndex ] = SPACE;
|
||
ulIndex++;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
void
|
||
ConvertPRINT (
|
||
char line[],
|
||
unsigned char buf[],
|
||
unsigned long cb
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine converts each byte received in a buffer into a
|
||
printable character.
|
||
|
||
|
||
Arguments:
|
||
|
||
line - Buffer that will receive the converted characters.
|
||
|
||
buf - A buffer that contains the data to be converted.
|
||
|
||
cb - Number of bytes in the buffer
|
||
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
|
||
sprintf( line,
|
||
MSG_PRINT_CHAR_FMT,
|
||
isprint( buf[ 0 ] ) ? buf[ 0 ] : DOT,
|
||
isprint( buf[ 1 ] ) ? buf[ 1 ] : DOT,
|
||
isprint( buf[ 2 ] ) ? buf[ 2 ] : DOT,
|
||
isprint( buf[ 3 ] ) ? buf[ 3 ] : DOT,
|
||
isprint( buf[ 4 ] ) ? buf[ 4 ] : DOT,
|
||
isprint( buf[ 5 ] ) ? buf[ 5 ] : DOT,
|
||
isprint( buf[ 6 ] ) ? buf[ 6 ] : DOT,
|
||
isprint( buf[ 7 ] ) ? buf[ 7 ] : DOT,
|
||
isprint( buf[ 8 ] ) ? buf[ 8 ] : DOT,
|
||
isprint( buf[ 9 ] ) ? buf[ 9 ] : DOT,
|
||
isprint( buf[ 10 ] ) ? buf[ 10 ] : DOT,
|
||
isprint( buf[ 11 ] ) ? buf[ 11 ] : DOT,
|
||
isprint( buf[ 12 ] ) ? buf[ 12 ] : DOT,
|
||
isprint( buf[ 13 ] ) ? buf[ 13 ] : DOT,
|
||
isprint( buf[ 14 ] ) ? buf[ 14 ] : DOT,
|
||
isprint( buf[ 15 ] ) ? buf[ 15 ] : DOT);
|
||
//
|
||
// If the buffer contains less characters than the maximum record size,
|
||
// then delete the characters that were converted but are not to be
|
||
// displayed
|
||
//
|
||
if (cb < RECORD_SIZE) {
|
||
while ( line[ cb ] != NUL ) {
|
||
line[ cb ] = SPACE;
|
||
cb++;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
void
|
||
Translate (
|
||
FORMAT fmt,
|
||
unsigned char buf[ ],
|
||
unsigned long cb,
|
||
char line[ ]
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function converts the bytes received in a buffer
|
||
into a printable representation, that corresponds to one
|
||
of the formats specified by the parameter fmt.
|
||
|
||
|
||
Arguments:
|
||
|
||
fmt - The format to be used in the conversion
|
||
|
||
buf - A buffer that contains the data to be converted.
|
||
|
||
cb - Number of bytes in the buffer
|
||
|
||
line - Buffer that will receive the converted characters.
|
||
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
|
||
{
|
||
assert( buf );
|
||
assert( line );
|
||
|
||
switch( fmt ) {
|
||
|
||
case ASCII_CHAR:
|
||
ConvertASCII( line, buf, cb, asciiChar );
|
||
break;
|
||
|
||
case ASCII_C:
|
||
ConvertASCII( line, buf, cb, asciiC );
|
||
break;
|
||
|
||
case ASCII_CODE:
|
||
ConvertASCII( line, buf, cb, asciiCode );
|
||
break;
|
||
|
||
case ASCII_CTRL:
|
||
ConvertASCII( line, buf, cb, asciiCtrl );
|
||
break;
|
||
|
||
case BYTE_DEC:
|
||
ConvertBYTE( line, buf, cb, DEC );
|
||
break;
|
||
|
||
case BYTE_HEX:
|
||
ConvertBYTE( line, buf, cb, HEX );
|
||
break;
|
||
|
||
case WORD_DEC:
|
||
ConvertWORD( line, buf, cb, DEC );
|
||
break;
|
||
|
||
case WORD_HEX:
|
||
ConvertWORD( line, buf, cb, HEX );
|
||
break;
|
||
|
||
case DWORD_DEC:
|
||
ConvertDWORD( line, buf, cb, DEC );
|
||
break;
|
||
|
||
case DWORD_HEX:
|
||
ConvertDWORD( line, buf, cb, HEX );
|
||
break;
|
||
|
||
case PRINT_CHAR:
|
||
ConvertPRINT( line, buf, cb );
|
||
break;
|
||
|
||
|
||
default:
|
||
printf( "Bad Format\n" );
|
||
assert( FALSE );
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
void
|
||
PutAddress (
|
||
char line[],
|
||
unsigned long ulAddress,
|
||
BASE Base
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine adds to the buffer received the offset of the first
|
||
byte (or character) already in the buffer. This offset represents
|
||
the position of the byte in the file, relatively to the begining
|
||
of the file.
|
||
|
||
|
||
Arguments:
|
||
|
||
Base - The base to be used to represent the offset.
|
||
|
||
line - Buffer containing the converted characters to be displayed in
|
||
the screen
|
||
|
||
ulAddress - Offset to be added to the begining of the buffer
|
||
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
unsigned long ulIndex;
|
||
|
||
assert( line);
|
||
|
||
switch( Base ) {
|
||
|
||
case DEC:
|
||
ulIndex = sprintf( line,
|
||
MSG_ADDR_DEC_FMT,
|
||
ulAddress );
|
||
break;
|
||
|
||
case HEX:
|
||
ulIndex = sprintf( line,
|
||
MSG_ADDR_HEX_FMT,
|
||
ulAddress);
|
||
break;
|
||
|
||
default:
|
||
printf( "Bad Address Base\n" );
|
||
assert( FALSE );
|
||
break;
|
||
}
|
||
line[ ulIndex ] = SPACE; // Get rid of the NUL added by sprintf
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
void
|
||
PutTable (
|
||
char line[],
|
||
unsigned char buf[],
|
||
unsigned long cb
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine adds to the end of the buffer received, the ASCII
|
||
representation of all printable characters already in the buffer.
|
||
Characters that are not printable (smaller than 0x20 or greater than
|
||
0x7f) are displayed as a dot.
|
||
|
||
|
||
Arguments:
|
||
|
||
line - Buffer containing the characters to be displayed in one line
|
||
of the screen
|
||
|
||
buf - The buffer that contains a record of bytes (maximum of 16)
|
||
read from the file being displayed.
|
||
|
||
ulAddress - Number of bytes in buf.
|
||
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
unsigned long ulIndex;
|
||
|
||
assert( line );
|
||
assert( buf );
|
||
|
||
ulIndex = strlen (line);
|
||
Translate( PRINT_CHAR, buf, cb, (line + ulIndex));
|
||
}
|
||
|
||
|
||
|
||
|
||
void
|
||
InterpretArgument (
|
||
char* pchPointer
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine interprets an argument typed by the user (exept -n
|
||
and -s) and initializes some variables accordingly.
|
||
|
||
|
||
Arguments:
|
||
|
||
pchPointer - Pointer to the argument to be interpreted.
|
||
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// pchPointer will point to the character that follows '-'
|
||
//
|
||
pchPointer++;
|
||
if( strcmp( pchPointer, "ax" ) == 0 ) {
|
||
AddrFormat = HEX;
|
||
}
|
||
else if( strcmp( pchPointer, "ad" ) == 0 ) {
|
||
AddrFormat = DEC;
|
||
}
|
||
else if( strcmp( pchPointer, "ch" ) == 0 ) {
|
||
DispFormat = ASCII_CHAR;
|
||
cStringSize = strlen( asciiChar[0] );
|
||
DumpAscii = ( DumpAscii == NOT_DEFINED ) ? NO : DumpAscii;
|
||
}
|
||
else if( strcmp( pchPointer, "cC" ) == 0 ) {
|
||
DispFormat = ASCII_C;
|
||
cStringSize = strlen( asciiC[0] );
|
||
DumpAscii = ( DumpAscii == NOT_DEFINED ) ? NO : DumpAscii;
|
||
}
|
||
else if( strcmp( pchPointer, "ce" ) == 0 ) {
|
||
DispFormat = ASCII_CODE;
|
||
cStringSize = strlen( asciiCode[0] );
|
||
DumpAscii = ( DumpAscii == NOT_DEFINED ) ? NO : DumpAscii;
|
||
}
|
||
else if( strcmp( pchPointer, "cr" ) == 0 ) {
|
||
DispFormat = ASCII_CTRL;
|
||
cStringSize = strlen( asciiCtrl[0] );
|
||
DumpAscii = ( DumpAscii == NOT_DEFINED ) ? NO : DumpAscii;
|
||
}
|
||
else if( strcmp( pchPointer, "bd" ) == 0 ) {
|
||
DispFormat = BYTE_DEC;
|
||
DumpAscii = ( DumpAscii == NOT_DEFINED ) ? NO : DumpAscii;
|
||
}
|
||
else if( strcmp( pchPointer, "bx" ) == 0 ) {
|
||
DispFormat = BYTE_HEX;
|
||
DumpAscii = ( DumpAscii == NOT_DEFINED ) ? NO : DumpAscii;
|
||
}
|
||
else if( strcmp( pchPointer, "wd" ) == 0 ) {
|
||
DispFormat = WORD_DEC;
|
||
DumpAscii = ( DumpAscii == NOT_DEFINED ) ? NO : DumpAscii;
|
||
}
|
||
else if( strcmp( pchPointer, "wx" ) == 0 ) {
|
||
DispFormat = WORD_HEX;
|
||
DumpAscii = ( DumpAscii == NOT_DEFINED ) ? NO : DumpAscii;
|
||
}
|
||
else if( strcmp( pchPointer, "ld" ) == 0 ) {
|
||
DispFormat = DWORD_DEC;
|
||
DumpAscii = ( DumpAscii == NOT_DEFINED ) ? NO : DumpAscii;
|
||
}
|
||
else if( strcmp( pchPointer, "lx" ) == 0 ) {
|
||
DispFormat = DWORD_HEX;
|
||
DumpAscii = ( DumpAscii == NOT_DEFINED ) ? NO : DumpAscii;
|
||
}
|
||
else if( strcmp( pchPointer, "A" ) == 0 ) {
|
||
DumpAscii = YES;
|
||
}
|
||
else if( strcmp( pchPointer, "i" ) == 0 ) {
|
||
IgnoreRedundantLines = 1;
|
||
}
|
||
else if( strcmp( pchPointer, "?" ) || strcmp( pchPointer, "h" ) ||
|
||
strcmp( pchPointer, "H" ) ) {
|
||
puts( HELP_MESSAGE );
|
||
exit( 0 );
|
||
}
|
||
else {
|
||
fprintf( stderr, "hd: error: invalid argument '%s'\n", --pchPointer );
|
||
exit( - 1 );
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
unsigned long
|
||
GetRecord (
|
||
unsigned char* puchRecord,
|
||
FILE* pf
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine fills the buffer whose pointer was received as parameter,
|
||
with characters read from the file being displayed. Blocks of data
|
||
are initially read from the file being displayed, and kept in a buffer.
|
||
A record is filled with characters obtained from this buffer.
|
||
Whenever this buffer gets empty, a new access to file is performed
|
||
in order to fill this buffer.
|
||
|
||
|
||
Arguments:
|
||
|
||
puchRecord - Pointer to the record to be filled
|
||
pf - Pointer to the file that is being displayed
|
||
|
||
|
||
Return Value:
|
||
|
||
Total number of characters put in the record.
|
||
|
||
--*/
|
||
|
||
{
|
||
unsigned long cbBytesCopied;
|
||
|
||
//
|
||
// If the buffer contains enogh characters to fill the record, then
|
||
// copy the appropriate number of bytes.
|
||
//
|
||
if( cbBytesInBuffer >= RECORD_SIZE ) {
|
||
for( cbBytesCopied = 0; cbBytesCopied < RECORD_SIZE; cbBytesCopied++ ) {
|
||
*puchRecord++ = *puchPointer++;
|
||
cbBytesInBuffer--;
|
||
}
|
||
}
|
||
|
||
//
|
||
// else, the buffer does not contain enough characters to fill the record
|
||
//
|
||
else {
|
||
//
|
||
// Copy to the remaining characters in the buffer to the record
|
||
//
|
||
for( cbBytesCopied = 0; cbBytesInBuffer > 0; cbBytesInBuffer-- ) {
|
||
*puchRecord++ = *puchPointer++;
|
||
cbBytesCopied++;
|
||
}
|
||
//
|
||
// Read more data from the file and fill the record
|
||
//
|
||
if( !feof( pf ) ) {
|
||
cbBytesInBuffer = fread( auchBuffer,
|
||
sizeof( char ),
|
||
BUFFER_SIZE,
|
||
pf );
|
||
puchPointer = auchBuffer;
|
||
while( ( cbBytesInBuffer != 0 ) && (cbBytesCopied < RECORD_SIZE) ) {
|
||
*puchRecord++ = *puchPointer++;
|
||
cbBytesInBuffer--;
|
||
cbBytesCopied++;
|
||
}
|
||
}
|
||
}
|
||
return( cbBytesCopied );
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
int
|
||
hd(
|
||
FILE * pf
|
||
)
|
||
/*++ hd
|
||
*
|
||
* Routine Description:
|
||
* takes the file/stream pointed to by pf and `hd's it to stdout.
|
||
*
|
||
* Arguments:
|
||
* FILE * pf -
|
||
*
|
||
* Return Value:
|
||
* int - to be determined, always zero for now
|
||
* Warnings:
|
||
--*/
|
||
{
|
||
unsigned char buf[ RECORD_SIZE ];
|
||
char line[ LINE_SIZE ];
|
||
char Previousline[ LINE_SIZE ];
|
||
int printedstar;
|
||
|
||
unsigned long CurrentAddress;
|
||
unsigned long cNumberOfBlocks;
|
||
unsigned cLastBlockSize;
|
||
unsigned long cb;
|
||
|
||
//
|
||
// Determine number of records to be displayed, and size of
|
||
// last record
|
||
//
|
||
|
||
CurrentAddress = Offset;
|
||
cNumberOfBlocks = Count / RECORD_SIZE;
|
||
cLastBlockSize = Count % RECORD_SIZE;
|
||
if( cLastBlockSize ) {
|
||
cNumberOfBlocks++;
|
||
}
|
||
else {
|
||
cLastBlockSize = RECORD_SIZE;
|
||
}
|
||
|
||
//
|
||
// Initialize global variables related to auchBuffer
|
||
//
|
||
|
||
cbBytesInBuffer = 0;
|
||
puchPointer = auchBuffer;
|
||
|
||
//
|
||
// Position the file in the correct place, and display
|
||
// its contents according to the arguments specified by the
|
||
// user
|
||
//
|
||
|
||
if ( pf != stdin ) {
|
||
if (fseek( pf, Offset, SEEK_SET ) == -1) return 0;
|
||
}
|
||
//...maybe enable skipping Offset number of bytes for stdin...
|
||
|
||
printedstar = 0;
|
||
|
||
while( ( (cb = GetRecord( buf, pf )) != 0) && cNumberOfBlocks ) {
|
||
cNumberOfBlocks--;
|
||
if ( cNumberOfBlocks == 0 ) {
|
||
cb = ( cb < cLastBlockSize ) ? cb : cLastBlockSize;
|
||
}
|
||
Translate( DispFormat, buf, cb, line );
|
||
|
||
if (IgnoreRedundantLines && (strcmp( Previousline, line ) == 0)) {
|
||
|
||
if (!printedstar) { printf("*\n"); }
|
||
printedstar = 1;
|
||
|
||
} else {
|
||
|
||
printedstar = 0;
|
||
|
||
strcpy( Previousline, line );
|
||
|
||
PutAddress( line, CurrentAddress, AddrFormat );
|
||
if ( (DumpAscii == YES) || (DumpAscii == NOT_DEFINED) )
|
||
{
|
||
PutTable ( line, buf, cb );
|
||
}
|
||
puts( line );
|
||
}
|
||
|
||
CurrentAddress += RECORD_SIZE;
|
||
}
|
||
return 0;
|
||
}
|
||
/* end of "int hd()" */
|
||
|
||
|
||
|
||
|
||
void
|
||
__cdecl main(
|
||
int argc,
|
||
char* argv[ ]
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine interprets all arguments entered by the user, and
|
||
displays the files specified in the appropriate format.
|
||
The contents of each file is displayed interpreted as a set of
|
||
record containing 16 bytes each.
|
||
|
||
|
||
Arguments:
|
||
|
||
argc - number of arguments in the command line
|
||
argv[] - array of pointers to the arguments entered by the user
|
||
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
|
||
{
|
||
FILE* pf;
|
||
//. unsigned char buf[ RECORD_SIZE ];
|
||
//. char line[ LINE_SIZE ];
|
||
int ArgIndex;
|
||
int status;
|
||
|
||
//. unsigned long CurrentAddress;
|
||
//. unsigned long cNumberOfBlocks;
|
||
//. unsigned cLastBlockSize;
|
||
//. unsigned long cb;
|
||
unsigned long Value;
|
||
unsigned char* pPtrString;
|
||
|
||
//. printf( "\n\n" ); //.gratuitous newlines removed
|
||
// Initialization of global variables
|
||
Offset = 0;
|
||
Count = (unsigned long)-1; // Maximum file size
|
||
AddrFormat = HEX;
|
||
DispFormat = BYTE_HEX;
|
||
DumpAscii = NOT_DEFINED;
|
||
IgnoreRedundantLines = 0;
|
||
|
||
ArgIndex = 1;
|
||
while ( (ArgIndex < argc) && (( *argv[ ArgIndex ] == '-' )) ) {
|
||
|
||
//
|
||
// Determine the type of argument
|
||
//
|
||
|
||
if( (*(argv[ ArgIndex ] + 1) == 's') ||
|
||
(*(argv[ ArgIndex ] + 1) == 'n') ) {
|
||
|
||
//
|
||
// If argument is -s or -n, interprets the number that
|
||
// follows the argument
|
||
//
|
||
|
||
if ( (ArgIndex + 1) >= argc ) {
|
||
fprintf(stderr,
|
||
"hd: error: missing count/offset value after -%c\n",
|
||
*(argv[ ArgIndex ] + 1) );
|
||
exit (-1);
|
||
}
|
||
Value = strtoul( argv[ ArgIndex + 1 ], &pPtrString, 0 );
|
||
if( *pPtrString != 0 ) {
|
||
fprintf(stderr,
|
||
"hd: error: invalid count/offset value after -%c\n",
|
||
*(argv[ ArgIndex ] + 1) );
|
||
exit( -1 );
|
||
}
|
||
if( *(argv[ ArgIndex ] + 1) == 's' ) {
|
||
Offset = Value;
|
||
}
|
||
else {
|
||
Count = Value;
|
||
}
|
||
ArgIndex += 2;
|
||
}
|
||
else {
|
||
|
||
//
|
||
// Interprets argument other than -s or -n
|
||
//
|
||
|
||
InterpretArgument ( argv[ ArgIndex ] );
|
||
ArgIndex++;
|
||
}
|
||
}
|
||
|
||
if ( ArgIndex >= argc ) {
|
||
//. printf ( "Error: file name is missing \n" );
|
||
status = hd( stdin );
|
||
exit( 0 );
|
||
}
|
||
|
||
|
||
//
|
||
// For each file, do
|
||
//
|
||
|
||
while ( ArgIndex < argc ) {
|
||
|
||
//
|
||
// Open file
|
||
//
|
||
|
||
if ( !( pf = fopen( argv[ ArgIndex ], "rb" ) ) ) {
|
||
fprintf(stderr, "hd: error: invalid file name '%s'\n",
|
||
argv[ ArgIndex ] );
|
||
ArgIndex++;
|
||
continue; //. don't abort if it's only a bad filename
|
||
//. exit( -1 );
|
||
}
|
||
|
||
//
|
||
// Print file name
|
||
//
|
||
|
||
//. printf( "\n\n" );
|
||
printf( "%s: \n", argv[ ArgIndex ] );
|
||
ArgIndex++;
|
||
|
||
status = hd( pf );
|
||
|
||
//. //
|
||
//. // Determine number of records to be displayed, and size of
|
||
//. // last record
|
||
//. //
|
||
//.
|
||
//. CurrentAddress = Offset;
|
||
//. cNumberOfBlocks = Count / RECORD_SIZE;
|
||
//. cLastBlockSize = Count % RECORD_SIZE;
|
||
//. if( cLastBlockSize ) {
|
||
//. cNumberOfBlocks++;
|
||
//. }
|
||
//. else {
|
||
//. cLastBlockSize = RECORD_SIZE;
|
||
//. }
|
||
//.
|
||
//. //
|
||
//. // Initialize global variables related to auchBuffer
|
||
//. //
|
||
//.
|
||
//. cbBytesInBuffer = 0;
|
||
//. puchPointer = auchBuffer;
|
||
//.
|
||
//. //
|
||
//. // Position the file in the correct place, and display
|
||
//. // its contents according to the arguments specified by the
|
||
//. // user
|
||
//. //
|
||
//.
|
||
//. fseek( pf, Offset, SEEK_SET );
|
||
//. while( ( (cb = GetRecord( buf, pf )) != 0) && cNumberOfBlocks ) {
|
||
//. cNumberOfBlocks--;
|
||
//. if ( cNumberOfBlocks == 0 ) {
|
||
//. cb = ( cb < cLastBlockSize ) ? cb : cLastBlockSize;
|
||
//. }
|
||
//. Translate( DispFormat, buf, cb, line );
|
||
//. PutAddress( line, CurrentAddress, AddrFormat );
|
||
//. if ( (DumpAscii == YES) || (DumpAscii == NOT_DEFINED) )
|
||
//. {
|
||
//. PutTable ( line, buf, cb );
|
||
//. }
|
||
//. puts( line );
|
||
//.
|
||
//. CurrentAddress += RECORD_SIZE;
|
||
//. }
|
||
}
|
||
}
|
||
/* end of "void main()" */
|