1#!/bin/sh -f 2# Generate a source code listing for C or C++ code with assembler code. The 3# listing is always written to stdout. 4# Author: Igor Metz <metz@iam.unibe.ch> 5 6# Revision 1.4 94/08/26 13:58:27 coxs <coxs@dg-rtp.dg.com> 7# lister now guesses how to should be configured. Added elf and coff support. 8# 9# Revision 1.3 89/12/18 13:58:27 metz 10# lister must now be configured before it can be used. This is done in the 11# /bin/sh part of the code. 12# 13# 14# Revision 1.2 89/08/16 17:35:02 metz 15# Support for SPARC added. 16# 17# Revision 1.1 89/08/16 16:49:22 metz 18# Initial revision 19# 20 21# Requires: gawk (may be it works also with nawk) 22 23# usage: lister filename [compiler-options] 24 25# Method: 26# compile the source with -g option to assembler code, then merge the 27# generated assembler code with the source code. Compiler options 28# can be supplied on the command line (for example -O) 29 30# To install lister, assign one of the supported values to the variable MYSYS: 31# mc68020 for Motorola 68020 (Sun-3, ..) 32# mc68030 for Motorola 68030 (Sun-3, ..) 33# sparc for SPARC (SUN-4, ..) 34# i386 for i386 (Sun i386, ...) 35# i386-gnu-linux for i386 (GNU/Linux, ...) 36 37# Guess what kind of objects we are creating and thus what type of assembler 38# symbols to look for 39 40ex /tmp/$$.c <<END >/dev/null 41a 42main (){} 43. 44w 45q 46END 47WD=`pwd` 48cd /tmp 49gcc -c $$.c 50case "`file $$.o`" in 51*ELF*) MYSYS=elf ;; 52*COFF*|*BCS*) MYSYS=coff ;; 53*mc68k*|*M68000*) MYSYS=mc68030 ;; 54*SPARC*) MYSYS=sparc ;; 55*386*) MYSYS=i386 ;; 56esac 57rm $$.c $$.o 58cd $WD 59 60# uncomment the line you need if the above guesses incorrectly: 61# MYSYS=mc68020 62# MYSYS=mc68030 63# MYSYS=sparc 64# MYSYS=i386 65# MYSYS=i386-gnu-linux 66# MYSYS=`mach` # this will work on Suns with SunOS > 4.0.0 67# MYSYS=elf 68# MYSYS=coff 69 70WHOAMI=$0 71if [ $# -gt 0 ] ; then 72FILENAME=$1 73shift 74fi 75 76exec gawk -v whoami=$WHOAMI -vsys=$MYSYS -voptions="$*" ' 77# commandline arguments: 78# ARGV[0] = "gawk" 79# ARGV[1] = processid 80# ARGV[2] = filename 81BEGIN { 82 if (ARGC != 3) { 83 usage() 84 exit 1 85 } 86 87 # Declaration of global variables 88 c_filename = "" 89 asm_filename = "" 90 cmdline = "" 91 asm_code = "" 92 c_code = "" 93 c_lineno = 0 94 oldlineno = 0 95 newlineno = 0 96 ignore_stabd = 0 97 num_of_fields = 0 98 99 # check processor architecture and set sourcecode line_hint accordingly 100 if (sys == "sparc" || sys == "i386") { 101 line_hint = "^[ \t]*\.stabn.*" 102 line_field = 3; 103 line_delimiter = ","; 104 line_offset = 0; 105 } 106 else if (sys == "mc68020" || sys == "mc68030" || sys == "i386-gnu-linux") { 107 line_hint = "^[ \t]*\.stabd.*" 108 line_field = 3; 109 line_delimiter = ","; 110 line_offset = 0; 111 } 112 else if (sys == "elf") { 113 line_hint = "section.*\.line" 114 line_field = 3; 115 line_delimiter = "\t"; 116 line_offset = 0; 117 } 118 else if (sys == "coff") { 119 line_hint = "^[ \t]*ln" 120 line_field = 3; 121 line_delimiter = "\t"; 122 } 123 else { 124 error("Processor type " sys " is not supported yet, sorry") 125 } 126 127 parse_cmdline() 128 129 printf("compiling %s to asm code\n", c_filename ) > "/dev/stderr" 130 131 if (system(cmdline) != 0 ) { 132 error("Compilation of " c_filename " failed") 133 } 134 135 printf("generating listing\n") > "/dev/stderr" 136 137 138 while ( getline asm_code < asm_filename > 0 ) { 139 if ( (ignore_stabd==0) && (asm_code ~ line_hint)) { 140 while ( sys == "elf" && (asm_code !~ "word" && asm_code !~ "byte") && 141 getline asm_code < asm_filename > 0); 142 # source line hint found. Split the line into fields separated by commas. 143 # num_of_fields is 4 for sparc, 3 for m68k 144 num_of_fields = split(asm_code, fields, line_delimiter) 145 newlineno = fields[line_field] + line_offset; 146 147 if (newlineno > oldlineno) { 148 while ( newlineno > c_lineno && getline c_code < c_filename > 0) { 149 c_lineno++ 150 printf("%4d %s\n", c_lineno, c_code) 151 } 152 oldlineno = newlineno 153 } 154 } 155 else if ( asm_code ~ ".*Ltext[ \t]*$" ) { 156 # filename hint found 157 if ( match(asm_code, c_filename)) { 158 ignore_stabd = 0 159 } 160 else { 161 ignore_stabd = 1 162 } 163 } 164 else if ( sys == "elf" && asm_code ~ "section.*\.debug" ) { 165 while ( asm_code !~ "^[ \t]*[.]*previous" && 166 asm_code !~ "\.popsection" && 167 getline asm_code < asm_filename > 0 ); 168 if ( ! (getline asm_code < asm_filename > 0)) break; 169 } 170 else if ( sys == "coff" && asm_code ~ "^[ \t]*sdef" ) { 171 if ( asm_code ~ "\.bf" ) { 172 while ( asm_code !~ "^[ \t]*line" && 173 getline asm_code < asm_filename > 0 ) { 174 num_of_fields = split(asm_code, fields, "\t") 175 line_offset = fields[line_field] - 1; 176 } 177 } 178 while ( asm_code !~ "^[ \t]*endef" && 179 getline asm_code < asm_filename > 0 ) { 180 } 181 if ( ! (getline asm_code < asm_filename > 0)) break; 182 } 183 printf("\t\t\t%s\n", asm_code) 184 } 185 186 # general cleanup 187 system("/bin/rm " asm_filename) 188} 189 190function usage() { 191 printf("usage: %s filename compiler-options\n", whoami) > "/dev/stderr" 192} 193 194function error(s) { 195 printf("error: %s\n", s) > "/dev/stderr" 196 exit 1 197} 198 199function parse_cmdline( i) { 200 # construct filenames to use 201 asm_filename = "/tmp/lister" ARGV[1] ".s" 202 ARGV[1] = "" 203 c_filename = ARGV[2] 204 ARGV[2] = "" 205 206 # construct commandline to use 207 if ( match(c_filename, ".C") || match(c_filename, ".cc") ) { 208 cmdline = "g++" 209 } 210 else if (match(c_filename, ".c") || match(c_filename, ".i")) { 211 cmdline = "gcc" 212 } 213 else { 214 error("unknown extension for file " c_filename) 215 } 216 217 cmdline = cmdline " -g -S -o " asm_filename 218 219 # now we append the compiler options specified by the user 220 cmdline = cmdline " " options 221 222 # last but not least: the name of the file to compile 223 cmdline = cmdline " " c_filename 224} 225 226' $$ $FILENAME 227 228