Initial revision

This commit is contained in:
Joel Sherrill
1995-05-11 17:39:37 +00:00
commit ac7d5ef06a
1683 changed files with 189788 additions and 0 deletions

32
tools/build/README Normal file
View File

@@ -0,0 +1,32 @@
#
# $Id$
#
Misc. support tools for RTEMS workspaces.
More will be added later as they are converted from Teamware
to CVS.
install-if-change
Smart install script that also can append suffixes as it
installs (suffixes used for debug and profile variants).
Requires bash or ksh.
rcs-clean
deletes all files from the current directory that can be
re-created from RCS. Careful to not delete locked files.
May be used by 'gmake clobber'
lock-directory
unlock-directory
traverse a directory structure making it unwritable.
Useful to keep people from accidentally overwriting
"released" trees if they get confused about which
module they have loaded.
rtems-glom
glom together all the rtems libraries in order to simplify
the link line used by applications.
Produces rtems.rel.
Not used by the RTEMS src tree at all.
Strictly optional.

364
tools/build/cklength.c Normal file
View File

@@ -0,0 +1,364 @@
/*
* cklength - check the length of lines in a file
*
* This program check to see if the files passed to it on the command line
* contain a line which exceeds the maximum allowable length. The default
* maximum line length is 80.
*
* usage: cklength [ -v ] [ arg ... ] files...
* -l length -- maximum line length
* -v -- verbose
*
* $Id$
* $Log$
*/
#define GETOPTARGS "l:nNv"
char *USAGE = "\
usage: cklength [ -v ] [ arg ... ] files... \n\
-l length -- maximum line length\n\
-n -- report line numbers for offending lines\n\
-N -- report line numbers and length for offending lines\n\
-v -- verbose\n\
\n\
Print the name of files which have at least 1 line which exceeds the\n\
maximum line length. The default maximum line length is 80.\n\
";
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <memory.h>
#include <stdarg.h>
#define BUFFER_SIZE 512
#define SUCCESS 0
#define FAILURE -1
#define Failed(x) (((int) (x)) == FAILURE)
#define TRUE 1
#define FALSE 0
#define STREQ(a,b) (strcmp(a,b) == 0)
#define NUMELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
/*
* Definitions for unsigned "ints"; especially for use in data structures
* that will be shared among (potentially) different cpu's (we punt on
* byte ordering problems tho)
*/
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
/*
* vars controlled by command line options
*/
int verbose = FALSE; /* be verbose */
int report_line_numbers = FALSE; /* report line numbers of offenders */
int report_line_length = FALSE; /* report line length of offenders */
int line_length = 80; /* maximum allowable line length */
extern char *optarg; /* getopt(3) control vars */
extern int optind, opterr;
extern int errno;
char *progname; /* for error() */
int process(char *arg);
void error(int errn, ...);
long getparm(char *s, long min, long max, char *msg);
#define ERR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */
#define ERR_FATAL (ERR_ERRNO / 2) /* fatal error ; no return */
#define ERR_ABORT (ERR_ERRNO / 4) /* fatal error ; abort */
#define ERR_MASK (ERR_ERRNO | ERR_FATAL | ERR_ABORT) /* all */
#define stol(p) strtol(p, (char **) NULL, 0)
int Open(), Read(), Write();
int
main(int argc, char **argv, char **env)
{
register int c;
int showusage = FALSE; /* usage error? */
int rc = 0;
/*
* figure out invocation leaf-name
*/
if ((progname = strrchr(argv[0], '/')) == (char *) NULL)
progname = argv[0];
else
progname++;
argv[0] = progname; /* for getopt err reporting */
/*
* Check options and arguments.
*/
opterr = 0; /* we'll report all errors */
while ((c = getopt(argc, argv, GETOPTARGS)) != EOF)
switch (c)
{
case 'l': /* line length */
line_length = atoi( optarg );
if ( line_length < 0 || line_length > BUFFER_SIZE )
error(ERR_FATAL, "(%d) is illegal line length\n",line_length);
break;
case 'n': /* toggle report_line_numbers */
report_line_numbers = ! report_line_numbers;
break;
case 'N': /* toggle both reports */
report_line_numbers = ! report_line_numbers;
report_line_length = ! report_line_length;
break;
case 'v': /* toggle verbose */
verbose = ! verbose;
break;
case '?':
showusage = TRUE;
}
if (showusage)
{
(void) fprintf(stderr, "%s", USAGE);
exit(1);
}
/*
* traverse and process the arguments
*/
for ( ; argv[optind]; optind++)
if (Failed(process(argv[optind])))
rc = FAILURE;
return rc;
}
/*
* process(arg)
*/
int
process(char *arg)
{
FILE *in;
char *bptr;
char buffer[ BUFFER_SIZE ];
int line_number;
int length;
int count;
int rc = SUCCESS; /* succeed by default */
in = fopen( arg, "r" );
if (!in)
error( ERR_ERRNO | ERR_FATAL, "Unable to open file (%s)\n", arg );
count = 0;
for ( line_number=1 ; ; line_number++ ) {
bptr = fgets( buffer, BUFFER_SIZE, in );
if (!bptr)
break;
/*
* Don't count the carriage return.
*/
length = strlen( buffer ) - 1;
if ( length <= line_length )
continue;
if ( count == 0 ) {
fprintf( stderr, "%s\n", arg );
if ( !report_line_numbers )
break;
}
if ( verbose )
fprintf( stderr, "TOO LONG:%d: %s\n", line_number, buffer );
if ( report_line_numbers ) {
if ( report_line_length )
fprintf( stderr, "%d: %d\n" , line_number, length );
else
fprintf( stderr, "%d\n" , line_number );
}
count++;
}
fclose( in );
return rc;
}
/*
* error(errn, arglist)
* report an error to stderr using printf(3) conventions.
* Any output is preceded by '<progname>: '
*
* Uses ERR_FATAL bit to request exit(errn)
* ERR_ABORT to request abort()
* ERR_ERRNO to indicate use of errno instead of argument.
*
* If resulting 'errn' is non-zero, it is assumed to be an 'errno' and its
* associated error message is appended to the output.
*/
/*VARARGS*/
void
error(int error_flag, ...)
{
va_list arglist;
register char *format;
extern char *sys_errlist[];
extern int sys_nerr;
int local_errno;
extern int errno;
(void) fflush(stdout); /* in case stdout/stderr same */
local_errno = error_flag & ~ERR_MASK;
if (error_flag & ERR_ERRNO) /* use errno? */
local_errno = errno;
va_start(arglist, error_flag);
format = va_arg(arglist, char *);
(void) fprintf(stderr, "%s: ", progname);
(void) vfprintf(stderr, format, arglist);
va_end(arglist);
if (local_errno)
if ((local_errno > 0) && (local_errno < sys_nerr))
(void) fprintf(stderr, " (%s)\n", sys_errlist[local_errno]);
else
(void) fprintf(stderr, " (unknown errno=%d)\n", local_errno);
else
(void) fprintf(stderr, "\n");
(void) fflush(stderr);
if (error_flag & (ERR_FATAL | ERR_ABORT))
{
if (error_flag & ERR_FATAL)
{
error(0, local_errno ? "fatal error, exiting" : "exiting");
exit(local_errno);
}
else
{
error(0, "fatal error, aborting");
abort();
}
}
}
long
getparm(char *s,
long min,
long max,
char *msg)
{
long val;
if ( ! strchr("0123456789-", *s))
{
error(ERR_FATAL, "'%s' is not a number", s);
return min;
}
val = strtol(s, (char **) NULL, 0);
if ((val < min) || (val > max))
{
if (min == max)
error(ERR_FATAL, "%s can only be %ld", s, min);
else
error(ERR_FATAL, "%s must be between %ld and %ld", msg, min, max);
}
return val;
}
/*
* Open()
* Perform open(2), returning the file descriptor. Prints
* error message if open fails.
*/
int
Open(char *file,
int oflag,
int mode)
{
int O_fd;
if (Failed(O_fd = open(file, oflag, mode)))
error(
ERR_ERRNO | ERR_FATAL,
"open('%s', 0x%x, 0%o) failed", file, oflag, mode
);
return O_fd;
}
/*
* Read()
* Perform read(2); prints error message if fails.
*/
int
Read(int file,
char *buffer,
unsigned int count)
{
int nbytes;
if (Failed(nbytes = read(file, buffer, count)))
error(
ERR_ERRNO | ERR_FATAL,
"read(%d, 0x%x, %d) failed", file, buffer, count
);
return nbytes;
}
/*
* Write()
* Perform write(2); prints error message if fails.
*/
int
Write(int file,
char *buffer,
unsigned int count)
{
int nbytes;
if (Failed(nbytes = write(file, buffer, count)))
error(
ERR_ERRNO | ERR_FATAL,
"write(%d, 0x%x, %d) failed", file, buffer, count
);
return nbytes;
}

351
tools/build/eolstrip.c Normal file
View File

@@ -0,0 +1,351 @@
/*
* eolstrip - strip white space from end of lines
*
* This program strips the white space from the end of every line in the
* specified program.
*
* usage: eolstrip [ -v ] [ arg ... ] files...
* -v -- verbose
*
* $Id$
* $Log$
*/
#define GETOPTARGS "vt"
char *USAGE = "\
usage: cklength [ -v ] [ arg ... ] files... \n\
-v -- verbose\n\
-t -- test only .. DO NOT OVERWRITE FILE!!!\n\
\n\
Strip the white space from the end of every line on the list of files.\n\
";
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <memory.h>
#include <stdarg.h>
#define BUFFER_SIZE 2048
#define MAX_PATH 2048
#define SUCCESS 0
#define FAILURE -1
#define Failed(x) (((int) (x)) == FAILURE)
#define TRUE 1
#define FALSE 0
#define STREQ(a,b) (strcmp(a,b) == 0)
#define NUMELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
/*
* Definitions for unsigned "ints"; especially for use in data structures
* that will be shared among (potentially) different cpu's (we punt on
* byte ordering problems tho)
*/
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
/*
* vars controlled by command line options
*/
int verbose = FALSE; /* be verbose */
int test_only = FALSE; /* test only */
extern char *optarg; /* getopt(3) control vars */
extern int optind, opterr;
extern int errno;
char *progname; /* for error() */
int process(char *arg);
void error(int errn, ...);
long getparm(char *s, long min, long max, char *msg);
#define ERR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */
#define ERR_FATAL (ERR_ERRNO / 2) /* fatal error ; no return */
#define ERR_ABORT (ERR_ERRNO / 4) /* fatal error ; abort */
#define ERR_MASK (ERR_ERRNO | ERR_FATAL | ERR_ABORT) /* all */
#define stol(p) strtol(p, (char **) NULL, 0)
int Open(), Read(), Write();
int
main(int argc, char **argv, char **env)
{
register int c;
int showusage = FALSE; /* usage error? */
int rc = 0;
/*
* figure out invocation leaf-name
*/
if ((progname = strrchr(argv[0], '/')) == (char *) NULL)
progname = argv[0];
else
progname++;
argv[0] = progname; /* for getopt err reporting */
/*
* Check options and arguments.
*/
opterr = 0; /* we'll report all errors */
while ((c = getopt(argc, argv, GETOPTARGS)) != EOF)
switch (c)
{
case 't': /* toggle test only mode */
test_only = ! test_only;
break;
case 'v': /* toggle verbose */
verbose = ! verbose;
break;
case '?':
showusage = TRUE;
}
if (showusage)
{
(void) fprintf(stderr, "%s", USAGE);
exit(1);
}
/*
* traverse and process the arguments
*/
for ( ; argv[optind]; optind++)
if (Failed(process(argv[optind])))
rc = FAILURE;
return rc;
}
/*
* process(arg)
*/
int
process(char *arg)
{
FILE *in;
FILE *out = (FILE *) 0;
char outname[ MAX_PATH ];
char *bptr;
char buffer[ BUFFER_SIZE ];
int length;
int line_number;
int rc = SUCCESS; /* succeed by default */
in = fopen( arg, "r" );
if (!in)
error( ERR_ERRNO | ERR_FATAL, "Unable to open file (%s)\n", arg );
if ( !test_only ) {
sprintf( outname, "%s.eoltmp", arg );
out = fopen( outname, "w" );
if (!out)
error( ERR_ERRNO | ERR_FATAL, "Unable to open file (%s)\n", arg );
}
if ( verbose )
fprintf( stderr, "Processing %s\n", arg );
for ( line_number=1 ; ; line_number++ ) {
bptr = fgets( buffer, BUFFER_SIZE, in );
if (!bptr)
break;
/*
* Don't count the carriage return.
*/
length = strlen( buffer ) - 1;
if ( buffer[ length ] != '\n' )
error(ERR_ERRNO|ERR_FATAL, "Line %d too long in %s\n", line_number, arg);
while ( isspace( buffer[ length ] ) )
buffer[ length-- ] = '\0';
if ( test_only ) {
fprintf( stderr, "%s\n", arg );
break;
}
fprintf( out, "%s\n", buffer );
}
fclose( in );
if ( !test_only ) {
fclose( out );
rename( outname, arg );
}
return rc;
}
/*
* error(errn, arglist)
* report an error to stderr using printf(3) conventions.
* Any output is preceded by '<progname>: '
*
* Uses ERR_FATAL bit to request exit(errn)
* ERR_ABORT to request abort()
* ERR_ERRNO to indicate use of errno instead of argument.
*
* If resulting 'errn' is non-zero, it is assumed to be an 'errno' and its
* associated error message is appended to the output.
*/
/*VARARGS*/
void
error(int error_flag, ...)
{
va_list arglist;
register char *format;
extern char *sys_errlist[];
extern int sys_nerr;
int local_errno;
extern int errno;
(void) fflush(stdout); /* in case stdout/stderr same */
local_errno = error_flag & ~ERR_MASK;
if (error_flag & ERR_ERRNO) /* use errno? */
local_errno = errno;
va_start(arglist, error_flag);
format = va_arg(arglist, char *);
(void) fprintf(stderr, "%s: ", progname);
(void) vfprintf(stderr, format, arglist);
va_end(arglist);
if (local_errno)
if ((local_errno > 0) && (local_errno < sys_nerr))
(void) fprintf(stderr, " (%s)\n", sys_errlist[local_errno]);
else
(void) fprintf(stderr, " (unknown errno=%d)\n", local_errno);
else
(void) fprintf(stderr, "\n");
(void) fflush(stderr);
if (error_flag & (ERR_FATAL | ERR_ABORT))
{
if (error_flag & ERR_FATAL)
{
error(0, local_errno ? "fatal error, exiting" : "exiting");
exit(local_errno);
}
else
{
error(0, "fatal error, aborting");
abort();
}
}
}
long
getparm(char *s,
long min,
long max,
char *msg)
{
long val;
if ( ! strchr("0123456789-", *s))
{
error(ERR_FATAL, "'%s' is not a number", s);
return min;
}
val = strtol(s, (char **) NULL, 0);
if ((val < min) || (val > max))
{
if (min == max)
error(ERR_FATAL, "%s can only be %ld", s, min);
else
error(ERR_FATAL, "%s must be between %ld and %ld", msg, min, max);
}
return val;
}
/*
* Open()
* Perform open(2), returning the file descriptor. Prints
* error message if open fails.
*/
int
Open(char *file,
int oflag,
int mode)
{
int O_fd;
if (Failed(O_fd = open(file, oflag, mode)))
error(
ERR_ERRNO | ERR_FATAL,
"open('%s', 0x%x, 0%o) failed", file, oflag, mode
);
return O_fd;
}
/*
* Read()
* Perform read(2); prints error message if fails.
*/
int
Read(int file,
char *buffer,
unsigned int count)
{
int nbytes;
if (Failed(nbytes = read(file, buffer, count)))
error(
ERR_ERRNO | ERR_FATAL,
"read(%d, 0x%x, %d) failed", file, buffer, count
);
return nbytes;
}
/*
* Write()
* Perform write(2); prints error message if fails.
*/
int
Write(int file,
char *buffer,
unsigned int count)
{
int nbytes;
if (Failed(nbytes = write(file, buffer, count)))
error(
ERR_ERRNO | ERR_FATAL,
"write(%d, 0x%x, %d) failed", file, buffer, count
);
return nbytes;
}

513
tools/build/packhex.c Normal file
View File

@@ -0,0 +1,513 @@
/***** P A C K H E X . C ************************************************
*
* Packhex is a hex-file compaction utility. It attempts to concatenate
* hex records to produce more size-efficient packaging.
*
* Limitations: Input files must be correctly formatted. This utility
* is not robust enough to detect hex-record formatting
* errors.
*
* Published: 5/93 Embedded Systems magazine
*
* Compiler: Microsoft C 6.0
* cl /F 1000 packhex.c
*
*
* $Id$
*
**************************************************************************/
/* #define SMALLER_RECORDS */
#ifdef SMALLER_RECORDS
#define MAX_LEN_S1_RECS 128
#define MAX_LEN_S2_RECS 128
#define MAX_LEN_S3_RECS 128
#else
#define MAX_LEN_S1_RECS 252
#define MAX_LEN_S2_RECS 251
#define MAX_LEN_S3_RECS 250
#endif
/*--------------------------------- includes ---------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__unix__) && !defined(EXIT_FAILURE)
#define EXIT_FAILURE -1
#define EXIT_SUCCESS 0
#endif
/*--------------------------------- defines ----------------------------------*/
#define YES 1
#define MAX_LINE_SIZE 600
#define EOS '\0'
/*---------------------------------- macros ----------------------------------*/
/* Convert ASCII hexadecimal digit to value. */
#define HEX_DIGIT( C ) ( ( ( ( C ) > '9' ) ? ( C ) + 25 : ( C ) ) & 0xF )
/*--------------------------------- typedefs ---------------------------------*/
typedef unsigned char Boolean;
typedef unsigned char Uchar;
typedef unsigned int Uint;
typedef unsigned long Ulong;
typedef struct /* Functions and constant returning Hex-record vital stats. */
{
Boolean ( *is_data_record )( char * );
Ulong ( *get_address )( char * );
Uint ( *get_data_count )( char * );
const Uint max_data_count;
char *( *get_data_start )( char * );
void ( *put_data_record )( Uint, Ulong, char * );
} Rec_vitals;
/*--------------------------- function prototypes ----------------------------*/
Rec_vitals * identify_first_data_record( char * );
Ulong get_ndigit_hex( char *, int );
/*----------------------------- Intel Hex format -----------------------------*/
/*
* Intel Hex data-record layout
*
* :aabbbbccd...dee
*
* : - header character
* aa - record data byte count, a 2-digit hex value
* bbbb - record address, a 4-digit hex value
* cc - record type, a 2-digit hex value:
* "00" is a data record
* "01" is an end-of-data record
* "02" is an extended-address record
* "03" is a start record
* d...d - data (always an even number of chars)
* ee - record checksum, a 2-digit hex value
* checksum = 2's complement
* [ (sum of bytes: aabbbbccd...d) modulo 256 ]
*/
Boolean is_intel_data_rec( char * rec_str )
{
return( ( rec_str[ 0 ] == ':' ) && ( rec_str[ 8 ] == '0' ) );
}
Uint get_intel_rec_data_count( char * rec_str )
{
return( ( Uint ) get_ndigit_hex( rec_str + 1, 2 ) );
}
Ulong get_intel_rec_address( char * rec_str )
{
return( get_ndigit_hex( rec_str + 3, 4 ) );
}
char * get_intel_rec_data_start( char * rec_str )
{
return( rec_str + 9 );
}
void put_intel_data_rec( Uint count, Ulong address, char * data_str )
{
char *ptr;
Uint sum = count + ( address >> 8 & 0xff ) + ( address & 0xff );
for ( ptr = data_str ; *ptr != EOS ; ptr += 2 )
sum += ( Uint ) get_ndigit_hex( ptr, 2 );
printf(
":%02X%04lX00%s%02X\n", count, address, data_str, (~sum + 1) & 0xff
);
}
Rec_vitals intel_hex =
{
is_intel_data_rec,
get_intel_rec_address,
get_intel_rec_data_count,
255, /* Maximum data bytes in a record. */
get_intel_rec_data_start,
put_intel_data_rec
};
/*------------------------- Motorola S1-record format ------------------------*/
/*
* Motorola S-record data-record layout
*
* Sabbc...cd...dee
*
* S - header character
* a - record type, a 1-digit value:
* "0" is a header record
* "1" is a 2-byte-address data record
* "2" is a 3-byte-address data record
* "3" is a 4-byte-address data record
* "7" is a 4-byte-address end-of-data record
* "8" is a 3-byte-address end-of-data record
* "9" is a 2-byte-address end-of-data record
* bb - record length in bytes, a 2-digit hex value
* (record length doesn't count the header/type
* chars and checksum byte)
* c...c - record address, a 4-, 6-, or 8-digit value,
* depending on record type
* d...d - data (always an even number of chars)
* ee - record checksum, a 2-digit hex value
* checksum = 1's complement
* [ (sum of all bytes: bbc..cd...d) modulo 256 ]
*/
#define S1_COUNT_OFFSET 3
Boolean is_moto_s1_data_rec( char * rec_str )
{
return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '1' ) );
}
Uint get_moto_s1_rec_data_count( char * rec_str )
{
return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S1_COUNT_OFFSET );
}
Ulong get_moto_s1_rec_address( char * rec_str )
{
return( get_ndigit_hex( rec_str + 4, 4 ) );
}
char * get_moto_s1_rec_data_start( char * rec_str )
{
return( rec_str + 8 );
}
void put_moto_s1_data_rec( Uint count, Ulong address, char * data_str )
{
char *ptr;
Uint sum = S1_COUNT_OFFSET + count +
( address >> 8 & 0xff ) + ( address & 0xff );
for ( ptr = data_str ; *ptr != EOS ; ptr += 2 )
sum += ( Uint ) get_ndigit_hex( ptr, 2 );
printf(
"S1%02X%04lX%s%02X\n",
count + S1_COUNT_OFFSET, address, data_str, ~sum & 0xff
);
}
Rec_vitals motorola_s1_rec =
{
is_moto_s1_data_rec,
get_moto_s1_rec_address,
get_moto_s1_rec_data_count,
MAX_LEN_S1_RECS, /* Maximum data bytes in a record. */
get_moto_s1_rec_data_start,
put_moto_s1_data_rec
};
/*------------------------- Motorola S2-record format ------------------------*/
#define S2_COUNT_OFFSET 4
Boolean is_moto_s2_data_rec( char * rec_str )
{
return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '2' ) );
}
Uint get_moto_s2_rec_data_count( char * rec_str )
{
return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S2_COUNT_OFFSET );
}
Ulong get_moto_s2_rec_address( char * rec_str )
{
return( get_ndigit_hex( rec_str + 4, 6 ) );
}
char * get_moto_s2_rec_data_start( char * rec_str )
{
return( rec_str + 10 );
}
void put_moto_s2_data_rec( Uint count, Ulong address, char * data_str )
{
char *ptr;
Uint sum = S2_COUNT_OFFSET + count + ( address >> 16 & 0xff ) +
( address >> 8 & 0xff ) +
( address & 0xff );
for ( ptr = data_str ; *ptr != EOS ; ptr += 2 )
sum += ( Uint ) get_ndigit_hex( ptr, 2 );
printf(
"S2%02X%06lX%s%02X\n",
count + S2_COUNT_OFFSET, address, data_str, ~sum & 0xff
);
}
Rec_vitals motorola_s2_rec =
{
is_moto_s2_data_rec,
get_moto_s2_rec_address,
get_moto_s2_rec_data_count,
MAX_LEN_S2_RECS, /* Maximum data bytes in a record. */
get_moto_s2_rec_data_start,
put_moto_s2_data_rec
};
/*------------------------- Motorola S3-record format ------------------------*/
#define S3_COUNT_OFFSET 5
Boolean is_moto_s3_data_rec( char * rec_str )
{
return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '3' ) );
}
Uint get_moto_s3_rec_data_count( char * rec_str )
{
return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S3_COUNT_OFFSET );
}
Ulong get_moto_s3_rec_address( char * rec_str )
{
return( get_ndigit_hex( rec_str + 4, 8 ) );
}
char * get_moto_s3_rec_data_start( char * rec_str )
{
return( rec_str + 12 );
}
void put_moto_s3_data_rec( Uint count, Ulong address, char * data_str )
{
char *ptr;
Uint sum = S3_COUNT_OFFSET + count + ( address >> 24 & 0xff ) +
( address >> 16 & 0xff ) +
( address >> 8 & 0xff ) +
( address & 0xff );
for ( ptr = data_str ; *ptr != EOS ; ptr += 2 )
sum += ( Uint ) get_ndigit_hex( ptr, 2 );
printf(
"S3%02X%08lX%s%02X\n",
count + S3_COUNT_OFFSET, address, data_str, ~sum & 0xff
);
}
Rec_vitals motorola_s3_rec =
{
is_moto_s3_data_rec,
get_moto_s3_rec_address,
get_moto_s3_rec_data_count,
MAX_LEN_S3_RECS, /* Maximum data bytes in a record. */
get_moto_s3_rec_data_start,
put_moto_s3_data_rec
};
/*-------------------- Put your favorite hex format here ---------------------*/
/*
* * * * The following is a template for an additional hex format: * * *
*
*
* Boolean is_X_data_rec( char * rec_str ) {}
*
* Uint get_X_rec_data_count( char * rec_str ) {}
*
* Ulong get_X_rec_address( char * rec_str ) {}
*
* char * get_X_rec_data_start( char * rec_str ) {}
*
* void put_X_data_rec( Uint count, Ulong address, char * data_str ) {}
*
* Rec_vitals X_rec =
* {
* is_X_data_rec,
* get_X_rec_address,
* get_X_rec_data_count,
* MAXIMUM DATA BYTES IN A RECORD,
* get_X_rec_data_start,
* put_X_data_rec
* };
*
*/
/*----------------------------------------------------------------------------*/
/*
* Put address of additional Rec_vitals structures
* in this array, before the NULL entry.
*/
Rec_vitals *formats[] =
{
&intel_hex,
&motorola_s1_rec,
&motorola_s2_rec,
&motorola_s3_rec,
( Rec_vitals * ) NULL
};
/**** main *****************************************************************
*
*
* Expects: Nothing (no command-line parameters).
*
* Returns: Exit status (EXIT_SUCCESS or EXIT_FAILURE).
*
* Reads hex records on the standard input and attempts to
* splice adjacent data fields together. Results appear on
* the standard output.
*
*******************************************************************************/
void main( void )
{
char inbuff[ MAX_LINE_SIZE ], outbuff[ MAX_LINE_SIZE ];
char *in_dptr, *out_dptr;
int d_total, d_count, d_excess, n;
Ulong in_rec_addr, out_rec_addr = 0;
Rec_vitals *rptr;
/* Sift through file until first hex record is identified. */
if ( ( rptr = identify_first_data_record( inbuff ) ) == NULL )
{
fputs( "No hex records found.\n", stderr );
exit( EXIT_FAILURE );
}
/* Attempt data-record splicing until end-of-file is reached. */
d_total = 0;
do
{
if ( rptr->is_data_record( inbuff ) == YES )
{ /* Input record is a data record. */
d_count = rptr->get_data_count( inbuff );
in_rec_addr = rptr->get_address( inbuff );
in_dptr = rptr->get_data_start( inbuff );
if ( d_total == 0 || in_rec_addr != out_rec_addr + d_total )
{ /* Begin a new output record. */
if ( d_total != 0 )
rptr->put_data_record( d_total, out_rec_addr, outbuff );
out_dptr = outbuff;
n = d_total = d_count;
out_rec_addr = in_rec_addr;
}
else if
( ( d_excess = d_total + d_count - rptr->max_data_count ) > 0 )
{ /* Output a maximum-length record, then start a new record. */
strncat( outbuff, in_dptr, 2 * ( d_count - d_excess ) );
rptr->put_data_record(
rptr->max_data_count, out_rec_addr, outbuff
);
in_dptr += 2 * ( d_count - d_excess );
out_dptr = outbuff;
n = d_total = d_excess;
out_rec_addr += rptr->max_data_count;
}
else
{ /* Append input record's data field with accumulated data. */
out_dptr = outbuff + ( 2 * d_total );
d_total += n = d_count;
}
strncpy( out_dptr, in_dptr, 2 * n );
out_dptr[ 2 * n ] = EOS;
}
else
{ /* Not a data record;
* flush accumulated data then echo non-data record.
*/
if ( d_total != 0 )
{
rptr->put_data_record( d_total, out_rec_addr, outbuff );
d_total = 0;
}
puts( inbuff );
}
} while ( gets( inbuff ) != NULL );
exit( EXIT_SUCCESS );
}
/**** identify_first_data_record *******************************************
*
* Expects: Pointer to hex-record line buffer.
*
* Returns: Pointer to hex-record structure (NULL if no match found).
*
* Reads the standard input, line by line, searching for a valid
* record header character. If a valid header is found, a pointer
* to the hex-record's type structure is returned, otherwise NULL.
*
* The input-stream pointer is left pointing to the first valid hex record.
*
*******************************************************************************/
Rec_vitals * identify_first_data_record( char * buff_ptr )
{
Rec_vitals ** ptr;
while ( gets( buff_ptr ) != NULL )
{
for ( ptr = formats ; *ptr != ( Rec_vitals * ) NULL ; ptr++ )
if ( ( *ptr )->is_data_record( buff_ptr ) == YES )
return( *ptr ); /* Successful return. */
puts( buff_ptr ); /* Echo non-hex-record line. */
}
return( ( Rec_vitals * ) NULL ); /* Unsuccessful return. */
}
/**** get_ndigit_hex *******************************************************
*
* Expects: Pointer to first ASCII hexadecimal digit, number of digits.
*
* Returns: Value of hexadecimal string as an unsigned long.
*
*******************************************************************************/
Ulong get_ndigit_hex( char * cptr, int digits )
{
Ulong value;
for ( value = 0 ; --digits >= 0 ; cptr++ )
value = ( value * 16L ) + HEX_DIGIT( *cptr );
return( value );
}

View File

@@ -0,0 +1,32 @@
#
# $Id$
#
Misc. support tools for RTEMS workspaces.
More will be added later as they are converted from Teamware
to CVS.
install-if-change
Smart install script that also can append suffixes as it
installs (suffixes used for debug and profile variants).
Requires bash or ksh.
rcs-clean
deletes all files from the current directory that can be
re-created from RCS. Careful to not delete locked files.
May be used by 'gmake clobber'
lock-directory
unlock-directory
traverse a directory structure making it unwritable.
Useful to keep people from accidentally overwriting
"released" trees if they get confused about which
module they have loaded.
rtems-glom
glom together all the rtems libraries in order to simplify
the link line used by applications.
Produces rtems.rel.
Not used by the RTEMS src tree at all.
Strictly optional.

364
tools/build/src/cklength.c Normal file
View File

@@ -0,0 +1,364 @@
/*
* cklength - check the length of lines in a file
*
* This program check to see if the files passed to it on the command line
* contain a line which exceeds the maximum allowable length. The default
* maximum line length is 80.
*
* usage: cklength [ -v ] [ arg ... ] files...
* -l length -- maximum line length
* -v -- verbose
*
* $Id$
* $Log$
*/
#define GETOPTARGS "l:nNv"
char *USAGE = "\
usage: cklength [ -v ] [ arg ... ] files... \n\
-l length -- maximum line length\n\
-n -- report line numbers for offending lines\n\
-N -- report line numbers and length for offending lines\n\
-v -- verbose\n\
\n\
Print the name of files which have at least 1 line which exceeds the\n\
maximum line length. The default maximum line length is 80.\n\
";
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <memory.h>
#include <stdarg.h>
#define BUFFER_SIZE 512
#define SUCCESS 0
#define FAILURE -1
#define Failed(x) (((int) (x)) == FAILURE)
#define TRUE 1
#define FALSE 0
#define STREQ(a,b) (strcmp(a,b) == 0)
#define NUMELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
/*
* Definitions for unsigned "ints"; especially for use in data structures
* that will be shared among (potentially) different cpu's (we punt on
* byte ordering problems tho)
*/
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
/*
* vars controlled by command line options
*/
int verbose = FALSE; /* be verbose */
int report_line_numbers = FALSE; /* report line numbers of offenders */
int report_line_length = FALSE; /* report line length of offenders */
int line_length = 80; /* maximum allowable line length */
extern char *optarg; /* getopt(3) control vars */
extern int optind, opterr;
extern int errno;
char *progname; /* for error() */
int process(char *arg);
void error(int errn, ...);
long getparm(char *s, long min, long max, char *msg);
#define ERR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */
#define ERR_FATAL (ERR_ERRNO / 2) /* fatal error ; no return */
#define ERR_ABORT (ERR_ERRNO / 4) /* fatal error ; abort */
#define ERR_MASK (ERR_ERRNO | ERR_FATAL | ERR_ABORT) /* all */
#define stol(p) strtol(p, (char **) NULL, 0)
int Open(), Read(), Write();
int
main(int argc, char **argv, char **env)
{
register int c;
int showusage = FALSE; /* usage error? */
int rc = 0;
/*
* figure out invocation leaf-name
*/
if ((progname = strrchr(argv[0], '/')) == (char *) NULL)
progname = argv[0];
else
progname++;
argv[0] = progname; /* for getopt err reporting */
/*
* Check options and arguments.
*/
opterr = 0; /* we'll report all errors */
while ((c = getopt(argc, argv, GETOPTARGS)) != EOF)
switch (c)
{
case 'l': /* line length */
line_length = atoi( optarg );
if ( line_length < 0 || line_length > BUFFER_SIZE )
error(ERR_FATAL, "(%d) is illegal line length\n",line_length);
break;
case 'n': /* toggle report_line_numbers */
report_line_numbers = ! report_line_numbers;
break;
case 'N': /* toggle both reports */
report_line_numbers = ! report_line_numbers;
report_line_length = ! report_line_length;
break;
case 'v': /* toggle verbose */
verbose = ! verbose;
break;
case '?':
showusage = TRUE;
}
if (showusage)
{
(void) fprintf(stderr, "%s", USAGE);
exit(1);
}
/*
* traverse and process the arguments
*/
for ( ; argv[optind]; optind++)
if (Failed(process(argv[optind])))
rc = FAILURE;
return rc;
}
/*
* process(arg)
*/
int
process(char *arg)
{
FILE *in;
char *bptr;
char buffer[ BUFFER_SIZE ];
int line_number;
int length;
int count;
int rc = SUCCESS; /* succeed by default */
in = fopen( arg, "r" );
if (!in)
error( ERR_ERRNO | ERR_FATAL, "Unable to open file (%s)\n", arg );
count = 0;
for ( line_number=1 ; ; line_number++ ) {
bptr = fgets( buffer, BUFFER_SIZE, in );
if (!bptr)
break;
/*
* Don't count the carriage return.
*/
length = strlen( buffer ) - 1;
if ( length <= line_length )
continue;
if ( count == 0 ) {
fprintf( stderr, "%s\n", arg );
if ( !report_line_numbers )
break;
}
if ( verbose )
fprintf( stderr, "TOO LONG:%d: %s\n", line_number, buffer );
if ( report_line_numbers ) {
if ( report_line_length )
fprintf( stderr, "%d: %d\n" , line_number, length );
else
fprintf( stderr, "%d\n" , line_number );
}
count++;
}
fclose( in );
return rc;
}
/*
* error(errn, arglist)
* report an error to stderr using printf(3) conventions.
* Any output is preceded by '<progname>: '
*
* Uses ERR_FATAL bit to request exit(errn)
* ERR_ABORT to request abort()
* ERR_ERRNO to indicate use of errno instead of argument.
*
* If resulting 'errn' is non-zero, it is assumed to be an 'errno' and its
* associated error message is appended to the output.
*/
/*VARARGS*/
void
error(int error_flag, ...)
{
va_list arglist;
register char *format;
extern char *sys_errlist[];
extern int sys_nerr;
int local_errno;
extern int errno;
(void) fflush(stdout); /* in case stdout/stderr same */
local_errno = error_flag & ~ERR_MASK;
if (error_flag & ERR_ERRNO) /* use errno? */
local_errno = errno;
va_start(arglist, error_flag);
format = va_arg(arglist, char *);
(void) fprintf(stderr, "%s: ", progname);
(void) vfprintf(stderr, format, arglist);
va_end(arglist);
if (local_errno)
if ((local_errno > 0) && (local_errno < sys_nerr))
(void) fprintf(stderr, " (%s)\n", sys_errlist[local_errno]);
else
(void) fprintf(stderr, " (unknown errno=%d)\n", local_errno);
else
(void) fprintf(stderr, "\n");
(void) fflush(stderr);
if (error_flag & (ERR_FATAL | ERR_ABORT))
{
if (error_flag & ERR_FATAL)
{
error(0, local_errno ? "fatal error, exiting" : "exiting");
exit(local_errno);
}
else
{
error(0, "fatal error, aborting");
abort();
}
}
}
long
getparm(char *s,
long min,
long max,
char *msg)
{
long val;
if ( ! strchr("0123456789-", *s))
{
error(ERR_FATAL, "'%s' is not a number", s);
return min;
}
val = strtol(s, (char **) NULL, 0);
if ((val < min) || (val > max))
{
if (min == max)
error(ERR_FATAL, "%s can only be %ld", s, min);
else
error(ERR_FATAL, "%s must be between %ld and %ld", msg, min, max);
}
return val;
}
/*
* Open()
* Perform open(2), returning the file descriptor. Prints
* error message if open fails.
*/
int
Open(char *file,
int oflag,
int mode)
{
int O_fd;
if (Failed(O_fd = open(file, oflag, mode)))
error(
ERR_ERRNO | ERR_FATAL,
"open('%s', 0x%x, 0%o) failed", file, oflag, mode
);
return O_fd;
}
/*
* Read()
* Perform read(2); prints error message if fails.
*/
int
Read(int file,
char *buffer,
unsigned int count)
{
int nbytes;
if (Failed(nbytes = read(file, buffer, count)))
error(
ERR_ERRNO | ERR_FATAL,
"read(%d, 0x%x, %d) failed", file, buffer, count
);
return nbytes;
}
/*
* Write()
* Perform write(2); prints error message if fails.
*/
int
Write(int file,
char *buffer,
unsigned int count)
{
int nbytes;
if (Failed(nbytes = write(file, buffer, count)))
error(
ERR_ERRNO | ERR_FATAL,
"write(%d, 0x%x, %d) failed", file, buffer, count
);
return nbytes;
}

351
tools/build/src/eolstrip.c Normal file
View File

@@ -0,0 +1,351 @@
/*
* eolstrip - strip white space from end of lines
*
* This program strips the white space from the end of every line in the
* specified program.
*
* usage: eolstrip [ -v ] [ arg ... ] files...
* -v -- verbose
*
* $Id$
* $Log$
*/
#define GETOPTARGS "vt"
char *USAGE = "\
usage: cklength [ -v ] [ arg ... ] files... \n\
-v -- verbose\n\
-t -- test only .. DO NOT OVERWRITE FILE!!!\n\
\n\
Strip the white space from the end of every line on the list of files.\n\
";
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <memory.h>
#include <stdarg.h>
#define BUFFER_SIZE 2048
#define MAX_PATH 2048
#define SUCCESS 0
#define FAILURE -1
#define Failed(x) (((int) (x)) == FAILURE)
#define TRUE 1
#define FALSE 0
#define STREQ(a,b) (strcmp(a,b) == 0)
#define NUMELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
/*
* Definitions for unsigned "ints"; especially for use in data structures
* that will be shared among (potentially) different cpu's (we punt on
* byte ordering problems tho)
*/
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
/*
* vars controlled by command line options
*/
int verbose = FALSE; /* be verbose */
int test_only = FALSE; /* test only */
extern char *optarg; /* getopt(3) control vars */
extern int optind, opterr;
extern int errno;
char *progname; /* for error() */
int process(char *arg);
void error(int errn, ...);
long getparm(char *s, long min, long max, char *msg);
#define ERR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */
#define ERR_FATAL (ERR_ERRNO / 2) /* fatal error ; no return */
#define ERR_ABORT (ERR_ERRNO / 4) /* fatal error ; abort */
#define ERR_MASK (ERR_ERRNO | ERR_FATAL | ERR_ABORT) /* all */
#define stol(p) strtol(p, (char **) NULL, 0)
int Open(), Read(), Write();
int
main(int argc, char **argv, char **env)
{
register int c;
int showusage = FALSE; /* usage error? */
int rc = 0;
/*
* figure out invocation leaf-name
*/
if ((progname = strrchr(argv[0], '/')) == (char *) NULL)
progname = argv[0];
else
progname++;
argv[0] = progname; /* for getopt err reporting */
/*
* Check options and arguments.
*/
opterr = 0; /* we'll report all errors */
while ((c = getopt(argc, argv, GETOPTARGS)) != EOF)
switch (c)
{
case 't': /* toggle test only mode */
test_only = ! test_only;
break;
case 'v': /* toggle verbose */
verbose = ! verbose;
break;
case '?':
showusage = TRUE;
}
if (showusage)
{
(void) fprintf(stderr, "%s", USAGE);
exit(1);
}
/*
* traverse and process the arguments
*/
for ( ; argv[optind]; optind++)
if (Failed(process(argv[optind])))
rc = FAILURE;
return rc;
}
/*
* process(arg)
*/
int
process(char *arg)
{
FILE *in;
FILE *out = (FILE *) 0;
char outname[ MAX_PATH ];
char *bptr;
char buffer[ BUFFER_SIZE ];
int length;
int line_number;
int rc = SUCCESS; /* succeed by default */
in = fopen( arg, "r" );
if (!in)
error( ERR_ERRNO | ERR_FATAL, "Unable to open file (%s)\n", arg );
if ( !test_only ) {
sprintf( outname, "%s.eoltmp", arg );
out = fopen( outname, "w" );
if (!out)
error( ERR_ERRNO | ERR_FATAL, "Unable to open file (%s)\n", arg );
}
if ( verbose )
fprintf( stderr, "Processing %s\n", arg );
for ( line_number=1 ; ; line_number++ ) {
bptr = fgets( buffer, BUFFER_SIZE, in );
if (!bptr)
break;
/*
* Don't count the carriage return.
*/
length = strlen( buffer ) - 1;
if ( buffer[ length ] != '\n' )
error(ERR_ERRNO|ERR_FATAL, "Line %d too long in %s\n", line_number, arg);
while ( isspace( buffer[ length ] ) )
buffer[ length-- ] = '\0';
if ( test_only ) {
fprintf( stderr, "%s\n", arg );
break;
}
fprintf( out, "%s\n", buffer );
}
fclose( in );
if ( !test_only ) {
fclose( out );
rename( outname, arg );
}
return rc;
}
/*
* error(errn, arglist)
* report an error to stderr using printf(3) conventions.
* Any output is preceded by '<progname>: '
*
* Uses ERR_FATAL bit to request exit(errn)
* ERR_ABORT to request abort()
* ERR_ERRNO to indicate use of errno instead of argument.
*
* If resulting 'errn' is non-zero, it is assumed to be an 'errno' and its
* associated error message is appended to the output.
*/
/*VARARGS*/
void
error(int error_flag, ...)
{
va_list arglist;
register char *format;
extern char *sys_errlist[];
extern int sys_nerr;
int local_errno;
extern int errno;
(void) fflush(stdout); /* in case stdout/stderr same */
local_errno = error_flag & ~ERR_MASK;
if (error_flag & ERR_ERRNO) /* use errno? */
local_errno = errno;
va_start(arglist, error_flag);
format = va_arg(arglist, char *);
(void) fprintf(stderr, "%s: ", progname);
(void) vfprintf(stderr, format, arglist);
va_end(arglist);
if (local_errno)
if ((local_errno > 0) && (local_errno < sys_nerr))
(void) fprintf(stderr, " (%s)\n", sys_errlist[local_errno]);
else
(void) fprintf(stderr, " (unknown errno=%d)\n", local_errno);
else
(void) fprintf(stderr, "\n");
(void) fflush(stderr);
if (error_flag & (ERR_FATAL | ERR_ABORT))
{
if (error_flag & ERR_FATAL)
{
error(0, local_errno ? "fatal error, exiting" : "exiting");
exit(local_errno);
}
else
{
error(0, "fatal error, aborting");
abort();
}
}
}
long
getparm(char *s,
long min,
long max,
char *msg)
{
long val;
if ( ! strchr("0123456789-", *s))
{
error(ERR_FATAL, "'%s' is not a number", s);
return min;
}
val = strtol(s, (char **) NULL, 0);
if ((val < min) || (val > max))
{
if (min == max)
error(ERR_FATAL, "%s can only be %ld", s, min);
else
error(ERR_FATAL, "%s must be between %ld and %ld", msg, min, max);
}
return val;
}
/*
* Open()
* Perform open(2), returning the file descriptor. Prints
* error message if open fails.
*/
int
Open(char *file,
int oflag,
int mode)
{
int O_fd;
if (Failed(O_fd = open(file, oflag, mode)))
error(
ERR_ERRNO | ERR_FATAL,
"open('%s', 0x%x, 0%o) failed", file, oflag, mode
);
return O_fd;
}
/*
* Read()
* Perform read(2); prints error message if fails.
*/
int
Read(int file,
char *buffer,
unsigned int count)
{
int nbytes;
if (Failed(nbytes = read(file, buffer, count)))
error(
ERR_ERRNO | ERR_FATAL,
"read(%d, 0x%x, %d) failed", file, buffer, count
);
return nbytes;
}
/*
* Write()
* Perform write(2); prints error message if fails.
*/
int
Write(int file,
char *buffer,
unsigned int count)
{
int nbytes;
if (Failed(nbytes = write(file, buffer, count)))
error(
ERR_ERRNO | ERR_FATAL,
"write(%d, 0x%x, %d) failed", file, buffer, count
);
return nbytes;
}

513
tools/build/src/packhex.c Normal file
View File

@@ -0,0 +1,513 @@
/***** P A C K H E X . C ************************************************
*
* Packhex is a hex-file compaction utility. It attempts to concatenate
* hex records to produce more size-efficient packaging.
*
* Limitations: Input files must be correctly formatted. This utility
* is not robust enough to detect hex-record formatting
* errors.
*
* Published: 5/93 Embedded Systems magazine
*
* Compiler: Microsoft C 6.0
* cl /F 1000 packhex.c
*
*
* $Id$
*
**************************************************************************/
/* #define SMALLER_RECORDS */
#ifdef SMALLER_RECORDS
#define MAX_LEN_S1_RECS 128
#define MAX_LEN_S2_RECS 128
#define MAX_LEN_S3_RECS 128
#else
#define MAX_LEN_S1_RECS 252
#define MAX_LEN_S2_RECS 251
#define MAX_LEN_S3_RECS 250
#endif
/*--------------------------------- includes ---------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__unix__) && !defined(EXIT_FAILURE)
#define EXIT_FAILURE -1
#define EXIT_SUCCESS 0
#endif
/*--------------------------------- defines ----------------------------------*/
#define YES 1
#define MAX_LINE_SIZE 600
#define EOS '\0'
/*---------------------------------- macros ----------------------------------*/
/* Convert ASCII hexadecimal digit to value. */
#define HEX_DIGIT( C ) ( ( ( ( C ) > '9' ) ? ( C ) + 25 : ( C ) ) & 0xF )
/*--------------------------------- typedefs ---------------------------------*/
typedef unsigned char Boolean;
typedef unsigned char Uchar;
typedef unsigned int Uint;
typedef unsigned long Ulong;
typedef struct /* Functions and constant returning Hex-record vital stats. */
{
Boolean ( *is_data_record )( char * );
Ulong ( *get_address )( char * );
Uint ( *get_data_count )( char * );
const Uint max_data_count;
char *( *get_data_start )( char * );
void ( *put_data_record )( Uint, Ulong, char * );
} Rec_vitals;
/*--------------------------- function prototypes ----------------------------*/
Rec_vitals * identify_first_data_record( char * );
Ulong get_ndigit_hex( char *, int );
/*----------------------------- Intel Hex format -----------------------------*/
/*
* Intel Hex data-record layout
*
* :aabbbbccd...dee
*
* : - header character
* aa - record data byte count, a 2-digit hex value
* bbbb - record address, a 4-digit hex value
* cc - record type, a 2-digit hex value:
* "00" is a data record
* "01" is an end-of-data record
* "02" is an extended-address record
* "03" is a start record
* d...d - data (always an even number of chars)
* ee - record checksum, a 2-digit hex value
* checksum = 2's complement
* [ (sum of bytes: aabbbbccd...d) modulo 256 ]
*/
Boolean is_intel_data_rec( char * rec_str )
{
return( ( rec_str[ 0 ] == ':' ) && ( rec_str[ 8 ] == '0' ) );
}
Uint get_intel_rec_data_count( char * rec_str )
{
return( ( Uint ) get_ndigit_hex( rec_str + 1, 2 ) );
}
Ulong get_intel_rec_address( char * rec_str )
{
return( get_ndigit_hex( rec_str + 3, 4 ) );
}
char * get_intel_rec_data_start( char * rec_str )
{
return( rec_str + 9 );
}
void put_intel_data_rec( Uint count, Ulong address, char * data_str )
{
char *ptr;
Uint sum = count + ( address >> 8 & 0xff ) + ( address & 0xff );
for ( ptr = data_str ; *ptr != EOS ; ptr += 2 )
sum += ( Uint ) get_ndigit_hex( ptr, 2 );
printf(
":%02X%04lX00%s%02X\n", count, address, data_str, (~sum + 1) & 0xff
);
}
Rec_vitals intel_hex =
{
is_intel_data_rec,
get_intel_rec_address,
get_intel_rec_data_count,
255, /* Maximum data bytes in a record. */
get_intel_rec_data_start,
put_intel_data_rec
};
/*------------------------- Motorola S1-record format ------------------------*/
/*
* Motorola S-record data-record layout
*
* Sabbc...cd...dee
*
* S - header character
* a - record type, a 1-digit value:
* "0" is a header record
* "1" is a 2-byte-address data record
* "2" is a 3-byte-address data record
* "3" is a 4-byte-address data record
* "7" is a 4-byte-address end-of-data record
* "8" is a 3-byte-address end-of-data record
* "9" is a 2-byte-address end-of-data record
* bb - record length in bytes, a 2-digit hex value
* (record length doesn't count the header/type
* chars and checksum byte)
* c...c - record address, a 4-, 6-, or 8-digit value,
* depending on record type
* d...d - data (always an even number of chars)
* ee - record checksum, a 2-digit hex value
* checksum = 1's complement
* [ (sum of all bytes: bbc..cd...d) modulo 256 ]
*/
#define S1_COUNT_OFFSET 3
Boolean is_moto_s1_data_rec( char * rec_str )
{
return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '1' ) );
}
Uint get_moto_s1_rec_data_count( char * rec_str )
{
return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S1_COUNT_OFFSET );
}
Ulong get_moto_s1_rec_address( char * rec_str )
{
return( get_ndigit_hex( rec_str + 4, 4 ) );
}
char * get_moto_s1_rec_data_start( char * rec_str )
{
return( rec_str + 8 );
}
void put_moto_s1_data_rec( Uint count, Ulong address, char * data_str )
{
char *ptr;
Uint sum = S1_COUNT_OFFSET + count +
( address >> 8 & 0xff ) + ( address & 0xff );
for ( ptr = data_str ; *ptr != EOS ; ptr += 2 )
sum += ( Uint ) get_ndigit_hex( ptr, 2 );
printf(
"S1%02X%04lX%s%02X\n",
count + S1_COUNT_OFFSET, address, data_str, ~sum & 0xff
);
}
Rec_vitals motorola_s1_rec =
{
is_moto_s1_data_rec,
get_moto_s1_rec_address,
get_moto_s1_rec_data_count,
MAX_LEN_S1_RECS, /* Maximum data bytes in a record. */
get_moto_s1_rec_data_start,
put_moto_s1_data_rec
};
/*------------------------- Motorola S2-record format ------------------------*/
#define S2_COUNT_OFFSET 4
Boolean is_moto_s2_data_rec( char * rec_str )
{
return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '2' ) );
}
Uint get_moto_s2_rec_data_count( char * rec_str )
{
return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S2_COUNT_OFFSET );
}
Ulong get_moto_s2_rec_address( char * rec_str )
{
return( get_ndigit_hex( rec_str + 4, 6 ) );
}
char * get_moto_s2_rec_data_start( char * rec_str )
{
return( rec_str + 10 );
}
void put_moto_s2_data_rec( Uint count, Ulong address, char * data_str )
{
char *ptr;
Uint sum = S2_COUNT_OFFSET + count + ( address >> 16 & 0xff ) +
( address >> 8 & 0xff ) +
( address & 0xff );
for ( ptr = data_str ; *ptr != EOS ; ptr += 2 )
sum += ( Uint ) get_ndigit_hex( ptr, 2 );
printf(
"S2%02X%06lX%s%02X\n",
count + S2_COUNT_OFFSET, address, data_str, ~sum & 0xff
);
}
Rec_vitals motorola_s2_rec =
{
is_moto_s2_data_rec,
get_moto_s2_rec_address,
get_moto_s2_rec_data_count,
MAX_LEN_S2_RECS, /* Maximum data bytes in a record. */
get_moto_s2_rec_data_start,
put_moto_s2_data_rec
};
/*------------------------- Motorola S3-record format ------------------------*/
#define S3_COUNT_OFFSET 5
Boolean is_moto_s3_data_rec( char * rec_str )
{
return ( ( rec_str[ 0 ] == 'S' ) && ( rec_str[ 1 ] == '3' ) );
}
Uint get_moto_s3_rec_data_count( char * rec_str )
{
return( ( Uint ) get_ndigit_hex( rec_str + 2, 2 ) - S3_COUNT_OFFSET );
}
Ulong get_moto_s3_rec_address( char * rec_str )
{
return( get_ndigit_hex( rec_str + 4, 8 ) );
}
char * get_moto_s3_rec_data_start( char * rec_str )
{
return( rec_str + 12 );
}
void put_moto_s3_data_rec( Uint count, Ulong address, char * data_str )
{
char *ptr;
Uint sum = S3_COUNT_OFFSET + count + ( address >> 24 & 0xff ) +
( address >> 16 & 0xff ) +
( address >> 8 & 0xff ) +
( address & 0xff );
for ( ptr = data_str ; *ptr != EOS ; ptr += 2 )
sum += ( Uint ) get_ndigit_hex( ptr, 2 );
printf(
"S3%02X%08lX%s%02X\n",
count + S3_COUNT_OFFSET, address, data_str, ~sum & 0xff
);
}
Rec_vitals motorola_s3_rec =
{
is_moto_s3_data_rec,
get_moto_s3_rec_address,
get_moto_s3_rec_data_count,
MAX_LEN_S3_RECS, /* Maximum data bytes in a record. */
get_moto_s3_rec_data_start,
put_moto_s3_data_rec
};
/*-------------------- Put your favorite hex format here ---------------------*/
/*
* * * * The following is a template for an additional hex format: * * *
*
*
* Boolean is_X_data_rec( char * rec_str ) {}
*
* Uint get_X_rec_data_count( char * rec_str ) {}
*
* Ulong get_X_rec_address( char * rec_str ) {}
*
* char * get_X_rec_data_start( char * rec_str ) {}
*
* void put_X_data_rec( Uint count, Ulong address, char * data_str ) {}
*
* Rec_vitals X_rec =
* {
* is_X_data_rec,
* get_X_rec_address,
* get_X_rec_data_count,
* MAXIMUM DATA BYTES IN A RECORD,
* get_X_rec_data_start,
* put_X_data_rec
* };
*
*/
/*----------------------------------------------------------------------------*/
/*
* Put address of additional Rec_vitals structures
* in this array, before the NULL entry.
*/
Rec_vitals *formats[] =
{
&intel_hex,
&motorola_s1_rec,
&motorola_s2_rec,
&motorola_s3_rec,
( Rec_vitals * ) NULL
};
/**** main *****************************************************************
*
*
* Expects: Nothing (no command-line parameters).
*
* Returns: Exit status (EXIT_SUCCESS or EXIT_FAILURE).
*
* Reads hex records on the standard input and attempts to
* splice adjacent data fields together. Results appear on
* the standard output.
*
*******************************************************************************/
void main( void )
{
char inbuff[ MAX_LINE_SIZE ], outbuff[ MAX_LINE_SIZE ];
char *in_dptr, *out_dptr;
int d_total, d_count, d_excess, n;
Ulong in_rec_addr, out_rec_addr = 0;
Rec_vitals *rptr;
/* Sift through file until first hex record is identified. */
if ( ( rptr = identify_first_data_record( inbuff ) ) == NULL )
{
fputs( "No hex records found.\n", stderr );
exit( EXIT_FAILURE );
}
/* Attempt data-record splicing until end-of-file is reached. */
d_total = 0;
do
{
if ( rptr->is_data_record( inbuff ) == YES )
{ /* Input record is a data record. */
d_count = rptr->get_data_count( inbuff );
in_rec_addr = rptr->get_address( inbuff );
in_dptr = rptr->get_data_start( inbuff );
if ( d_total == 0 || in_rec_addr != out_rec_addr + d_total )
{ /* Begin a new output record. */
if ( d_total != 0 )
rptr->put_data_record( d_total, out_rec_addr, outbuff );
out_dptr = outbuff;
n = d_total = d_count;
out_rec_addr = in_rec_addr;
}
else if
( ( d_excess = d_total + d_count - rptr->max_data_count ) > 0 )
{ /* Output a maximum-length record, then start a new record. */
strncat( outbuff, in_dptr, 2 * ( d_count - d_excess ) );
rptr->put_data_record(
rptr->max_data_count, out_rec_addr, outbuff
);
in_dptr += 2 * ( d_count - d_excess );
out_dptr = outbuff;
n = d_total = d_excess;
out_rec_addr += rptr->max_data_count;
}
else
{ /* Append input record's data field with accumulated data. */
out_dptr = outbuff + ( 2 * d_total );
d_total += n = d_count;
}
strncpy( out_dptr, in_dptr, 2 * n );
out_dptr[ 2 * n ] = EOS;
}
else
{ /* Not a data record;
* flush accumulated data then echo non-data record.
*/
if ( d_total != 0 )
{
rptr->put_data_record( d_total, out_rec_addr, outbuff );
d_total = 0;
}
puts( inbuff );
}
} while ( gets( inbuff ) != NULL );
exit( EXIT_SUCCESS );
}
/**** identify_first_data_record *******************************************
*
* Expects: Pointer to hex-record line buffer.
*
* Returns: Pointer to hex-record structure (NULL if no match found).
*
* Reads the standard input, line by line, searching for a valid
* record header character. If a valid header is found, a pointer
* to the hex-record's type structure is returned, otherwise NULL.
*
* The input-stream pointer is left pointing to the first valid hex record.
*
*******************************************************************************/
Rec_vitals * identify_first_data_record( char * buff_ptr )
{
Rec_vitals ** ptr;
while ( gets( buff_ptr ) != NULL )
{
for ( ptr = formats ; *ptr != ( Rec_vitals * ) NULL ; ptr++ )
if ( ( *ptr )->is_data_record( buff_ptr ) == YES )
return( *ptr ); /* Successful return. */
puts( buff_ptr ); /* Echo non-hex-record line. */
}
return( ( Rec_vitals * ) NULL ); /* Unsuccessful return. */
}
/**** get_ndigit_hex *******************************************************
*
* Expects: Pointer to first ASCII hexadecimal digit, number of digits.
*
* Returns: Value of hexadecimal string as an unsigned long.
*
*******************************************************************************/
Ulong get_ndigit_hex( char * cptr, int digits )
{
Ulong value;
for ( value = 0 ; --digits >= 0 ; cptr++ )
value = ( value * 16L ) + HEX_DIGIT( *cptr );
return( value );
}

719
tools/build/src/unhex.c Normal file
View File

@@ -0,0 +1,719 @@
/*
* unhex
* convert a hex file to binary equivalent. If more than one file name
* is given, then the output will be logically concatenated together.
* stdin and stdout are defaults. Verbose will enable checksum output.
*
* Supported input formats are Intel hex, Motorola S records, and TI 'B'
* records.
*
* Intel hex input format is
* Byte
* 1 Colon :
* 2..3 Record length, eg: "20"
* 4..7 load address nibbles
* 8..9 record type: "00" (data) or "02" base addr
* 10..x data bytes in ascii-hex
* x+1..x+2 cksum (2's compl of (len+addr+data))
* x+3 \n -- newline
*/
char *USAGE = "\
usage: unhex [-va] [ -o file ] [ file [file ... ] ]\n\
-v -- verbose\n\
-a base -- 1st byte of output corresponds to this address\n\
-l -- linear, just writes data out\n\
-o file -- output file; must not be input file\n\
-F k_bits -- \"holes\" in input will be filled with 0xFF's\n\
up to \"k_bits\" * 1024 bits\n\
";
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#define OK 0
#define FAILURE (-1)
#define Failed(x) ((x) == FAILURE)
#define TRUE 1
#define FALSE 0
typedef char bool;
#define STREQ(a,b) (strcmp(a,b) == 0)
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
/*
* Pick out designated bytes
*/
#define B0(x) ((x) & 0xff)
#define B1(x) B0((x) >> 8)
#define B2(x) B0((x) >> 16)
#define B3(x) B0((x) >> 24)
typedef struct buffer_rec {
u32 dl_destaddr;
u32 dl_jumpaddr;
int dl_count;
u8 dl_buf[512];
} buffer_rec;
/*
* vars controlled by command line options
*/
bool verbose = FALSE; /* be verbose */
bool linear = FALSE; /* just write out linear data */
char *outfilename = "-"; /* default output is stdout */
u32 base = 0L; /* base address */
u32 FFfill = 0L; /* how far to fill w 0xFF's */
extern char *optarg; /* getopt(3) control vars */
extern int optind;
extern int errno;
char *progname; /* for error() */
void error(int errn, ...);
#define ERR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */
#define ERR_FATAL (ERR_ERRNO / 2) /* error is fatal; no return */
#define ERR_ABORT (ERR_ERRNO / 4) /* error is fatal; abort */
#define ERR_MASK (ERR_ERRNO | ERR_FATAL | ERR_ABORT) /* all */
#define stol(p) strtol(p, (char **) NULL, 0)
int unhex(FILE *ifp, char *inm, FILE *ofp, char *onm);
int convert_Intel_records(FILE *ifp, char *inm, FILE *ofp, char *onm);
int convert_S_records(FILE *ifp, char *inm, FILE *ofp, char *onm);
int convert_TI_records(FILE *ifp, char *inm, FILE *ofp, char *onm);
void write_record(buffer_rec *tb, FILE *fp);
int getnibble(char **p);
int getbyte(char **p);
long getNbytes(char **p, int n);
void badformat(char *s, char *fname, char *msg);
#define get1bytes(p) ((int) getbyte(p))
#define get2bytes(p) ((int) getNbytes(p, 2))
#define get3bytes(p) getNbytes(p, 3)
#define get4bytes(p) getNbytes(p, 4)
char *BADADDR = "Invalid record address";
char *BADLEN = "Invalid record length";
char *BADBASE = "Bad base or starting address";
char *BADFMT = "Unrecognized record type";
char *BADDATA = "Invalid data byte";
char *BADCSUM = "Invalid checksum";
char *MISCSUM = "Checksum mismatch";
char *BADTYPE = "Unrecognized record type";
char *MISTYPE = "Incompatible record types";
int
main(argc, argv)
int argc;
char **argv;
{
register int c;
bool showusage = FALSE; /* usage error? */
int rc = 0;
FILE *outfp, *infp;
/*
* figure out invocation leaf-name
*/
if ((progname = strrchr(argv[0], '/')) == (char *) NULL)
progname = argv[0];
else
progname++;
argv[0] = progname; /* for getopt err reporting */
/*
* Check options and arguments.
*/
progname = argv[0];
while ((c = getopt(argc, argv, "F:a:o:vl")) != EOF)
switch (c)
{
case 'a': /* base address */
base = stol(optarg);
break;
case 'l': /* linear output */
linear = TRUE;
break;
case 'v': /* toggle verbose */
verbose = ! verbose;
break;
case 'o': /* output file */
outfilename = optarg;
break;
case 'F': /* 0xFF fill amount (bytes) */
FFfill = stol(optarg) * 1024L / 8L;
break;
case '?':
showusage = TRUE;
}
if (showusage)
{
(void) fprintf(stderr, "%s", USAGE);
exit(1);
}
if (linear && (base != 0))
{
error(0, "-l and -a may not be specified in combination");
exit(1);
}
if (STREQ(outfilename, "-"))
{
outfp = stdout;
outfilename = "stdout";
}
else
if ((outfp = fopen(outfilename, "w")) == (FILE *) NULL)
{
error(-1, "couldn't open '%s' for output", outfilename);
exit(1);
}
/*
* Now process the input files (or stdin, if none specified)
*/
if (argv[optind] == (char *) NULL) /* just stdin */
exit(unhex(stdin, "stdin", outfp, outfilename));
else
for (; (optarg = argv[optind]); optind++)
{
if (STREQ(optarg, "-"))
rc += unhex(stdin, "stdin", outfp, outfilename);
else
{
if ((infp = fopen(optarg, "r")) == (FILE *) NULL)
{
error(-1, "couldn't open '%s' for input", optarg);
exit(1);
}
rc += unhex(infp, optarg, outfp, outfilename);
}
}
return(rc);
}
u16 filesum;
int
unhex(FILE *ifp,
char *inm,
FILE *ofp,
char *onm)
{
int c;
filesum = 0;
/*
* Make sure holes will be filled with 0xFF's if requested. We
* do this the easy way by just filling the file with FF's before
* getting started. To do it more optimally would be quite a bit
* more difficult since the user can skip around as much as he/she
* likes in the input hex file addressing.
*
* We'll clean this up later (after this program has run) with
* 'stripffs'
*/
if (FFfill)
{
(void) fseek(ofp, 0, 0);
for (c = FFfill; c > 0; c--)
(void) fputc(0xFF, ofp);
}
/*
* Read the first char from file and determine record types
*/
if ((c = getc(ifp)) != EOF)
{
ungetc(c, ifp);
switch(c)
{
case 'S':
convert_S_records(ifp, inm, ofp, onm);
break;
case ':':
convert_Intel_records(ifp, inm, ofp, onm);
break;
case '9':
case 'B':
convert_TI_records(ifp, inm, ofp, onm);
break;
default:
{
char tmp[2];
tmp[0] = c; tmp[1] = 0;
badformat(tmp, inm, BADFMT);
}
}
}
if (verbose)
fprintf(stderr, "'%s' checksum is 0x%04x\n", inm, filesum);
return 0;
}
int
convert_Intel_records(
FILE *ifp,
char *inm,
FILE *ofp,
char *onm)
{
char buff[512];
char *p;
u8 cksum;
int incksum;
int c;
int rectype; /* record type */
int len; /* data length of current line */
u32 addr;
u32 base_address = 0;
bool endrecord = FALSE;
buffer_rec tb;
while ( ! endrecord && (fgets(buff, sizeof(buff), ifp)))
{
p = &buff[0];
if (p[strlen(p)-1] == '\n') /* get rid of newline */
p[strlen(p)-1] = '\0';
if (p[strlen(p)-1] == '\r') /* get rid of any CR */
p[strlen(p)-1] = '\0';
tb.dl_count = 0;
if (*p != ':')
badformat(p, inm, BADFMT);
p++;
if ((len = getbyte(&p)) == -1) /* record len */
badformat(buff, inm, BADLEN);
if ((addr = get2bytes(&p)) == -1L) /* record addr */
badformat(buff, inm, BADADDR);
rectype = getbyte(&p);
cksum = len + B0(addr) + B1(addr) + rectype;
switch (rectype)
{
case 0x00: /* normal data record */
tb.dl_destaddr = base_address + addr;
while (len--)
{
if ((c = getbyte(&p)) == -1)
badformat(buff, inm, BADDATA);
cksum += c;
filesum += c;
tb.dl_buf[tb.dl_count++] = c;
}
break;
case 0x01: /* execution start address */
base_address = addr;
endrecord = TRUE;
break;
case 0x02: /* new base */
if ((base_address = get2bytes(&p)) == -1L)
badformat(buff, inm, BADBASE);
cksum += B0(base_address) + B1(base_address);
base_address <<= 4;
break;
case 0x03: /* seg/off execution start address */
{
u32 seg, off;
seg = get2bytes(&p);
off = get2bytes(&p);
if ((seg == -1L) || (off == -1L))
badformat(buff, inm, BADADDR);
cksum += B0(seg) + B1(seg) + B0(off) + B1(off);
tb.dl_jumpaddr = (seg << 4) + off;
break;
}
default:
error(0, "unknown Intel-hex record type: 0x%02x", rectype);
badformat(buff, inm, BADTYPE);
}
/*
* Verify checksums are correct in file.
*/
cksum = (-cksum) & 0xff;
if ((incksum = getbyte(&p)) == -1)
badformat(buff, inm, BADCSUM);
if (((u8) incksum) != cksum)
badformat(buff, inm, MISCSUM);
if (tb.dl_count)
write_record(&tb, ofp);
}
return 0;
}
int
convert_S_records(
FILE *ifp,
char *inm,
FILE *ofp,
char *onm)
{
char buff[512];
char *p;
u8 cksum;
int incksum;
int c;
int len; /* data length of current line */
int rectype; /* record type */
u32 addr;
bool endrecord = FALSE;
buffer_rec tb;
while ( ! endrecord && (fgets(buff, sizeof(buff), ifp)))
{
p = &buff[0];
if (p[strlen(p)-1] == '\n') /* get rid of newline */
p[strlen(p)-1] = '\0';
if (p[strlen(p)-1] == '\r') /* get rid of any CR */
p[strlen(p)-1] = '\0';
tb.dl_count = 0;
if (*p != 'S')
badformat(p, inm, BADFMT);
p++;
if ((rectype = getnibble(&p)) == -1) /* record type */
badformat(buff, inm, BADTYPE);
if ((len = getbyte(&p)) == -1) /* record len */
badformat(buff, inm, BADLEN);
cksum = len;
switch (rectype)
{
case 0x00: /* comment field, ignored */
goto write_it;
case 0x01: /* data record, 16 bit addr */
if ((addr = get2bytes(&p)) == -1L)
badformat(buff, inm, BADADDR);
len -= 3;
goto doit;
case 0x02: /* ... 24 bit addr */
if ((addr = get3bytes(&p)) == -1L)
badformat(buff, inm, BADADDR);
len -= 4;
goto doit;
case 0x03: /* ... 32 bit addr */
if ((addr = get4bytes(&p)) == -1L)
badformat(buff, inm, BADADDR);
len -= 5;
doit:
cksum += B0(addr) + B1(addr) + B2(addr) + B3(addr);
tb.dl_destaddr = addr;
while (len--)
{
if ((c = getbyte(&p)) == -1)
badformat(buff, inm, BADDATA);
cksum += c;
filesum += c;
tb.dl_buf[tb.dl_count++] = c;
}
break;
case 0x07: /* 32 bit end record */
if ((addr = get4bytes(&p)) == -1L)
badformat(buff, inm, BADADDR);
goto end_rec;
case 0x08: /* 24 bit end record */
if ((addr = get3bytes(&p)) == -1L)
badformat(buff, inm, BADADDR);
goto end_rec;
case 0x09: /* 16 bit end record */
if ((addr = get2bytes(&p)) == -1L)
badformat(buff, inm, BADADDR);
end_rec:
cksum += B0(addr) + B1(addr) + B2(addr) + B3(addr);
tb.dl_jumpaddr = addr;
break;
default:
error(0, "unknown Motorola-S record type: 0x%02x", rectype);
badformat(buff, inm, BADTYPE);
break;
}
/*
* Verify checksums are correct in file.
*/
cksum = (~cksum) & 0xff;
if ((incksum = getbyte(&p)) == -1)
badformat(buff, inm, BADCSUM);
if (((u8) incksum) != cksum)
badformat(buff, inm, MISCSUM);
write_it:
if (tb.dl_count)
write_record(&tb, ofp);
}
return 0;
}
int
convert_TI_records(
FILE *ifp,
char *inm,
FILE *ofp,
char *onm)
{
char buff[512];
char *p;
int c;
bool endrecord = FALSE;
bool eol;
buffer_rec tb;
while ( ! endrecord && (fgets(buff, sizeof(buff), ifp)))
{
if (p[strlen(p)-1] == '\n') /* get rid of newline */
p[strlen(p)-1] = '\0';
if (p[strlen(p)-1] == '\r') /* get rid of any CR */
p[strlen(p)-1] = '\0';
tb.dl_count = 0;
p = &buff[0];
eol = FALSE;
while ( ! eol && ! endrecord)
{
switch (*p++)
{
case '9':
if (tb.dl_count)
write_record(&tb, ofp);
tb.dl_destaddr = get2bytes(&p);
break;
case 'B':
c = getbyte(&p);
filesum += c;
tb.dl_buf[tb.dl_count++] = c;
c = getbyte(&p);
filesum += c;
tb.dl_buf[tb.dl_count++] = c;
break;
case 'F':
eol = TRUE;
break;
case ':':
endrecord = TRUE;
break;
default:
badformat(p, inm, BADFMT);
}
}
if (tb.dl_count)
write_record(&tb, ofp);
}
return 0;
}
void
write_record(buffer_rec *tb,
FILE *fp)
{
if ( ! linear)
{
if (tb->dl_destaddr < base)
error(ERR_FATAL, "record at address 0x%x precedes base of 0x%x",
tb->dl_destaddr, base);
(void) fseek(fp, tb->dl_destaddr - base, 0);
}
(void) fwrite(tb->dl_buf, tb->dl_count, 1, fp);
tb->dl_destaddr += tb->dl_count;
tb->dl_count = 0;
}
int
getnibble(char **p)
{
register int val;
**p = toupper(**p);
switch (**p)
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
val = **p - '0';
break;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
val = 10 + (**p - 'A');
break;
default:
return(-1);
}
*p += 1;
return(val & 0x0f);
}
int
getbyte(char **p)
{
int n0, n1;
if ((n0 = getnibble(p)) == -1)
return(-1);
if ((n1 = getnibble(p)) == -1)
return(-1);
return(((n0 << 4) + n1) & 0xff);
}
long
getNbytes(char **p,
int n)
{
int t;
u32 val = 0;
while (n--)
{
if ((t = getbyte(p)) == -1)
return(-1L);
val <<= 8;
val += t;
}
return(val);
}
void
badformat(char *s,
char *fname,
char *msg)
{
if (s[strlen(s)-1] == '\n') /* get rid of newline */
s[strlen(s)-1] = '\0';
error(0, "line '%s'::\n\tfrom file '%s'; %s", s, fname, msg);
exit(1);
}
/*
* error(errn, arglist)
* report an error to stderr using printf(3) conventions.
* Any output is preceded by '<progname>: '
*
* Uses ERR_EXIT bit to request exit(errn)
* ERR_ABORT to request abort()
* ERR_ERRNO to indicate use of errno instead of argument.
*
* If resulting 'errn' is non-zero, it is assumed to be an 'errno' and its
* associated error message is appended to the output.
*/
/*VARARGS*/
void
error(int error_flag, ...)
{
va_list arglist;
register char *format;
extern char *sys_errlist[];
extern int sys_nerr;
int local_errno;
extern int errno;
(void) fflush(stdout); /* in case stdout/stderr same */
local_errno = error_flag & ~ERR_MASK;
if (error_flag & ERR_ERRNO) /* use errno? */
local_errno = errno;
va_start(arglist, error_flag);
format = va_arg(arglist, char *);
(void) fprintf(stderr, "%s: ", progname);
(void) vfprintf(stderr, format, arglist);
va_end(arglist);
if (local_errno)
if ((local_errno > 0) && (local_errno < sys_nerr))
(void) fprintf(stderr, " (%s)\n", sys_errlist[local_errno]);
else
(void) fprintf(stderr, " (unknown errno=%d)\n", local_errno);
else
(void) fprintf(stderr, "\n");
(void) fflush(stderr);
if (error_flag & (ERR_FATAL | ERR_ABORT))
{
if (error_flag & ERR_FATAL)
{
error(0, local_errno ? "fatal error, exiting" : "exiting");
exit(local_errno);
}
else
{
error(0, "fatal error, aborting");
abort();
}
}
}

719
tools/build/unhex.c Normal file
View File

@@ -0,0 +1,719 @@
/*
* unhex
* convert a hex file to binary equivalent. If more than one file name
* is given, then the output will be logically concatenated together.
* stdin and stdout are defaults. Verbose will enable checksum output.
*
* Supported input formats are Intel hex, Motorola S records, and TI 'B'
* records.
*
* Intel hex input format is
* Byte
* 1 Colon :
* 2..3 Record length, eg: "20"
* 4..7 load address nibbles
* 8..9 record type: "00" (data) or "02" base addr
* 10..x data bytes in ascii-hex
* x+1..x+2 cksum (2's compl of (len+addr+data))
* x+3 \n -- newline
*/
char *USAGE = "\
usage: unhex [-va] [ -o file ] [ file [file ... ] ]\n\
-v -- verbose\n\
-a base -- 1st byte of output corresponds to this address\n\
-l -- linear, just writes data out\n\
-o file -- output file; must not be input file\n\
-F k_bits -- \"holes\" in input will be filled with 0xFF's\n\
up to \"k_bits\" * 1024 bits\n\
";
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#define OK 0
#define FAILURE (-1)
#define Failed(x) ((x) == FAILURE)
#define TRUE 1
#define FALSE 0
typedef char bool;
#define STREQ(a,b) (strcmp(a,b) == 0)
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
/*
* Pick out designated bytes
*/
#define B0(x) ((x) & 0xff)
#define B1(x) B0((x) >> 8)
#define B2(x) B0((x) >> 16)
#define B3(x) B0((x) >> 24)
typedef struct buffer_rec {
u32 dl_destaddr;
u32 dl_jumpaddr;
int dl_count;
u8 dl_buf[512];
} buffer_rec;
/*
* vars controlled by command line options
*/
bool verbose = FALSE; /* be verbose */
bool linear = FALSE; /* just write out linear data */
char *outfilename = "-"; /* default output is stdout */
u32 base = 0L; /* base address */
u32 FFfill = 0L; /* how far to fill w 0xFF's */
extern char *optarg; /* getopt(3) control vars */
extern int optind;
extern int errno;
char *progname; /* for error() */
void error(int errn, ...);
#define ERR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */
#define ERR_FATAL (ERR_ERRNO / 2) /* error is fatal; no return */
#define ERR_ABORT (ERR_ERRNO / 4) /* error is fatal; abort */
#define ERR_MASK (ERR_ERRNO | ERR_FATAL | ERR_ABORT) /* all */
#define stol(p) strtol(p, (char **) NULL, 0)
int unhex(FILE *ifp, char *inm, FILE *ofp, char *onm);
int convert_Intel_records(FILE *ifp, char *inm, FILE *ofp, char *onm);
int convert_S_records(FILE *ifp, char *inm, FILE *ofp, char *onm);
int convert_TI_records(FILE *ifp, char *inm, FILE *ofp, char *onm);
void write_record(buffer_rec *tb, FILE *fp);
int getnibble(char **p);
int getbyte(char **p);
long getNbytes(char **p, int n);
void badformat(char *s, char *fname, char *msg);
#define get1bytes(p) ((int) getbyte(p))
#define get2bytes(p) ((int) getNbytes(p, 2))
#define get3bytes(p) getNbytes(p, 3)
#define get4bytes(p) getNbytes(p, 4)
char *BADADDR = "Invalid record address";
char *BADLEN = "Invalid record length";
char *BADBASE = "Bad base or starting address";
char *BADFMT = "Unrecognized record type";
char *BADDATA = "Invalid data byte";
char *BADCSUM = "Invalid checksum";
char *MISCSUM = "Checksum mismatch";
char *BADTYPE = "Unrecognized record type";
char *MISTYPE = "Incompatible record types";
int
main(argc, argv)
int argc;
char **argv;
{
register int c;
bool showusage = FALSE; /* usage error? */
int rc = 0;
FILE *outfp, *infp;
/*
* figure out invocation leaf-name
*/
if ((progname = strrchr(argv[0], '/')) == (char *) NULL)
progname = argv[0];
else
progname++;
argv[0] = progname; /* for getopt err reporting */
/*
* Check options and arguments.
*/
progname = argv[0];
while ((c = getopt(argc, argv, "F:a:o:vl")) != EOF)
switch (c)
{
case 'a': /* base address */
base = stol(optarg);
break;
case 'l': /* linear output */
linear = TRUE;
break;
case 'v': /* toggle verbose */
verbose = ! verbose;
break;
case 'o': /* output file */
outfilename = optarg;
break;
case 'F': /* 0xFF fill amount (bytes) */
FFfill = stol(optarg) * 1024L / 8L;
break;
case '?':
showusage = TRUE;
}
if (showusage)
{
(void) fprintf(stderr, "%s", USAGE);
exit(1);
}
if (linear && (base != 0))
{
error(0, "-l and -a may not be specified in combination");
exit(1);
}
if (STREQ(outfilename, "-"))
{
outfp = stdout;
outfilename = "stdout";
}
else
if ((outfp = fopen(outfilename, "w")) == (FILE *) NULL)
{
error(-1, "couldn't open '%s' for output", outfilename);
exit(1);
}
/*
* Now process the input files (or stdin, if none specified)
*/
if (argv[optind] == (char *) NULL) /* just stdin */
exit(unhex(stdin, "stdin", outfp, outfilename));
else
for (; (optarg = argv[optind]); optind++)
{
if (STREQ(optarg, "-"))
rc += unhex(stdin, "stdin", outfp, outfilename);
else
{
if ((infp = fopen(optarg, "r")) == (FILE *) NULL)
{
error(-1, "couldn't open '%s' for input", optarg);
exit(1);
}
rc += unhex(infp, optarg, outfp, outfilename);
}
}
return(rc);
}
u16 filesum;
int
unhex(FILE *ifp,
char *inm,
FILE *ofp,
char *onm)
{
int c;
filesum = 0;
/*
* Make sure holes will be filled with 0xFF's if requested. We
* do this the easy way by just filling the file with FF's before
* getting started. To do it more optimally would be quite a bit
* more difficult since the user can skip around as much as he/she
* likes in the input hex file addressing.
*
* We'll clean this up later (after this program has run) with
* 'stripffs'
*/
if (FFfill)
{
(void) fseek(ofp, 0, 0);
for (c = FFfill; c > 0; c--)
(void) fputc(0xFF, ofp);
}
/*
* Read the first char from file and determine record types
*/
if ((c = getc(ifp)) != EOF)
{
ungetc(c, ifp);
switch(c)
{
case 'S':
convert_S_records(ifp, inm, ofp, onm);
break;
case ':':
convert_Intel_records(ifp, inm, ofp, onm);
break;
case '9':
case 'B':
convert_TI_records(ifp, inm, ofp, onm);
break;
default:
{
char tmp[2];
tmp[0] = c; tmp[1] = 0;
badformat(tmp, inm, BADFMT);
}
}
}
if (verbose)
fprintf(stderr, "'%s' checksum is 0x%04x\n", inm, filesum);
return 0;
}
int
convert_Intel_records(
FILE *ifp,
char *inm,
FILE *ofp,
char *onm)
{
char buff[512];
char *p;
u8 cksum;
int incksum;
int c;
int rectype; /* record type */
int len; /* data length of current line */
u32 addr;
u32 base_address = 0;
bool endrecord = FALSE;
buffer_rec tb;
while ( ! endrecord && (fgets(buff, sizeof(buff), ifp)))
{
p = &buff[0];
if (p[strlen(p)-1] == '\n') /* get rid of newline */
p[strlen(p)-1] = '\0';
if (p[strlen(p)-1] == '\r') /* get rid of any CR */
p[strlen(p)-1] = '\0';
tb.dl_count = 0;
if (*p != ':')
badformat(p, inm, BADFMT);
p++;
if ((len = getbyte(&p)) == -1) /* record len */
badformat(buff, inm, BADLEN);
if ((addr = get2bytes(&p)) == -1L) /* record addr */
badformat(buff, inm, BADADDR);
rectype = getbyte(&p);
cksum = len + B0(addr) + B1(addr) + rectype;
switch (rectype)
{
case 0x00: /* normal data record */
tb.dl_destaddr = base_address + addr;
while (len--)
{
if ((c = getbyte(&p)) == -1)
badformat(buff, inm, BADDATA);
cksum += c;
filesum += c;
tb.dl_buf[tb.dl_count++] = c;
}
break;
case 0x01: /* execution start address */
base_address = addr;
endrecord = TRUE;
break;
case 0x02: /* new base */
if ((base_address = get2bytes(&p)) == -1L)
badformat(buff, inm, BADBASE);
cksum += B0(base_address) + B1(base_address);
base_address <<= 4;
break;
case 0x03: /* seg/off execution start address */
{
u32 seg, off;
seg = get2bytes(&p);
off = get2bytes(&p);
if ((seg == -1L) || (off == -1L))
badformat(buff, inm, BADADDR);
cksum += B0(seg) + B1(seg) + B0(off) + B1(off);
tb.dl_jumpaddr = (seg << 4) + off;
break;
}
default:
error(0, "unknown Intel-hex record type: 0x%02x", rectype);
badformat(buff, inm, BADTYPE);
}
/*
* Verify checksums are correct in file.
*/
cksum = (-cksum) & 0xff;
if ((incksum = getbyte(&p)) == -1)
badformat(buff, inm, BADCSUM);
if (((u8) incksum) != cksum)
badformat(buff, inm, MISCSUM);
if (tb.dl_count)
write_record(&tb, ofp);
}
return 0;
}
int
convert_S_records(
FILE *ifp,
char *inm,
FILE *ofp,
char *onm)
{
char buff[512];
char *p;
u8 cksum;
int incksum;
int c;
int len; /* data length of current line */
int rectype; /* record type */
u32 addr;
bool endrecord = FALSE;
buffer_rec tb;
while ( ! endrecord && (fgets(buff, sizeof(buff), ifp)))
{
p = &buff[0];
if (p[strlen(p)-1] == '\n') /* get rid of newline */
p[strlen(p)-1] = '\0';
if (p[strlen(p)-1] == '\r') /* get rid of any CR */
p[strlen(p)-1] = '\0';
tb.dl_count = 0;
if (*p != 'S')
badformat(p, inm, BADFMT);
p++;
if ((rectype = getnibble(&p)) == -1) /* record type */
badformat(buff, inm, BADTYPE);
if ((len = getbyte(&p)) == -1) /* record len */
badformat(buff, inm, BADLEN);
cksum = len;
switch (rectype)
{
case 0x00: /* comment field, ignored */
goto write_it;
case 0x01: /* data record, 16 bit addr */
if ((addr = get2bytes(&p)) == -1L)
badformat(buff, inm, BADADDR);
len -= 3;
goto doit;
case 0x02: /* ... 24 bit addr */
if ((addr = get3bytes(&p)) == -1L)
badformat(buff, inm, BADADDR);
len -= 4;
goto doit;
case 0x03: /* ... 32 bit addr */
if ((addr = get4bytes(&p)) == -1L)
badformat(buff, inm, BADADDR);
len -= 5;
doit:
cksum += B0(addr) + B1(addr) + B2(addr) + B3(addr);
tb.dl_destaddr = addr;
while (len--)
{
if ((c = getbyte(&p)) == -1)
badformat(buff, inm, BADDATA);
cksum += c;
filesum += c;
tb.dl_buf[tb.dl_count++] = c;
}
break;
case 0x07: /* 32 bit end record */
if ((addr = get4bytes(&p)) == -1L)
badformat(buff, inm, BADADDR);
goto end_rec;
case 0x08: /* 24 bit end record */
if ((addr = get3bytes(&p)) == -1L)
badformat(buff, inm, BADADDR);
goto end_rec;
case 0x09: /* 16 bit end record */
if ((addr = get2bytes(&p)) == -1L)
badformat(buff, inm, BADADDR);
end_rec:
cksum += B0(addr) + B1(addr) + B2(addr) + B3(addr);
tb.dl_jumpaddr = addr;
break;
default:
error(0, "unknown Motorola-S record type: 0x%02x", rectype);
badformat(buff, inm, BADTYPE);
break;
}
/*
* Verify checksums are correct in file.
*/
cksum = (~cksum) & 0xff;
if ((incksum = getbyte(&p)) == -1)
badformat(buff, inm, BADCSUM);
if (((u8) incksum) != cksum)
badformat(buff, inm, MISCSUM);
write_it:
if (tb.dl_count)
write_record(&tb, ofp);
}
return 0;
}
int
convert_TI_records(
FILE *ifp,
char *inm,
FILE *ofp,
char *onm)
{
char buff[512];
char *p;
int c;
bool endrecord = FALSE;
bool eol;
buffer_rec tb;
while ( ! endrecord && (fgets(buff, sizeof(buff), ifp)))
{
if (p[strlen(p)-1] == '\n') /* get rid of newline */
p[strlen(p)-1] = '\0';
if (p[strlen(p)-1] == '\r') /* get rid of any CR */
p[strlen(p)-1] = '\0';
tb.dl_count = 0;
p = &buff[0];
eol = FALSE;
while ( ! eol && ! endrecord)
{
switch (*p++)
{
case '9':
if (tb.dl_count)
write_record(&tb, ofp);
tb.dl_destaddr = get2bytes(&p);
break;
case 'B':
c = getbyte(&p);
filesum += c;
tb.dl_buf[tb.dl_count++] = c;
c = getbyte(&p);
filesum += c;
tb.dl_buf[tb.dl_count++] = c;
break;
case 'F':
eol = TRUE;
break;
case ':':
endrecord = TRUE;
break;
default:
badformat(p, inm, BADFMT);
}
}
if (tb.dl_count)
write_record(&tb, ofp);
}
return 0;
}
void
write_record(buffer_rec *tb,
FILE *fp)
{
if ( ! linear)
{
if (tb->dl_destaddr < base)
error(ERR_FATAL, "record at address 0x%x precedes base of 0x%x",
tb->dl_destaddr, base);
(void) fseek(fp, tb->dl_destaddr - base, 0);
}
(void) fwrite(tb->dl_buf, tb->dl_count, 1, fp);
tb->dl_destaddr += tb->dl_count;
tb->dl_count = 0;
}
int
getnibble(char **p)
{
register int val;
**p = toupper(**p);
switch (**p)
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
val = **p - '0';
break;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
val = 10 + (**p - 'A');
break;
default:
return(-1);
}
*p += 1;
return(val & 0x0f);
}
int
getbyte(char **p)
{
int n0, n1;
if ((n0 = getnibble(p)) == -1)
return(-1);
if ((n1 = getnibble(p)) == -1)
return(-1);
return(((n0 << 4) + n1) & 0xff);
}
long
getNbytes(char **p,
int n)
{
int t;
u32 val = 0;
while (n--)
{
if ((t = getbyte(p)) == -1)
return(-1L);
val <<= 8;
val += t;
}
return(val);
}
void
badformat(char *s,
char *fname,
char *msg)
{
if (s[strlen(s)-1] == '\n') /* get rid of newline */
s[strlen(s)-1] = '\0';
error(0, "line '%s'::\n\tfrom file '%s'; %s", s, fname, msg);
exit(1);
}
/*
* error(errn, arglist)
* report an error to stderr using printf(3) conventions.
* Any output is preceded by '<progname>: '
*
* Uses ERR_EXIT bit to request exit(errn)
* ERR_ABORT to request abort()
* ERR_ERRNO to indicate use of errno instead of argument.
*
* If resulting 'errn' is non-zero, it is assumed to be an 'errno' and its
* associated error message is appended to the output.
*/
/*VARARGS*/
void
error(int error_flag, ...)
{
va_list arglist;
register char *format;
extern char *sys_errlist[];
extern int sys_nerr;
int local_errno;
extern int errno;
(void) fflush(stdout); /* in case stdout/stderr same */
local_errno = error_flag & ~ERR_MASK;
if (error_flag & ERR_ERRNO) /* use errno? */
local_errno = errno;
va_start(arglist, error_flag);
format = va_arg(arglist, char *);
(void) fprintf(stderr, "%s: ", progname);
(void) vfprintf(stderr, format, arglist);
va_end(arglist);
if (local_errno)
if ((local_errno > 0) && (local_errno < sys_nerr))
(void) fprintf(stderr, " (%s)\n", sys_errlist[local_errno]);
else
(void) fprintf(stderr, " (unknown errno=%d)\n", local_errno);
else
(void) fprintf(stderr, "\n");
(void) fflush(stderr);
if (error_flag & (ERR_FATAL | ERR_ABORT))
{
if (error_flag & ERR_FATAL)
{
error(0, local_errno ? "fatal error, exiting" : "exiting");
exit(local_errno);
}
else
{
error(0, "fatal error, aborting");
abort();
}
}
}