Merge from vendor branch BIND:
[dragonfly.git] / contrib / gcc / listing
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
40 ex /tmp/$$.c <<END >/dev/null
41 a
42 main (){}
43 .
44 w
45 q
46 END
47 WD=`pwd`
48 cd /tmp
49 gcc -c $$.c
50 case "`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 ;;
56 esac
57 rm $$.c $$.o
58 cd $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
70 WHOAMI=$0
71 if [ $# -gt 0 ] ; then
72 FILENAME=$1
73 shift
74 fi
75
76 exec gawk -v whoami=$WHOAMI -vsys=$MYSYS -voptions="$*" '
77 # commandline arguments:
78 #  ARGV[0] = "gawk"
79 #  ARGV[1] = processid
80 #  ARGV[2] = filename
81 BEGIN {
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
190 function usage() {
191     printf("usage: %s filename compiler-options\n", whoami) > "/dev/stderr"
192 }
193
194 function error(s) {
195     printf("error: %s\n", s) > "/dev/stderr"
196     exit 1
197 }
198
199 function 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