228 lines
5.6 KiB
Plaintext
228 lines
5.6 KiB
Plaintext
|
#!/bin/sh -f
|
||
|
# Generate a source code listing for C or C++ code with assembler code. The
|
||
|
# listing is always written to stdout.
|
||
|
# Author: Igor Metz <metz@iam.unibe.ch>
|
||
|
|
||
|
# Revision 1.4 94/08/26 13:58:27 coxs <coxs@dg-rtp.dg.com>
|
||
|
# lister now guesses how to should be configured. Added elf and coff support.
|
||
|
#
|
||
|
# Revision 1.3 89/12/18 13:58:27 metz
|
||
|
# lister must now be configured before it can be used. This is done in the
|
||
|
# /bin/sh part of the code.
|
||
|
#
|
||
|
#
|
||
|
# Revision 1.2 89/08/16 17:35:02 metz
|
||
|
# Support for SPARC added.
|
||
|
#
|
||
|
# Revision 1.1 89/08/16 16:49:22 metz
|
||
|
# Initial revision
|
||
|
#
|
||
|
|
||
|
# Requires: gawk (may be it works also with nawk)
|
||
|
|
||
|
# usage: lister filename [compiler-options]
|
||
|
|
||
|
# Method:
|
||
|
# compile the source with -g option to assembler code, then merge the
|
||
|
# generated assembler code with the source code. Compiler options
|
||
|
# can be supplied on the command line (for example -O)
|
||
|
|
||
|
# To install lister, assign one of the supported values to the variable MYSYS:
|
||
|
# mc68020 for Motorola 68020 (Sun-3, ..)
|
||
|
# mc68030 for Motorola 68030 (Sun-3, ..)
|
||
|
# sparc for SPARC (SUN-4, ..)
|
||
|
# i386 for i386 (Sun i386, ...)
|
||
|
# i386-linux for i386 (Linux, ...)
|
||
|
|
||
|
# Guess what kind of objects we are creating and thus what type of assembler
|
||
|
# symbols to look for
|
||
|
|
||
|
ex /tmp/$$.c <<END >/dev/null
|
||
|
a
|
||
|
main (){}
|
||
|
.
|
||
|
w
|
||
|
q
|
||
|
END
|
||
|
WD=`pwd`
|
||
|
cd /tmp
|
||
|
gcc -c $$.c
|
||
|
case "`file $$.o`" in
|
||
|
*ELF*) MYSYS=elf ;;
|
||
|
*COFF*|*BCS*) MYSYS=coff ;;
|
||
|
*mc68k*|*M68000*) MYSYS=mc68030 ;;
|
||
|
*SPARC*) MYSYS=sparc ;;
|
||
|
*386*) MYSYS=i386 ;;
|
||
|
esac
|
||
|
rm $$.c $$.o
|
||
|
cd $WD
|
||
|
|
||
|
# uncomment the line you need if the above guesses incorrectly:
|
||
|
# MYSYS=mc68020
|
||
|
# MYSYS=mc68030
|
||
|
# MYSYS=sparc
|
||
|
# MYSYS=i386
|
||
|
# MYSYS=i386-linux
|
||
|
# MYSYS=`mach` # this will work on Suns with SunOS > 4.0.0
|
||
|
# MYSYS=elf
|
||
|
# MYSYS=coff
|
||
|
|
||
|
WHOAMI=$0
|
||
|
if [ $# -gt 0 ] ; then
|
||
|
FILENAME=$1
|
||
|
shift
|
||
|
fi
|
||
|
|
||
|
exec gawk -v whoami=$WHOAMI -vsys=$MYSYS -voptions="$*" '
|
||
|
# commandline arguments:
|
||
|
# ARGV[0] = "gawk"
|
||
|
# ARGV[1] = processid
|
||
|
# ARGV[2] = filename
|
||
|
BEGIN {
|
||
|
if (ARGC != 3) {
|
||
|
usage()
|
||
|
exit 1
|
||
|
}
|
||
|
|
||
|
# Declaration of global variables
|
||
|
c_filename = ""
|
||
|
asm_filename = ""
|
||
|
cmdline = ""
|
||
|
asm_code = ""
|
||
|
c_code = ""
|
||
|
c_lineno = 0
|
||
|
oldlineno = 0
|
||
|
newlineno = 0
|
||
|
ignore_stabd = 0
|
||
|
num_of_fields = 0
|
||
|
|
||
|
# check processor architecture and set sourcecode line_hint accordingly
|
||
|
if (sys == "sparc" || sys == "i386") {
|
||
|
line_hint = "^[ \t]*\.stabn.*"
|
||
|
line_field = 3;
|
||
|
line_delimiter = ",";
|
||
|
line_offset = 0;
|
||
|
}
|
||
|
else if (sys == "mc68020" || sys == "mc68030" || sys == "i386-linux") {
|
||
|
line_hint = "^[ \t]*\.stabd.*"
|
||
|
line_field = 3;
|
||
|
line_delimiter = ",";
|
||
|
line_offset = 0;
|
||
|
}
|
||
|
else if (sys == "elf") {
|
||
|
line_hint = "section.*\.line"
|
||
|
line_field = 3;
|
||
|
line_delimiter = "\t";
|
||
|
line_offset = 0;
|
||
|
}
|
||
|
else if (sys == "coff") {
|
||
|
line_hint = "^[ \t]*ln"
|
||
|
line_field = 3;
|
||
|
line_delimiter = "\t";
|
||
|
}
|
||
|
else {
|
||
|
error("Processor type " sys " is not supported yet, sorry")
|
||
|
}
|
||
|
|
||
|
parse_cmdline()
|
||
|
|
||
|
printf("compiling %s to asm code\n", c_filename ) > "/dev/stderr"
|
||
|
|
||
|
if (system(cmdline) != 0 ) {
|
||
|
error("Compilation of " c_filename " failed")
|
||
|
}
|
||
|
|
||
|
printf("generating listing\n") > "/dev/stderr"
|
||
|
|
||
|
|
||
|
while ( getline asm_code < asm_filename > 0 ) {
|
||
|
if ( (ignore_stabd==0) && (asm_code ~ line_hint)) {
|
||
|
while ( sys == "elf" && (asm_code !~ "word" && asm_code !~ "byte") &&
|
||
|
getline asm_code < asm_filename > 0);
|
||
|
# source line hint found. Split the line into fields separated by commas.
|
||
|
# num_of_fields is 4 for sparc, 3 for m68k
|
||
|
num_of_fields = split(asm_code, fields, line_delimiter)
|
||
|
newlineno = fields[line_field] + line_offset;
|
||
|
|
||
|
if (newlineno > oldlineno) {
|
||
|
while ( newlineno > c_lineno && getline c_code < c_filename > 0) {
|
||
|
c_lineno++
|
||
|
printf("%4d %s\n", c_lineno, c_code)
|
||
|
}
|
||
|
oldlineno = newlineno
|
||
|
}
|
||
|
}
|
||
|
else if ( asm_code ~ ".*Ltext[ \t]*$" ) {
|
||
|
# filename hint found
|
||
|
if ( match(asm_code, c_filename)) {
|
||
|
ignore_stabd = 0
|
||
|
}
|
||
|
else {
|
||
|
ignore_stabd = 1
|
||
|
}
|
||
|
}
|
||
|
else if ( sys == "elf" && asm_code ~ "section.*\.debug" ) {
|
||
|
while ( asm_code !~ "^[ \t]*[.]*previous" &&
|
||
|
asm_code !~ "\.popsection" &&
|
||
|
getline asm_code < asm_filename > 0 );
|
||
|
if ( ! (getline asm_code < asm_filename > 0)) break;
|
||
|
}
|
||
|
else if ( sys == "coff" && asm_code ~ "^[ \t]*sdef" ) {
|
||
|
if ( asm_code ~ "\.bf" ) {
|
||
|
while ( asm_code !~ "^[ \t]*line" &&
|
||
|
getline asm_code < asm_filename > 0 ) {
|
||
|
num_of_fields = split(asm_code, fields, "\t")
|
||
|
line_offset = fields[line_field] - 1;
|
||
|
}
|
||
|
}
|
||
|
while ( asm_code !~ "^[ \t]*endef" &&
|
||
|
getline asm_code < asm_filename > 0 ) {
|
||
|
}
|
||
|
if ( ! (getline asm_code < asm_filename > 0)) break;
|
||
|
}
|
||
|
printf("\t\t\t%s\n", asm_code)
|
||
|
}
|
||
|
|
||
|
# general cleanup
|
||
|
system("/bin/rm " asm_filename)
|
||
|
}
|
||
|
|
||
|
function usage() {
|
||
|
printf("usage: %s filename compiler-options\n", whoami) > "/dev/stderr"
|
||
|
}
|
||
|
|
||
|
function error(s) {
|
||
|
printf("error: %s\n", s) > "/dev/stderr"
|
||
|
exit 1
|
||
|
}
|
||
|
|
||
|
function parse_cmdline( i) {
|
||
|
# construct filenames to use
|
||
|
asm_filename = "/tmp/lister" ARGV[1] ".s"
|
||
|
ARGV[1] = ""
|
||
|
c_filename = ARGV[2]
|
||
|
ARGV[2] = ""
|
||
|
|
||
|
# construct commandline to use
|
||
|
if ( match(c_filename, ".C") || match(c_filename, ".cc") ) {
|
||
|
cmdline = "g++"
|
||
|
}
|
||
|
else if (match(c_filename, ".c") || match(c_filename, ".i")) {
|
||
|
cmdline = "gcc"
|
||
|
}
|
||
|
else {
|
||
|
error("unknown extension for file " c_filename)
|
||
|
}
|
||
|
|
||
|
cmdline = cmdline " -g -S -o " asm_filename
|
||
|
|
||
|
# now we append the compiler options specified by the user
|
||
|
cmdline = cmdline " " options
|
||
|
|
||
|
# last but not least: the name of the file to compile
|
||
|
cmdline = cmdline " " c_filename
|
||
|
}
|
||
|
|
||
|
' $$ $FILENAME
|
||
|
|