1*0Sstevel@tonic-gate#!/usr/local/bin/perl 2*0Sstevel@tonic-gate 3*0Sstevel@tonic-gateuse Config; 4*0Sstevel@tonic-gateuse File::Basename qw(&basename &dirname); 5*0Sstevel@tonic-gateuse Cwd; 6*0Sstevel@tonic-gateuse subs qw(link); 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gatesub link { # This is a cut-down version of installperl:link(). 9*0Sstevel@tonic-gate my($from,$to) = @_; 10*0Sstevel@tonic-gate my($success) = 0; 11*0Sstevel@tonic-gate 12*0Sstevel@tonic-gate eval { 13*0Sstevel@tonic-gate CORE::link($from, $to) 14*0Sstevel@tonic-gate ? $success++ 15*0Sstevel@tonic-gate : ($from =~ m#^/afs/# || $to =~ m#^/afs/#) 16*0Sstevel@tonic-gate ? die "AFS" # okay inside eval {} 17*0Sstevel@tonic-gate : die "Couldn't link $from to $to: $!\n"; 18*0Sstevel@tonic-gate }; 19*0Sstevel@tonic-gate if ($@) { 20*0Sstevel@tonic-gate warn $@; 21*0Sstevel@tonic-gate require File::Copy; 22*0Sstevel@tonic-gate File::Copy::copy($from, $to) 23*0Sstevel@tonic-gate ? $success++ 24*0Sstevel@tonic-gate : warn "Couldn't copy $from to $to: $!\n"; 25*0Sstevel@tonic-gate } 26*0Sstevel@tonic-gate $success; 27*0Sstevel@tonic-gate} 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate# List explicitly here the variables you want Configure to 30*0Sstevel@tonic-gate# generate. Metaconfig only looks for shell variables, so you 31*0Sstevel@tonic-gate# have to mention them as if they were shell variables, not 32*0Sstevel@tonic-gate# %Config entries. Thus you write 33*0Sstevel@tonic-gate# $startperl 34*0Sstevel@tonic-gate# to ensure Configure will look for $Config{startperl}. 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate# This forces PL files to create target in same directory as PL file. 37*0Sstevel@tonic-gate# This is so that make depend always knows where to find PL derivatives. 38*0Sstevel@tonic-gate$origdir = cwd; 39*0Sstevel@tonic-gatechdir dirname($0); 40*0Sstevel@tonic-gate$file = basename($0, '.PL'); 41*0Sstevel@tonic-gate$file .= '.com' if $^O eq 'VMS'; 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gateopen OUT,">$file" or die "Can't create $file: $!"; 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gateprint "Extracting $file (with variable substitutions)\n"; 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate# In this section, perl variables will be expanded during extraction. 48*0Sstevel@tonic-gate# You can use $Config{...} to use Configure variables. 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gateprint OUT <<"!GROK!THIS!"; 51*0Sstevel@tonic-gate$Config{startperl} 52*0Sstevel@tonic-gate eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}' 53*0Sstevel@tonic-gate if \$running_under_some_shell; 54*0Sstevel@tonic-gate!GROK!THIS! 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate# In the following, perl variables are not expanded during extraction. 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gateprint OUT <<'!NO!SUBS!'; 59*0Sstevel@tonic-gate# 60*0Sstevel@tonic-gate# 61*0Sstevel@tonic-gate# c2ph (aka pstruct) 62*0Sstevel@tonic-gate# Tom Christiansen, <tchrist@convex.com> 63*0Sstevel@tonic-gate# 64*0Sstevel@tonic-gate# As pstruct, dump C structures as generated from 'cc -g -S' stabs. 65*0Sstevel@tonic-gate# As c2ph, do this PLUS generate perl code for getting at the structures. 66*0Sstevel@tonic-gate# 67*0Sstevel@tonic-gate# See the usage message for more. If this isn't enough, read the code. 68*0Sstevel@tonic-gate# 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate=head1 NAME 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gatec2ph, pstruct - Dump C structures as generated from C<cc -g -S> stabs 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate=head1 SYNOPSIS 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate c2ph [-dpnP] [var=val] [files ...] 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate=head2 OPTIONS 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate Options: 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate -w wide; short for: type_width=45 member_width=35 offset_width=8 83*0Sstevel@tonic-gate -x hex; short for: offset_fmt=x offset_width=08 size_fmt=x size_width=04 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate -n do not generate perl code (default when invoked as pstruct) 86*0Sstevel@tonic-gate -p generate perl code (default when invoked as c2ph) 87*0Sstevel@tonic-gate -v generate perl code, with C decls as comments 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate -i do NOT recompute sizes for intrinsic datatypes 90*0Sstevel@tonic-gate -a dump information on intrinsics also 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate -t trace execution 93*0Sstevel@tonic-gate -d spew reams of debugging output 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate -slist give comma-separated list a structures to dump 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate=head1 DESCRIPTION 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gateThe following is the old c2ph.doc documentation by Tom Christiansen 100*0Sstevel@tonic-gate<tchrist@perl.com> 101*0Sstevel@tonic-gateDate: 25 Jul 91 08:10:21 GMT 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gateOnce upon a time, I wrote a program called pstruct. It was a perl 104*0Sstevel@tonic-gateprogram that tried to parse out C structures and display their member 105*0Sstevel@tonic-gateoffsets for you. This was especially useful for people looking at 106*0Sstevel@tonic-gatebinary dumps or poking around the kernel. 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gatePstruct was not a pretty program. Neither was it particularly robust. 109*0Sstevel@tonic-gateThe problem, you see, was that the C compiler was much better at parsing 110*0Sstevel@tonic-gateC than I could ever hope to be. 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gateSo I got smart: I decided to be lazy and let the C compiler parse the C, 113*0Sstevel@tonic-gatewhich would spit out debugger stabs for me to read. These were much 114*0Sstevel@tonic-gateeasier to parse. It's still not a pretty program, but at least it's more 115*0Sstevel@tonic-gaterobust. 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gatePstruct takes any .c or .h files, or preferably .s ones, since that's 118*0Sstevel@tonic-gatethe format it is going to massage them into anyway, and spits out 119*0Sstevel@tonic-gatelistings like this: 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate struct tty { 122*0Sstevel@tonic-gate int tty.t_locker 000 4 123*0Sstevel@tonic-gate int tty.t_mutex_index 004 4 124*0Sstevel@tonic-gate struct tty * tty.t_tp_virt 008 4 125*0Sstevel@tonic-gate struct clist tty.t_rawq 00c 20 126*0Sstevel@tonic-gate int tty.t_rawq.c_cc 00c 4 127*0Sstevel@tonic-gate int tty.t_rawq.c_cmax 010 4 128*0Sstevel@tonic-gate int tty.t_rawq.c_cfx 014 4 129*0Sstevel@tonic-gate int tty.t_rawq.c_clx 018 4 130*0Sstevel@tonic-gate struct tty * tty.t_rawq.c_tp_cpu 01c 4 131*0Sstevel@tonic-gate struct tty * tty.t_rawq.c_tp_iop 020 4 132*0Sstevel@tonic-gate unsigned char * tty.t_rawq.c_buf_cpu 024 4 133*0Sstevel@tonic-gate unsigned char * tty.t_rawq.c_buf_iop 028 4 134*0Sstevel@tonic-gate struct clist tty.t_canq 02c 20 135*0Sstevel@tonic-gate int tty.t_canq.c_cc 02c 4 136*0Sstevel@tonic-gate int tty.t_canq.c_cmax 030 4 137*0Sstevel@tonic-gate int tty.t_canq.c_cfx 034 4 138*0Sstevel@tonic-gate int tty.t_canq.c_clx 038 4 139*0Sstevel@tonic-gate struct tty * tty.t_canq.c_tp_cpu 03c 4 140*0Sstevel@tonic-gate struct tty * tty.t_canq.c_tp_iop 040 4 141*0Sstevel@tonic-gate unsigned char * tty.t_canq.c_buf_cpu 044 4 142*0Sstevel@tonic-gate unsigned char * tty.t_canq.c_buf_iop 048 4 143*0Sstevel@tonic-gate struct clist tty.t_outq 04c 20 144*0Sstevel@tonic-gate int tty.t_outq.c_cc 04c 4 145*0Sstevel@tonic-gate int tty.t_outq.c_cmax 050 4 146*0Sstevel@tonic-gate int tty.t_outq.c_cfx 054 4 147*0Sstevel@tonic-gate int tty.t_outq.c_clx 058 4 148*0Sstevel@tonic-gate struct tty * tty.t_outq.c_tp_cpu 05c 4 149*0Sstevel@tonic-gate struct tty * tty.t_outq.c_tp_iop 060 4 150*0Sstevel@tonic-gate unsigned char * tty.t_outq.c_buf_cpu 064 4 151*0Sstevel@tonic-gate unsigned char * tty.t_outq.c_buf_iop 068 4 152*0Sstevel@tonic-gate (*int)() tty.t_oproc_cpu 06c 4 153*0Sstevel@tonic-gate (*int)() tty.t_oproc_iop 070 4 154*0Sstevel@tonic-gate (*int)() tty.t_stopproc_cpu 074 4 155*0Sstevel@tonic-gate (*int)() tty.t_stopproc_iop 078 4 156*0Sstevel@tonic-gate struct thread * tty.t_rsel 07c 4 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gateetc. 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gateActually, this was generated by a particular set of options. You can control 162*0Sstevel@tonic-gatethe formatting of each column, whether you prefer wide or fat, hex or decimal, 163*0Sstevel@tonic-gateleading zeroes or whatever. 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gateAll you need to be able to use this is a C compiler than generates 166*0Sstevel@tonic-gateBSD/GCC-style stabs. The B<-g> option on native BSD compilers and GCC 167*0Sstevel@tonic-gateshould get this for you. 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gateTo learn more, just type a bogus option, like B<-\?>, and a long usage message 170*0Sstevel@tonic-gatewill be provided. There are a fair number of possibilities. 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gateIf you're only a C programmer, than this is the end of the message for you. 173*0Sstevel@tonic-gateYou can quit right now, and if you care to, save off the source and run it 174*0Sstevel@tonic-gatewhen you feel like it. Or not. 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gateBut if you're a perl programmer, then for you I have something much more 179*0Sstevel@tonic-gatewondrous than just a structure offset printer. 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gateYou see, if you call pstruct by its other incybernation, c2ph, you have a code 182*0Sstevel@tonic-gategenerator that translates C code into perl code! Well, structure and union 183*0Sstevel@tonic-gatedeclarations at least, but that's quite a bit. 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gatePrior to this point, anyone programming in perl who wanted to interact 186*0Sstevel@tonic-gatewith C programs, like the kernel, was forced to guess the layouts of 187*0Sstevel@tonic-gatethe C structures, and then hardwire these into his program. Of course, 188*0Sstevel@tonic-gatewhen you took your wonderfully crafted program to a system where the 189*0Sstevel@tonic-gatesgtty structure was laid out differently, your program broke. Which is 190*0Sstevel@tonic-gatea shame. 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gateWe've had Larry's h2ph translator, which helped, but that only works on 193*0Sstevel@tonic-gatecpp symbols, not real C, which was also very much needed. What I offer 194*0Sstevel@tonic-gateyou is a symbolic way of getting at all the C structures. I've couched 195*0Sstevel@tonic-gatethem in terms of packages and functions. Consider the following program: 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate #!/usr/local/bin/perl 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate require 'syscall.ph'; 200*0Sstevel@tonic-gate require 'sys/time.ph'; 201*0Sstevel@tonic-gate require 'sys/resource.ph'; 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate $ru = "\0" x &rusage'sizeof(); 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate syscall(&SYS_getrusage, &RUSAGE_SELF, $ru) && die "getrusage: $!"; 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate @ru = unpack($t = &rusage'typedef(), $ru); 208*0Sstevel@tonic-gate 209*0Sstevel@tonic-gate $utime = $ru[ &rusage'ru_utime + &timeval'tv_sec ] 210*0Sstevel@tonic-gate + ($ru[ &rusage'ru_utime + &timeval'tv_usec ]) / 1e6; 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate $stime = $ru[ &rusage'ru_stime + &timeval'tv_sec ] 213*0Sstevel@tonic-gate + ($ru[ &rusage'ru_stime + &timeval'tv_usec ]) / 1e6; 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate printf "you have used %8.3fs+%8.3fu seconds.\n", $utime, $stime; 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gateAs you see, the name of the package is the name of the structure. Regular 219*0Sstevel@tonic-gatefields are just their own names. Plus the following accessor functions are 220*0Sstevel@tonic-gateprovided for your convenience: 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate struct This takes no arguments, and is merely the number of first-level 223*0Sstevel@tonic-gate elements in the structure. You would use this for indexing 224*0Sstevel@tonic-gate into arrays of structures, perhaps like this 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate $usec = $u[ &user'u_utimer 228*0Sstevel@tonic-gate + (&ITIMER_VIRTUAL * &itimerval'struct) 229*0Sstevel@tonic-gate + &itimerval'it_value 230*0Sstevel@tonic-gate + &timeval'tv_usec 231*0Sstevel@tonic-gate ]; 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate sizeof Returns the bytes in the structure, or the member if 234*0Sstevel@tonic-gate you pass it an argument, such as 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate &rusage'sizeof(&rusage'ru_utime) 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate typedef This is the perl format definition for passing to pack and 239*0Sstevel@tonic-gate unpack. If you ask for the typedef of a nothing, you get 240*0Sstevel@tonic-gate the whole structure, otherwise you get that of the member 241*0Sstevel@tonic-gate you ask for. Padding is taken care of, as is the magic to 242*0Sstevel@tonic-gate guarantee that a union is unpacked into all its aliases. 243*0Sstevel@tonic-gate Bitfields are not quite yet supported however. 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate offsetof This function is the byte offset into the array of that 246*0Sstevel@tonic-gate member. You may wish to use this for indexing directly 247*0Sstevel@tonic-gate into the packed structure with vec() if you're too lazy 248*0Sstevel@tonic-gate to unpack it. 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate typeof Not to be confused with the typedef accessor function, this 251*0Sstevel@tonic-gate one returns the C type of that field. This would allow 252*0Sstevel@tonic-gate you to print out a nice structured pretty print of some 253*0Sstevel@tonic-gate structure without knoning anything about it beforehand. 254*0Sstevel@tonic-gate No args to this one is a noop. Someday I'll post such 255*0Sstevel@tonic-gate a thing to dump out your u structure for you. 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate 258*0Sstevel@tonic-gateThe way I see this being used is like basically this: 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate % h2ph <some_include_file.h > /usr/lib/perl/tmp.ph 261*0Sstevel@tonic-gate % c2ph some_include_file.h >> /usr/lib/perl/tmp.ph 262*0Sstevel@tonic-gate % install 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gateIt's a little tricker with c2ph because you have to get the includes right. 265*0Sstevel@tonic-gateI can't know this for your system, but it's not usually too terribly difficult. 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gateThe code isn't pretty as I mentioned -- I never thought it would be a 1000- 268*0Sstevel@tonic-gateline program when I started, or I might not have begun. :-) But I would have 269*0Sstevel@tonic-gatebeen less cavalier in how the parts of the program communicated with each 270*0Sstevel@tonic-gateother, etc. It might also have helped if I didn't have to divine the makeup 271*0Sstevel@tonic-gateof the stabs on the fly, and then account for micro differences between my 272*0Sstevel@tonic-gatecompiler and gcc. 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gateAnyway, here it is. Should run on perl v4 or greater. Maybe less. 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate --tom 278*0Sstevel@tonic-gate 279*0Sstevel@tonic-gate=cut 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate$RCSID = '$Id: c2ph,v 1.7 95/10/28 10:41:47 tchrist Exp Locker: tchrist $'; 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gateuse File::Temp; 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate###################################################################### 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate# some handy data definitions. many of these can be reset later. 288*0Sstevel@tonic-gate 289*0Sstevel@tonic-gate$bitorder = 'b'; # ascending; set to B for descending bit fields 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate%intrinsics = 292*0Sstevel@tonic-gate%template = ( 293*0Sstevel@tonic-gate 'char', 'c', 294*0Sstevel@tonic-gate 'unsigned char', 'C', 295*0Sstevel@tonic-gate 'short', 's', 296*0Sstevel@tonic-gate 'short int', 's', 297*0Sstevel@tonic-gate 'unsigned short', 'S', 298*0Sstevel@tonic-gate 'unsigned short int', 'S', 299*0Sstevel@tonic-gate 'short unsigned int', 'S', 300*0Sstevel@tonic-gate 'int', 'i', 301*0Sstevel@tonic-gate 'unsigned int', 'I', 302*0Sstevel@tonic-gate 'long', 'l', 303*0Sstevel@tonic-gate 'long int', 'l', 304*0Sstevel@tonic-gate 'unsigned long', 'L', 305*0Sstevel@tonic-gate 'unsigned long', 'L', 306*0Sstevel@tonic-gate 'long unsigned int', 'L', 307*0Sstevel@tonic-gate 'unsigned long int', 'L', 308*0Sstevel@tonic-gate 'long long', 'q', 309*0Sstevel@tonic-gate 'long long int', 'q', 310*0Sstevel@tonic-gate 'unsigned long long', 'Q', 311*0Sstevel@tonic-gate 'unsigned long long int', 'Q', 312*0Sstevel@tonic-gate 'float', 'f', 313*0Sstevel@tonic-gate 'double', 'd', 314*0Sstevel@tonic-gate 'pointer', 'p', 315*0Sstevel@tonic-gate 'null', 'x', 316*0Sstevel@tonic-gate 'neganull', 'X', 317*0Sstevel@tonic-gate 'bit', $bitorder, 318*0Sstevel@tonic-gate); 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate&buildscrunchlist; 321*0Sstevel@tonic-gatedelete $intrinsics{'neganull'}; 322*0Sstevel@tonic-gatedelete $intrinsics{'bit'}; 323*0Sstevel@tonic-gatedelete $intrinsics{'null'}; 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate# use -s to recompute sizes 326*0Sstevel@tonic-gate%sizeof = ( 327*0Sstevel@tonic-gate 'char', '1', 328*0Sstevel@tonic-gate 'unsigned char', '1', 329*0Sstevel@tonic-gate 'short', '2', 330*0Sstevel@tonic-gate 'short int', '2', 331*0Sstevel@tonic-gate 'unsigned short', '2', 332*0Sstevel@tonic-gate 'unsigned short int', '2', 333*0Sstevel@tonic-gate 'short unsigned int', '2', 334*0Sstevel@tonic-gate 'int', '4', 335*0Sstevel@tonic-gate 'unsigned int', '4', 336*0Sstevel@tonic-gate 'long', '4', 337*0Sstevel@tonic-gate 'long int', '4', 338*0Sstevel@tonic-gate 'unsigned long', '4', 339*0Sstevel@tonic-gate 'unsigned long int', '4', 340*0Sstevel@tonic-gate 'long unsigned int', '4', 341*0Sstevel@tonic-gate 'long long', '8', 342*0Sstevel@tonic-gate 'long long int', '8', 343*0Sstevel@tonic-gate 'unsigned long long', '8', 344*0Sstevel@tonic-gate 'unsigned long long int', '8', 345*0Sstevel@tonic-gate 'float', '4', 346*0Sstevel@tonic-gate 'double', '8', 347*0Sstevel@tonic-gate 'pointer', '4', 348*0Sstevel@tonic-gate); 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate($type_width, $member_width, $offset_width, $size_width) = (20, 20, 6, 5); 351*0Sstevel@tonic-gate 352*0Sstevel@tonic-gate($offset_fmt, $size_fmt) = ('d', 'd'); 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate$indent = 2; 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate$CC = 'cc'; 357*0Sstevel@tonic-gate!NO!SUBS! 358*0Sstevel@tonic-gate 359*0Sstevel@tonic-gateif (($Config{gccversion} || '') =~ /^(\d+)\.(\d+)/ 360*0Sstevel@tonic-gate and ($1 > 3 or ($1 == 3 and $2 >= 2))) { 361*0Sstevel@tonic-gate print OUT q/$CFLAGS = '-gstabs -S';/; 362*0Sstevel@tonic-gate} else { 363*0Sstevel@tonic-gate print OUT q/$CFLAGS = '-g -S';/; 364*0Sstevel@tonic-gate} 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gateprint OUT <<'!NO!SUBS!'; 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate$DEFINES = ''; 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate$perl++ if $0 =~ m#/?c2ph$#; 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gaterequire 'getopts.pl'; 373*0Sstevel@tonic-gate 374*0Sstevel@tonic-gateuse File::Temp 'tempdir'; 375*0Sstevel@tonic-gate 376*0Sstevel@tonic-gateeval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift; 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate&Getopts('aixdpvtnws:') || &usage(0); 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate$opt_d && $debug++; 381*0Sstevel@tonic-gate$opt_t && $trace++; 382*0Sstevel@tonic-gate$opt_p && $perl++; 383*0Sstevel@tonic-gate$opt_v && $verbose++; 384*0Sstevel@tonic-gate$opt_n && ($perl = 0); 385*0Sstevel@tonic-gate 386*0Sstevel@tonic-gateif ($opt_w) { 387*0Sstevel@tonic-gate ($type_width, $member_width, $offset_width) = (45, 35, 8); 388*0Sstevel@tonic-gate} 389*0Sstevel@tonic-gateif ($opt_x) { 390*0Sstevel@tonic-gate ($offset_fmt, $offset_width, $size_fmt, $size_width) = ( 'x', '08', 'x', 04 ); 391*0Sstevel@tonic-gate} 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gateeval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift; 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gatesub PLUMBER { 396*0Sstevel@tonic-gate select(STDERR); 397*0Sstevel@tonic-gate print "oops, apperent pager foulup\n"; 398*0Sstevel@tonic-gate $isatty++; 399*0Sstevel@tonic-gate &usage(1); 400*0Sstevel@tonic-gate} 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gatesub usage { 403*0Sstevel@tonic-gate local($oops) = @_; 404*0Sstevel@tonic-gate unless (-t STDOUT) { 405*0Sstevel@tonic-gate select(STDERR); 406*0Sstevel@tonic-gate } elsif (!$oops) { 407*0Sstevel@tonic-gate $isatty++; 408*0Sstevel@tonic-gate $| = 1; 409*0Sstevel@tonic-gate print "hit <RETURN> for further explanation: "; 410*0Sstevel@tonic-gate <STDIN>; 411*0Sstevel@tonic-gate open (PIPE, "|". ($ENV{PAGER} || 'more')); 412*0Sstevel@tonic-gate $SIG{PIPE} = PLUMBER; 413*0Sstevel@tonic-gate select(PIPE); 414*0Sstevel@tonic-gate } 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate print "usage: $0 [-dpnP] [var=val] [files ...]\n"; 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate exit unless $isatty; 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate print <<EOF; 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gateOptions: 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate-w wide; short for: type_width=45 member_width=35 offset_width=8 425*0Sstevel@tonic-gate-x hex; short for: offset_fmt=x offset_width=08 size_fmt=x size_width=04 426*0Sstevel@tonic-gate 427*0Sstevel@tonic-gate-n do not generate perl code (default when invoked as pstruct) 428*0Sstevel@tonic-gate-p generate perl code (default when invoked as c2ph) 429*0Sstevel@tonic-gate-v generate perl code, with C decls as comments 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate-i do NOT recompute sizes for intrinsic datatypes 432*0Sstevel@tonic-gate-a dump information on intrinsics also 433*0Sstevel@tonic-gate 434*0Sstevel@tonic-gate-t trace execution 435*0Sstevel@tonic-gate-d spew reams of debugging output 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate-slist give comma-separated list a structures to dump 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gateVar Name Default Value Meaning 441*0Sstevel@tonic-gate 442*0Sstevel@tonic-gateEOF 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate &defvar('CC', 'which_compiler to call'); 445*0Sstevel@tonic-gate &defvar('CFLAGS', 'how to generate *.s files with stabs'); 446*0Sstevel@tonic-gate &defvar('DEFINES','any extra cflags or cpp defines, like -I, -D, -U'); 447*0Sstevel@tonic-gate 448*0Sstevel@tonic-gate print "\n"; 449*0Sstevel@tonic-gate 450*0Sstevel@tonic-gate &defvar('type_width', 'width of type field (column 1)'); 451*0Sstevel@tonic-gate &defvar('member_width', 'width of member field (column 2)'); 452*0Sstevel@tonic-gate &defvar('offset_width', 'width of offset field (column 3)'); 453*0Sstevel@tonic-gate &defvar('size_width', 'width of size field (column 4)'); 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate print "\n"; 456*0Sstevel@tonic-gate 457*0Sstevel@tonic-gate &defvar('offset_fmt', 'sprintf format type for offset'); 458*0Sstevel@tonic-gate &defvar('size_fmt', 'sprintf format type for size'); 459*0Sstevel@tonic-gate 460*0Sstevel@tonic-gate print "\n"; 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate &defvar('indent', 'how far to indent each nesting level'); 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate print <<'EOF'; 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate If any *.[ch] files are given, these will be catted together into 467*0Sstevel@tonic-gate a temporary *.c file and sent through: 468*0Sstevel@tonic-gate $CC $CFLAGS $DEFINES 469*0Sstevel@tonic-gate and the resulting *.s groped for stab information. If no files are 470*0Sstevel@tonic-gate supplied, then stdin is read directly with the assumption that it 471*0Sstevel@tonic-gate contains stab information. All other liens will be ignored. At 472*0Sstevel@tonic-gate most one *.s file should be supplied. 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gateEOF 475*0Sstevel@tonic-gate close PIPE; 476*0Sstevel@tonic-gate exit 1; 477*0Sstevel@tonic-gate} 478*0Sstevel@tonic-gate 479*0Sstevel@tonic-gatesub defvar { 480*0Sstevel@tonic-gate local($var, $msg) = @_; 481*0Sstevel@tonic-gate printf "%-16s%-15s %s\n", $var, eval "\$$var", $msg; 482*0Sstevel@tonic-gate} 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gatesub safedir { 485*0Sstevel@tonic-gate $SAFEDIR = File::Temp::tempdir("c2ph.XXXXXX", TMPDIR => 1, CLEANUP => 1) 486*0Sstevel@tonic-gate unless (defined($SAFEDIR)); 487*0Sstevel@tonic-gate} 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gateundef $SAFEDIR; 490*0Sstevel@tonic-gate 491*0Sstevel@tonic-gate$recurse = 1; 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gateif (@ARGV) { 494*0Sstevel@tonic-gate if (grep(!/\.[csh]$/,@ARGV)) { 495*0Sstevel@tonic-gate warn "Only *.[csh] files expected!\n"; 496*0Sstevel@tonic-gate &usage; 497*0Sstevel@tonic-gate } 498*0Sstevel@tonic-gate elsif (grep(/\.s$/,@ARGV)) { 499*0Sstevel@tonic-gate if (@ARGV > 1) { 500*0Sstevel@tonic-gate warn "Only one *.s file allowed!\n"; 501*0Sstevel@tonic-gate &usage; 502*0Sstevel@tonic-gate } 503*0Sstevel@tonic-gate } 504*0Sstevel@tonic-gate elsif (@ARGV == 1 && $ARGV[0] =~ /\.c$/) { 505*0Sstevel@tonic-gate local($dir, $file) = $ARGV[0] =~ m#(.*/)?(.*)$#; 506*0Sstevel@tonic-gate $chdir = "cd $dir && " if $dir; 507*0Sstevel@tonic-gate &system("$chdir$CC $CFLAGS $DEFINES $file") && exit 1; 508*0Sstevel@tonic-gate $ARGV[0] =~ s/\.c$/.s/; 509*0Sstevel@tonic-gate } 510*0Sstevel@tonic-gate else { 511*0Sstevel@tonic-gate &safedir; 512*0Sstevel@tonic-gate $TMP = "$SAFEDIR/c2ph.$$.c"; 513*0Sstevel@tonic-gate &system("cat @ARGV > $TMP") && exit 1; 514*0Sstevel@tonic-gate &system("cd $SAFEDIR && $CC $CFLAGS $DEFINES $TMP") && exit 1; 515*0Sstevel@tonic-gate unlink $TMP; 516*0Sstevel@tonic-gate $TMP =~ s/\.c$/.s/; 517*0Sstevel@tonic-gate @ARGV = ($TMP); 518*0Sstevel@tonic-gate } 519*0Sstevel@tonic-gate} 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gateif ($opt_s) { 522*0Sstevel@tonic-gate for (split(/[\s,]+/, $opt_s)) { 523*0Sstevel@tonic-gate $interested{$_}++; 524*0Sstevel@tonic-gate } 525*0Sstevel@tonic-gate} 526*0Sstevel@tonic-gate 527*0Sstevel@tonic-gate 528*0Sstevel@tonic-gate$| = 1 if $debug; 529*0Sstevel@tonic-gate 530*0Sstevel@tonic-gatemain: { 531*0Sstevel@tonic-gate 532*0Sstevel@tonic-gate if ($trace) { 533*0Sstevel@tonic-gate if (-t && !@ARGV) { 534*0Sstevel@tonic-gate print STDERR "reading from your keyboard: "; 535*0Sstevel@tonic-gate } else { 536*0Sstevel@tonic-gate print STDERR "reading from " . (@ARGV ? "@ARGV" : "<STDIN>").": "; 537*0Sstevel@tonic-gate } 538*0Sstevel@tonic-gate } 539*0Sstevel@tonic-gate 540*0Sstevel@tonic-gateSTAB: while (<>) { 541*0Sstevel@tonic-gate if ($trace && !($. % 10)) { 542*0Sstevel@tonic-gate $lineno = $..''; 543*0Sstevel@tonic-gate print STDERR $lineno, "\b" x length($lineno); 544*0Sstevel@tonic-gate } 545*0Sstevel@tonic-gate next unless /^\s*\.stabs\s+/; 546*0Sstevel@tonic-gate $line = $_; 547*0Sstevel@tonic-gate s/^\s*\.stabs\s+//; 548*0Sstevel@tonic-gate if (s/\\\\"[d,]+$//) { 549*0Sstevel@tonic-gate $saveline .= $line; 550*0Sstevel@tonic-gate $savebar = $_; 551*0Sstevel@tonic-gate next STAB; 552*0Sstevel@tonic-gate } 553*0Sstevel@tonic-gate if ($saveline) { 554*0Sstevel@tonic-gate s/^"//; 555*0Sstevel@tonic-gate $_ = $savebar . $_; 556*0Sstevel@tonic-gate $line = $saveline; 557*0Sstevel@tonic-gate } 558*0Sstevel@tonic-gate &stab; 559*0Sstevel@tonic-gate $savebar = $saveline = undef; 560*0Sstevel@tonic-gate } 561*0Sstevel@tonic-gate print STDERR "$.\n" if $trace; 562*0Sstevel@tonic-gate unlink $TMP if $TMP; 563*0Sstevel@tonic-gate 564*0Sstevel@tonic-gate &compute_intrinsics if $perl && !$opt_i; 565*0Sstevel@tonic-gate 566*0Sstevel@tonic-gate print STDERR "resolving types\n" if $trace; 567*0Sstevel@tonic-gate 568*0Sstevel@tonic-gate &resolve_types; 569*0Sstevel@tonic-gate &adjust_start_addrs; 570*0Sstevel@tonic-gate 571*0Sstevel@tonic-gate $sum = 2 + $type_width + $member_width; 572*0Sstevel@tonic-gate $pmask1 = "%-${type_width}s %-${member_width}s"; 573*0Sstevel@tonic-gate $pmask2 = "%-${sum}s %${offset_width}${offset_fmt}%s %${size_width}${size_fmt}%s"; 574*0Sstevel@tonic-gate 575*0Sstevel@tonic-gate 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate if ($perl) { 578*0Sstevel@tonic-gate # resolve template -- should be in stab define order, but even this isn't enough. 579*0Sstevel@tonic-gate print STDERR "\nbuilding type templates: " if $trace; 580*0Sstevel@tonic-gate for $i (reverse 0..$#type) { 581*0Sstevel@tonic-gate next unless defined($name = $type[$i]); 582*0Sstevel@tonic-gate next unless defined $struct{$name}; 583*0Sstevel@tonic-gate ($iname = $name) =~ s/\..*//; 584*0Sstevel@tonic-gate $build_recursed = 0; 585*0Sstevel@tonic-gate &build_template($name) unless defined $template{&psou($name)} || 586*0Sstevel@tonic-gate $opt_s && !$interested{$iname}; 587*0Sstevel@tonic-gate } 588*0Sstevel@tonic-gate print STDERR "\n\n" if $trace; 589*0Sstevel@tonic-gate } 590*0Sstevel@tonic-gate 591*0Sstevel@tonic-gate print STDERR "dumping structs: " if $trace; 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gate local($iam); 594*0Sstevel@tonic-gate 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate 597*0Sstevel@tonic-gate foreach $name (sort keys %struct) { 598*0Sstevel@tonic-gate ($iname = $name) =~ s/\..*//; 599*0Sstevel@tonic-gate next if $opt_s && !$interested{$iname}; 600*0Sstevel@tonic-gate print STDERR "$name " if $trace; 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gate undef @sizeof; 603*0Sstevel@tonic-gate undef @typedef; 604*0Sstevel@tonic-gate undef @offsetof; 605*0Sstevel@tonic-gate undef @indices; 606*0Sstevel@tonic-gate undef @typeof; 607*0Sstevel@tonic-gate undef @fieldnames; 608*0Sstevel@tonic-gate 609*0Sstevel@tonic-gate $mname = &munge($name); 610*0Sstevel@tonic-gate 611*0Sstevel@tonic-gate $fname = &psou($name); 612*0Sstevel@tonic-gate 613*0Sstevel@tonic-gate print "# " if $perl && $verbose; 614*0Sstevel@tonic-gate $pcode = ''; 615*0Sstevel@tonic-gate print "$fname {\n" if !$perl || $verbose; 616*0Sstevel@tonic-gate $template{$fname} = &scrunch($template{$fname}) if $perl; 617*0Sstevel@tonic-gate &pstruct($name,$name,0); 618*0Sstevel@tonic-gate print "# " if $perl && $verbose; 619*0Sstevel@tonic-gate print "}\n" if !$perl || $verbose; 620*0Sstevel@tonic-gate print "\n" if $perl && $verbose; 621*0Sstevel@tonic-gate 622*0Sstevel@tonic-gate if ($perl) { 623*0Sstevel@tonic-gate print "$pcode"; 624*0Sstevel@tonic-gate 625*0Sstevel@tonic-gate printf("\nsub %-32s { %4d; }\n\n", "${mname}'struct", $countof{$name}); 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate print <<EOF; 628*0Sstevel@tonic-gatesub ${mname}'typedef { 629*0Sstevel@tonic-gate local(\$${mname}'index) = shift; 630*0Sstevel@tonic-gate defined \$${mname}'index 631*0Sstevel@tonic-gate ? \$${mname}'typedef[\$${mname}'index] 632*0Sstevel@tonic-gate : \$${mname}'typedef; 633*0Sstevel@tonic-gate} 634*0Sstevel@tonic-gateEOF 635*0Sstevel@tonic-gate 636*0Sstevel@tonic-gate print <<EOF; 637*0Sstevel@tonic-gatesub ${mname}'sizeof { 638*0Sstevel@tonic-gate local(\$${mname}'index) = shift; 639*0Sstevel@tonic-gate defined \$${mname}'index 640*0Sstevel@tonic-gate ? \$${mname}'sizeof[\$${mname}'index] 641*0Sstevel@tonic-gate : \$${mname}'sizeof; 642*0Sstevel@tonic-gate} 643*0Sstevel@tonic-gateEOF 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate print <<EOF; 646*0Sstevel@tonic-gatesub ${mname}'offsetof { 647*0Sstevel@tonic-gate local(\$${mname}'index) = shift; 648*0Sstevel@tonic-gate defined \$${mname}index 649*0Sstevel@tonic-gate ? \$${mname}'offsetof[\$${mname}'index] 650*0Sstevel@tonic-gate : \$${mname}'sizeof; 651*0Sstevel@tonic-gate} 652*0Sstevel@tonic-gateEOF 653*0Sstevel@tonic-gate 654*0Sstevel@tonic-gate print <<EOF; 655*0Sstevel@tonic-gatesub ${mname}'typeof { 656*0Sstevel@tonic-gate local(\$${mname}'index) = shift; 657*0Sstevel@tonic-gate defined \$${mname}index 658*0Sstevel@tonic-gate ? \$${mname}'typeof[\$${mname}'index] 659*0Sstevel@tonic-gate : '$name'; 660*0Sstevel@tonic-gate} 661*0Sstevel@tonic-gateEOF 662*0Sstevel@tonic-gate 663*0Sstevel@tonic-gate print <<EOF; 664*0Sstevel@tonic-gatesub ${mname}'fieldnames { 665*0Sstevel@tonic-gate \@${mname}'fieldnames; 666*0Sstevel@tonic-gate} 667*0Sstevel@tonic-gateEOF 668*0Sstevel@tonic-gate 669*0Sstevel@tonic-gate $iam = ($isastruct{$name} && 's') || ($isaunion{$name} && 'u'); 670*0Sstevel@tonic-gate 671*0Sstevel@tonic-gate print <<EOF; 672*0Sstevel@tonic-gatesub ${mname}'isastruct { 673*0Sstevel@tonic-gate '$iam'; 674*0Sstevel@tonic-gate} 675*0Sstevel@tonic-gateEOF 676*0Sstevel@tonic-gate 677*0Sstevel@tonic-gate print "\$${mname}'typedef = '" . &scrunch($template{$fname}) 678*0Sstevel@tonic-gate . "';\n"; 679*0Sstevel@tonic-gate 680*0Sstevel@tonic-gate print "\$${mname}'sizeof = $sizeof{$name};\n\n"; 681*0Sstevel@tonic-gate 682*0Sstevel@tonic-gate 683*0Sstevel@tonic-gate print "\@${mname}'indices = (", &squishseq(@indices), ");\n"; 684*0Sstevel@tonic-gate 685*0Sstevel@tonic-gate print "\n"; 686*0Sstevel@tonic-gate 687*0Sstevel@tonic-gate print "\@${mname}'typedef[\@${mname}'indices] = (", 688*0Sstevel@tonic-gate join("\n\t", '', @typedef), "\n );\n\n"; 689*0Sstevel@tonic-gate print "\@${mname}'sizeof[\@${mname}'indices] = (", 690*0Sstevel@tonic-gate join("\n\t", '', @sizeof), "\n );\n\n"; 691*0Sstevel@tonic-gate print "\@${mname}'offsetof[\@${mname}'indices] = (", 692*0Sstevel@tonic-gate join("\n\t", '', @offsetof), "\n );\n\n"; 693*0Sstevel@tonic-gate print "\@${mname}'typeof[\@${mname}'indices] = (", 694*0Sstevel@tonic-gate join("\n\t", '', @typeof), "\n );\n\n"; 695*0Sstevel@tonic-gate print "\@${mname}'fieldnames[\@${mname}'indices] = (", 696*0Sstevel@tonic-gate join("\n\t", '', @fieldnames), "\n );\n\n"; 697*0Sstevel@tonic-gate 698*0Sstevel@tonic-gate $template_printed{$fname}++; 699*0Sstevel@tonic-gate $size_printed{$fname}++; 700*0Sstevel@tonic-gate } 701*0Sstevel@tonic-gate print "\n"; 702*0Sstevel@tonic-gate } 703*0Sstevel@tonic-gate 704*0Sstevel@tonic-gate print STDERR "\n" if $trace; 705*0Sstevel@tonic-gate 706*0Sstevel@tonic-gate unless ($perl && $opt_a) { 707*0Sstevel@tonic-gate print "\n1;\n" if $perl; 708*0Sstevel@tonic-gate exit; 709*0Sstevel@tonic-gate } 710*0Sstevel@tonic-gate 711*0Sstevel@tonic-gate 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate foreach $name (sort bysizevalue keys %intrinsics) { 714*0Sstevel@tonic-gate next if $size_printed{$name}; 715*0Sstevel@tonic-gate print '$',&munge($name),"'sizeof = ", $sizeof{$name}, ";\n"; 716*0Sstevel@tonic-gate } 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate print "\n"; 719*0Sstevel@tonic-gate 720*0Sstevel@tonic-gate sub bysizevalue { $sizeof{$a} <=> $sizeof{$b}; } 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate 723*0Sstevel@tonic-gate foreach $name (sort keys %intrinsics) { 724*0Sstevel@tonic-gate print '$',&munge($name),"'typedef = '", $template{$name}, "';\n"; 725*0Sstevel@tonic-gate } 726*0Sstevel@tonic-gate 727*0Sstevel@tonic-gate print "\n1;\n" if $perl; 728*0Sstevel@tonic-gate 729*0Sstevel@tonic-gate exit; 730*0Sstevel@tonic-gate} 731*0Sstevel@tonic-gate 732*0Sstevel@tonic-gate######################################################################################## 733*0Sstevel@tonic-gate 734*0Sstevel@tonic-gate 735*0Sstevel@tonic-gatesub stab { 736*0Sstevel@tonic-gate next unless $continued || /:[\$\w]+(\(\d+,\d+\))?=[\*\$\w]+/; # (\d+,\d+) is for sun 737*0Sstevel@tonic-gate s/"// || next; 738*0Sstevel@tonic-gate s/",([x\d]+),([x\d]+),([x\d]+),.*// || next; 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gate next if /^\s*$/; 741*0Sstevel@tonic-gate 742*0Sstevel@tonic-gate $size = $3 if $3; 743*0Sstevel@tonic-gate $_ = $continued . $_ if length($continued); 744*0Sstevel@tonic-gate if (s/\\\\$//) { 745*0Sstevel@tonic-gate # if last 2 chars of string are '\\' then stab is continued 746*0Sstevel@tonic-gate # in next stab entry 747*0Sstevel@tonic-gate chop; 748*0Sstevel@tonic-gate $continued = $_; 749*0Sstevel@tonic-gate next; 750*0Sstevel@tonic-gate } 751*0Sstevel@tonic-gate $continued = ''; 752*0Sstevel@tonic-gate 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate $line = $_; 755*0Sstevel@tonic-gate 756*0Sstevel@tonic-gate if (($name, $pdecl) = /^([\$ \w]+):[tT]((\d+)(=[rufs*](\d+))+)$/) { 757*0Sstevel@tonic-gate print "$name is a typedef for some funky pointers: $pdecl\n" if $debug; 758*0Sstevel@tonic-gate &pdecl($pdecl); 759*0Sstevel@tonic-gate next; 760*0Sstevel@tonic-gate } 761*0Sstevel@tonic-gate 762*0Sstevel@tonic-gate 763*0Sstevel@tonic-gate 764*0Sstevel@tonic-gate if (/(([ \w]+):t(\d+|\(\d+,\d+\)))=r?(\d+|\(\d+,\d+\))(;\d+;\d+;)?/) { 765*0Sstevel@tonic-gate local($ident) = $2; 766*0Sstevel@tonic-gate push(@intrinsics, $ident); 767*0Sstevel@tonic-gate $typeno = &typeno($3); 768*0Sstevel@tonic-gate $type[$typeno] = $ident; 769*0Sstevel@tonic-gate print STDERR "intrinsic $ident in new type $typeno\n" if $debug; 770*0Sstevel@tonic-gate next; 771*0Sstevel@tonic-gate } 772*0Sstevel@tonic-gate 773*0Sstevel@tonic-gate if (($name, $typeordef, $typeno, $extra, $struct, $_) 774*0Sstevel@tonic-gate = /^([\$ \w]+):([ustT])(\d+|\(\d+,\d+\))(=[rufs*](\d+))?(.*)$/) 775*0Sstevel@tonic-gate { 776*0Sstevel@tonic-gate $typeno = &typeno($typeno); # sun foolery 777*0Sstevel@tonic-gate } 778*0Sstevel@tonic-gate elsif (/^[\$\w]+:/) { 779*0Sstevel@tonic-gate next; # variable 780*0Sstevel@tonic-gate } 781*0Sstevel@tonic-gate else { 782*0Sstevel@tonic-gate warn "can't grok stab: <$_> in: $line " if $_; 783*0Sstevel@tonic-gate next; 784*0Sstevel@tonic-gate } 785*0Sstevel@tonic-gate 786*0Sstevel@tonic-gate #warn "got size $size for $name\n"; 787*0Sstevel@tonic-gate $sizeof{$name} = $size if $size; 788*0Sstevel@tonic-gate 789*0Sstevel@tonic-gate s/;[-\d]*;[-\d]*;$//; # we don't care about ranges 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate $typenos{$name} = $typeno; 792*0Sstevel@tonic-gate 793*0Sstevel@tonic-gate unless (defined $type[$typeno]) { 794*0Sstevel@tonic-gate &panic("type 0??") unless $typeno; 795*0Sstevel@tonic-gate $type[$typeno] = $name unless defined $type[$typeno]; 796*0Sstevel@tonic-gate printf "new type $typeno is $name" if $debug; 797*0Sstevel@tonic-gate if ($extra =~ /\*/ && defined $type[$struct]) { 798*0Sstevel@tonic-gate print ", a typedef for a pointer to " , $type[$struct] if $debug; 799*0Sstevel@tonic-gate } 800*0Sstevel@tonic-gate } else { 801*0Sstevel@tonic-gate printf "%s is type %d", $name, $typeno if $debug; 802*0Sstevel@tonic-gate print ", a typedef for " , $type[$typeno] if $debug; 803*0Sstevel@tonic-gate } 804*0Sstevel@tonic-gate print "\n" if $debug; 805*0Sstevel@tonic-gate #next unless $extra =~ /[su*]/; 806*0Sstevel@tonic-gate 807*0Sstevel@tonic-gate #$type[$struct] = $name; 808*0Sstevel@tonic-gate 809*0Sstevel@tonic-gate if ($extra =~ /[us*]/) { 810*0Sstevel@tonic-gate &sou($name, $extra); 811*0Sstevel@tonic-gate $_ = &sdecl($name, $_, 0); 812*0Sstevel@tonic-gate } 813*0Sstevel@tonic-gate elsif (/^=ar/) { 814*0Sstevel@tonic-gate print "it's a bare array typedef -- that's pretty sick\n" if $debug; 815*0Sstevel@tonic-gate $_ = "$typeno$_"; 816*0Sstevel@tonic-gate $scripts = ''; 817*0Sstevel@tonic-gate $_ = &adecl($_,1); 818*0Sstevel@tonic-gate 819*0Sstevel@tonic-gate } 820*0Sstevel@tonic-gate elsif (s/((\w+):t(\d+|\(\d+,\d+\)))?=r?(;\d+;\d+;)?//) { # the ?'s are for gcc 821*0Sstevel@tonic-gate push(@intrinsics, $2); 822*0Sstevel@tonic-gate $typeno = &typeno($3); 823*0Sstevel@tonic-gate $type[$typeno] = $2; 824*0Sstevel@tonic-gate print STDERR "intrinsic $2 in new type $typeno\n" if $debug; 825*0Sstevel@tonic-gate } 826*0Sstevel@tonic-gate elsif (s/^=e//) { # blessed be thy compiler; mine won't do this 827*0Sstevel@tonic-gate &edecl; 828*0Sstevel@tonic-gate } 829*0Sstevel@tonic-gate else { 830*0Sstevel@tonic-gate warn "Funny remainder for $name on line $_ left in $line " if $_; 831*0Sstevel@tonic-gate } 832*0Sstevel@tonic-gate} 833*0Sstevel@tonic-gate 834*0Sstevel@tonic-gatesub typeno { # sun thinks types are (0,27) instead of just 27 835*0Sstevel@tonic-gate local($_) = @_; 836*0Sstevel@tonic-gate s/\(\d+,(\d+)\)/$1/; 837*0Sstevel@tonic-gate $_; 838*0Sstevel@tonic-gate} 839*0Sstevel@tonic-gate 840*0Sstevel@tonic-gatesub pstruct { 841*0Sstevel@tonic-gate local($what,$prefix,$base) = @_; 842*0Sstevel@tonic-gate local($field, $fieldname, $typeno, $count, $offset, $entry); 843*0Sstevel@tonic-gate local($fieldtype); 844*0Sstevel@tonic-gate local($type, $tname); 845*0Sstevel@tonic-gate local($mytype, $mycount, $entry2); 846*0Sstevel@tonic-gate local($struct_count) = 0; 847*0Sstevel@tonic-gate local($pad, $revpad, $length, $prepad, $lastoffset, $lastlength, $fmt); 848*0Sstevel@tonic-gate local($bits,$bytes); 849*0Sstevel@tonic-gate local($template); 850*0Sstevel@tonic-gate 851*0Sstevel@tonic-gate 852*0Sstevel@tonic-gate local($mname) = &munge($name); 853*0Sstevel@tonic-gate 854*0Sstevel@tonic-gate sub munge { 855*0Sstevel@tonic-gate local($_) = @_; 856*0Sstevel@tonic-gate s/[\s\$\.]/_/g; 857*0Sstevel@tonic-gate $_; 858*0Sstevel@tonic-gate } 859*0Sstevel@tonic-gate 860*0Sstevel@tonic-gate local($sname) = &psou($what); 861*0Sstevel@tonic-gate 862*0Sstevel@tonic-gate $nesting++; 863*0Sstevel@tonic-gate 864*0Sstevel@tonic-gate for $field (split(/;/, $struct{$what})) { 865*0Sstevel@tonic-gate $pad = $prepad = 0; 866*0Sstevel@tonic-gate $entry = ''; 867*0Sstevel@tonic-gate ($fieldname, $typeno, $count, $offset, $length) = split(/,/, $field); 868*0Sstevel@tonic-gate 869*0Sstevel@tonic-gate $type = $type[$typeno]; 870*0Sstevel@tonic-gate 871*0Sstevel@tonic-gate $type =~ /([^[]*)(\[.*\])?/; 872*0Sstevel@tonic-gate $mytype = $1; 873*0Sstevel@tonic-gate $count .= $2; 874*0Sstevel@tonic-gate $fieldtype = &psou($mytype); 875*0Sstevel@tonic-gate 876*0Sstevel@tonic-gate local($fname) = &psou($name); 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate if ($build_templates) { 879*0Sstevel@tonic-gate 880*0Sstevel@tonic-gate $pad = ($offset - ($lastoffset + $lastlength))/8 881*0Sstevel@tonic-gate if defined $lastoffset; 882*0Sstevel@tonic-gate 883*0Sstevel@tonic-gate if (! $finished_template{$sname}) { 884*0Sstevel@tonic-gate if ($isaunion{$what}) { 885*0Sstevel@tonic-gate $template{$sname} .= 'X' x $revpad . ' ' if $revpad; 886*0Sstevel@tonic-gate } else { 887*0Sstevel@tonic-gate $template{$sname} .= 'x' x $pad . ' ' if $pad; 888*0Sstevel@tonic-gate } 889*0Sstevel@tonic-gate } 890*0Sstevel@tonic-gate 891*0Sstevel@tonic-gate $template = &fetch_template($type); 892*0Sstevel@tonic-gate &repeat_template($template,$count); 893*0Sstevel@tonic-gate 894*0Sstevel@tonic-gate if (! $finished_template{$sname}) { 895*0Sstevel@tonic-gate $template{$sname} .= $template; 896*0Sstevel@tonic-gate } 897*0Sstevel@tonic-gate 898*0Sstevel@tonic-gate $revpad = $length/8 if $isaunion{$what}; 899*0Sstevel@tonic-gate 900*0Sstevel@tonic-gate ($lastoffset, $lastlength) = ($offset, $length); 901*0Sstevel@tonic-gate 902*0Sstevel@tonic-gate } else { 903*0Sstevel@tonic-gate print '# ' if $perl && $verbose; 904*0Sstevel@tonic-gate $entry = sprintf($pmask1, 905*0Sstevel@tonic-gate ' ' x ($nesting * $indent) . $fieldtype, 906*0Sstevel@tonic-gate "$prefix.$fieldname" . $count); 907*0Sstevel@tonic-gate 908*0Sstevel@tonic-gate $entry =~ s/(\*+)( )/$2$1/; 909*0Sstevel@tonic-gate 910*0Sstevel@tonic-gate printf $pmask2, 911*0Sstevel@tonic-gate $entry, 912*0Sstevel@tonic-gate ($base+$offset)/8, 913*0Sstevel@tonic-gate ($bits = ($base+$offset)%8) ? ".$bits" : " ", 914*0Sstevel@tonic-gate $length/8, 915*0Sstevel@tonic-gate ($bits = $length % 8) ? ".$bits": "" 916*0Sstevel@tonic-gate if !$perl || $verbose; 917*0Sstevel@tonic-gate 918*0Sstevel@tonic-gate if ($perl) { 919*0Sstevel@tonic-gate $template = &fetch_template($type); 920*0Sstevel@tonic-gate &repeat_template($template,$count); 921*0Sstevel@tonic-gate } 922*0Sstevel@tonic-gate 923*0Sstevel@tonic-gate if ($perl && $nesting == 1) { 924*0Sstevel@tonic-gate 925*0Sstevel@tonic-gate push(@sizeof, int($length/8) .",\t# $fieldname"); 926*0Sstevel@tonic-gate push(@offsetof, int($offset/8) .",\t# $fieldname"); 927*0Sstevel@tonic-gate local($little) = &scrunch($template); 928*0Sstevel@tonic-gate push(@typedef, "'$little', \t# $fieldname"); 929*0Sstevel@tonic-gate $type =~ s/(struct|union) //; 930*0Sstevel@tonic-gate push(@typeof, "'$mytype" . ($count ? $count : '') . 931*0Sstevel@tonic-gate "',\t# $fieldname"); 932*0Sstevel@tonic-gate push(@fieldnames, "'$fieldname',"); 933*0Sstevel@tonic-gate } 934*0Sstevel@tonic-gate 935*0Sstevel@tonic-gate print ' ', ' ' x $indent x $nesting, $template 936*0Sstevel@tonic-gate if $perl && $verbose; 937*0Sstevel@tonic-gate 938*0Sstevel@tonic-gate print "\n" if !$perl || $verbose; 939*0Sstevel@tonic-gate 940*0Sstevel@tonic-gate } 941*0Sstevel@tonic-gate if ($perl) { 942*0Sstevel@tonic-gate local($mycount) = defined $struct{$mytype} ? $countof{$mytype} : 1; 943*0Sstevel@tonic-gate $mycount *= &scripts2count($count) if $count; 944*0Sstevel@tonic-gate if ($nesting==1 && !$build_templates) { 945*0Sstevel@tonic-gate $pcode .= sprintf("sub %-32s { %4d; }\n", 946*0Sstevel@tonic-gate "${mname}'${fieldname}", $struct_count); 947*0Sstevel@tonic-gate push(@indices, $struct_count); 948*0Sstevel@tonic-gate } 949*0Sstevel@tonic-gate $struct_count += $mycount; 950*0Sstevel@tonic-gate } 951*0Sstevel@tonic-gate 952*0Sstevel@tonic-gate 953*0Sstevel@tonic-gate &pstruct($type, "$prefix.$fieldname", $base+$offset) 954*0Sstevel@tonic-gate if $recurse && defined $struct{$type}; 955*0Sstevel@tonic-gate } 956*0Sstevel@tonic-gate 957*0Sstevel@tonic-gate $countof{$what} = $struct_count unless defined $countof{$whati}; 958*0Sstevel@tonic-gate 959*0Sstevel@tonic-gate $template{$sname} .= '$' if $build_templates; 960*0Sstevel@tonic-gate $finished_template{$sname}++; 961*0Sstevel@tonic-gate 962*0Sstevel@tonic-gate if ($build_templates && !defined $sizeof{$name}) { 963*0Sstevel@tonic-gate local($fmt) = &scrunch($template{$sname}); 964*0Sstevel@tonic-gate print STDERR "no size for $name, punting with $fmt..." if $debug; 965*0Sstevel@tonic-gate eval '$sizeof{$name} = length(pack($fmt, ()))'; 966*0Sstevel@tonic-gate if ($@) { 967*0Sstevel@tonic-gate chop $@; 968*0Sstevel@tonic-gate warn "couldn't get size for \$name: $@"; 969*0Sstevel@tonic-gate } else { 970*0Sstevel@tonic-gate print STDERR $sizeof{$name}, "\n" if $debUg; 971*0Sstevel@tonic-gate } 972*0Sstevel@tonic-gate } 973*0Sstevel@tonic-gate 974*0Sstevel@tonic-gate --$nesting; 975*0Sstevel@tonic-gate} 976*0Sstevel@tonic-gate 977*0Sstevel@tonic-gate 978*0Sstevel@tonic-gatesub psize { 979*0Sstevel@tonic-gate local($me) = @_; 980*0Sstevel@tonic-gate local($amstruct) = $struct{$me} ? 'struct ' : ''; 981*0Sstevel@tonic-gate 982*0Sstevel@tonic-gate print '$sizeof{\'', $amstruct, $me, '\'} = '; 983*0Sstevel@tonic-gate printf "%d;\n", $sizeof{$me}; 984*0Sstevel@tonic-gate} 985*0Sstevel@tonic-gate 986*0Sstevel@tonic-gatesub pdecl { 987*0Sstevel@tonic-gate local($pdecl) = @_; 988*0Sstevel@tonic-gate local(@pdecls); 989*0Sstevel@tonic-gate local($tname); 990*0Sstevel@tonic-gate 991*0Sstevel@tonic-gate warn "pdecl: $pdecl\n" if $debug; 992*0Sstevel@tonic-gate 993*0Sstevel@tonic-gate $pdecl =~ s/\(\d+,(\d+)\)/$1/g; 994*0Sstevel@tonic-gate $pdecl =~ s/\*//g; 995*0Sstevel@tonic-gate @pdecls = split(/=/, $pdecl); 996*0Sstevel@tonic-gate $typeno = $pdecls[0]; 997*0Sstevel@tonic-gate $tname = pop @pdecls; 998*0Sstevel@tonic-gate 999*0Sstevel@tonic-gate if ($tname =~ s/^f//) { $tname = "$tname&"; } 1000*0Sstevel@tonic-gate #else { $tname = "$tname*"; } 1001*0Sstevel@tonic-gate 1002*0Sstevel@tonic-gate for (reverse @pdecls) { 1003*0Sstevel@tonic-gate $tname .= s/^f// ? "&" : "*"; 1004*0Sstevel@tonic-gate #$tname =~ s/^f(.*)/$1&/; 1005*0Sstevel@tonic-gate print "type[$_] is $tname\n" if $debug; 1006*0Sstevel@tonic-gate $type[$_] = $tname unless defined $type[$_]; 1007*0Sstevel@tonic-gate } 1008*0Sstevel@tonic-gate} 1009*0Sstevel@tonic-gate 1010*0Sstevel@tonic-gate 1011*0Sstevel@tonic-gate 1012*0Sstevel@tonic-gatesub adecl { 1013*0Sstevel@tonic-gate ($arraytype, $unknown, $lower, $upper) = (); 1014*0Sstevel@tonic-gate #local($typeno); 1015*0Sstevel@tonic-gate # global $typeno, @type 1016*0Sstevel@tonic-gate local($_, $typedef) = @_; 1017*0Sstevel@tonic-gate 1018*0Sstevel@tonic-gate while (s/^((\d+|\(\d+,\d+\))=)?ar(\d+|\(\d+,\d+\));//) { 1019*0Sstevel@tonic-gate ($arraytype, $unknown) = ($2, $3); 1020*0Sstevel@tonic-gate $arraytype = &typeno($arraytype); 1021*0Sstevel@tonic-gate $unknown = &typeno($unknown); 1022*0Sstevel@tonic-gate if (s/^(\d+);(\d+);//) { 1023*0Sstevel@tonic-gate ($lower, $upper) = ($1, $2); 1024*0Sstevel@tonic-gate $scripts .= '[' . ($upper+1) . ']'; 1025*0Sstevel@tonic-gate } else { 1026*0Sstevel@tonic-gate warn "can't find array bounds: $_"; 1027*0Sstevel@tonic-gate } 1028*0Sstevel@tonic-gate } 1029*0Sstevel@tonic-gate if (s/^([(,)\d*f=]*),(\d+),(\d+);//) { 1030*0Sstevel@tonic-gate ($start, $length) = ($2, $3); 1031*0Sstevel@tonic-gate $whatis = $1; 1032*0Sstevel@tonic-gate if ($whatis =~ /^(\d+|\(\d+,\d+\))=/) { 1033*0Sstevel@tonic-gate $typeno = &typeno($1); 1034*0Sstevel@tonic-gate &pdecl($whatis); 1035*0Sstevel@tonic-gate } else { 1036*0Sstevel@tonic-gate $typeno = &typeno($whatis); 1037*0Sstevel@tonic-gate } 1038*0Sstevel@tonic-gate } elsif (s/^(\d+)(=[*suf]\d*)//) { 1039*0Sstevel@tonic-gate local($whatis) = $2; 1040*0Sstevel@tonic-gate 1041*0Sstevel@tonic-gate if ($whatis =~ /[f*]/) { 1042*0Sstevel@tonic-gate &pdecl($whatis); 1043*0Sstevel@tonic-gate } elsif ($whatis =~ /[su]/) { # 1044*0Sstevel@tonic-gate print "$prefix.$fieldname is an array$scripts anon structs; disgusting\n" 1045*0Sstevel@tonic-gate if $debug; 1046*0Sstevel@tonic-gate #$type[$typeno] = $name unless defined $type[$typeno]; 1047*0Sstevel@tonic-gate ##printf "new type $typeno is $name" if $debug; 1048*0Sstevel@tonic-gate $typeno = $1; 1049*0Sstevel@tonic-gate $type[$typeno] = "$prefix.$fieldname"; 1050*0Sstevel@tonic-gate local($name) = $type[$typeno]; 1051*0Sstevel@tonic-gate &sou($name, $whatis); 1052*0Sstevel@tonic-gate $_ = &sdecl($name, $_, $start+$offset); 1053*0Sstevel@tonic-gate 1; 1054*0Sstevel@tonic-gate $start = $start{$name}; 1055*0Sstevel@tonic-gate $offset = $sizeof{$name}; 1056*0Sstevel@tonic-gate $length = $offset; 1057*0Sstevel@tonic-gate } else { 1058*0Sstevel@tonic-gate warn "what's this? $whatis in $line "; 1059*0Sstevel@tonic-gate } 1060*0Sstevel@tonic-gate } elsif (/^\d+$/) { 1061*0Sstevel@tonic-gate $typeno = $_; 1062*0Sstevel@tonic-gate } else { 1063*0Sstevel@tonic-gate warn "bad array stab: $_ in $line "; 1064*0Sstevel@tonic-gate next STAB; 1065*0Sstevel@tonic-gate } 1066*0Sstevel@tonic-gate #local($wasdef) = defined($type[$typeno]) && $debug; 1067*0Sstevel@tonic-gate #if ($typedef) { 1068*0Sstevel@tonic-gate #print "redefining $type[$typeno] to " if $wasdef; 1069*0Sstevel@tonic-gate #$type[$typeno] = "$whatis$scripts"; # unless defined $type[$typeno]; 1070*0Sstevel@tonic-gate #print "$type[$typeno]\n" if $wasdef; 1071*0Sstevel@tonic-gate #} else { 1072*0Sstevel@tonic-gate #$type[$arraytype] = $type[$typeno] unless defined $type[$arraytype]; 1073*0Sstevel@tonic-gate #} 1074*0Sstevel@tonic-gate $type[$arraytype] = "$type[$typeno]$scripts" if defined $type[$typeno]; 1075*0Sstevel@tonic-gate print "type[$arraytype] is $type[$arraytype]\n" if $debug; 1076*0Sstevel@tonic-gate print "$prefix.$fieldname is an array of $type[$arraytype]\n" if $debug; 1077*0Sstevel@tonic-gate $_; 1078*0Sstevel@tonic-gate} 1079*0Sstevel@tonic-gate 1080*0Sstevel@tonic-gate 1081*0Sstevel@tonic-gate 1082*0Sstevel@tonic-gatesub sdecl { 1083*0Sstevel@tonic-gate local($prefix, $_, $offset) = @_; 1084*0Sstevel@tonic-gate 1085*0Sstevel@tonic-gate local($fieldname, $scripts, $type, $arraytype, $unknown, 1086*0Sstevel@tonic-gate $whatis, $pdecl, $upper,$lower, $start,$length) = (); 1087*0Sstevel@tonic-gate local($typeno,$sou); 1088*0Sstevel@tonic-gate 1089*0Sstevel@tonic-gate 1090*0Sstevel@tonic-gateSFIELD: 1091*0Sstevel@tonic-gate while (/^([^;]+);/) { 1092*0Sstevel@tonic-gate $scripts = ''; 1093*0Sstevel@tonic-gate warn "sdecl $_\n" if $debug; 1094*0Sstevel@tonic-gate if (s/^([\$\w]+)://) { 1095*0Sstevel@tonic-gate $fieldname = $1; 1096*0Sstevel@tonic-gate } elsif (s/(\d+)=([us])(\d+|\(\d+,\d+\))//) { # 1097*0Sstevel@tonic-gate $typeno = &typeno($1); 1098*0Sstevel@tonic-gate $type[$typeno] = "$prefix.$fieldname"; 1099*0Sstevel@tonic-gate local($name) = "$prefix.$fieldname"; 1100*0Sstevel@tonic-gate &sou($name,$2); 1101*0Sstevel@tonic-gate $_ = &sdecl("$prefix.$fieldname", $_, $start+$offset); 1102*0Sstevel@tonic-gate $start = $start{$name}; 1103*0Sstevel@tonic-gate $offset += $sizeof{$name}; 1104*0Sstevel@tonic-gate #print "done with anon, start is $start, offset is $offset\n"; 1105*0Sstevel@tonic-gate #next SFIELD; 1106*0Sstevel@tonic-gate } else { 1107*0Sstevel@tonic-gate warn "weird field $_ of $line" if $debug; 1108*0Sstevel@tonic-gate next STAB; 1109*0Sstevel@tonic-gate #$fieldname = &gensym; 1110*0Sstevel@tonic-gate #$_ = &sdecl("$prefix.$fieldname", $_, $start+$offset); 1111*0Sstevel@tonic-gate } 1112*0Sstevel@tonic-gate 1113*0Sstevel@tonic-gate if (/^(\d+|\(\d+,\d+\))=ar/) { 1114*0Sstevel@tonic-gate $_ = &adecl($_); 1115*0Sstevel@tonic-gate } 1116*0Sstevel@tonic-gate elsif (s/^(\d+|\(\d+,\d+\))?,(\d+),(\d+);//) { 1117*0Sstevel@tonic-gate ($start, $length) = ($2, $3); 1118*0Sstevel@tonic-gate &panic("no length?") unless $length; 1119*0Sstevel@tonic-gate $typeno = &typeno($1) if $1; 1120*0Sstevel@tonic-gate } 1121*0Sstevel@tonic-gate elsif (s/^(\d+)=xs\w+:,(\d+),(\d+);//) { 1122*0Sstevel@tonic-gate ($start, $length) = ($2, $3); 1123*0Sstevel@tonic-gate &panic("no length?") unless $length; 1124*0Sstevel@tonic-gate $typeno = &typeno($1) if $1; 1125*0Sstevel@tonic-gate } 1126*0Sstevel@tonic-gate elsif (s/^((\d+|\(\d+,\d+\))(=[*f](\d+|\(\d+,\d+\)))+),(\d+),(\d+);//) { 1127*0Sstevel@tonic-gate ($pdecl, $start, $length) = ($1,$5,$6); 1128*0Sstevel@tonic-gate &pdecl($pdecl); 1129*0Sstevel@tonic-gate } 1130*0Sstevel@tonic-gate elsif (s/(\d+)=([us])(\d+|\(\d+,\d+\))//) { # the dratted anon struct 1131*0Sstevel@tonic-gate ($typeno, $sou) = ($1, $2); 1132*0Sstevel@tonic-gate $typeno = &typeno($typeno); 1133*0Sstevel@tonic-gate if (defined($type[$typeno])) { 1134*0Sstevel@tonic-gate warn "now how did we get type $1 in $fieldname of $line?"; 1135*0Sstevel@tonic-gate } else { 1136*0Sstevel@tonic-gate print "anon type $typeno is $prefix.$fieldname\n" if $debug; 1137*0Sstevel@tonic-gate $type[$typeno] = "$prefix.$fieldname" unless defined $type[$typeno]; 1138*0Sstevel@tonic-gate }; 1139*0Sstevel@tonic-gate local($name) = "$prefix.$fieldname"; 1140*0Sstevel@tonic-gate &sou($name,$sou); 1141*0Sstevel@tonic-gate print "anon ".($isastruct{$name}) ? "struct":"union"." for $prefix.$fieldname\n" if $debug; 1142*0Sstevel@tonic-gate $type[$typeno] = "$prefix.$fieldname"; 1143*0Sstevel@tonic-gate $_ = &sdecl("$prefix.$fieldname", $_, $start+$offset); 1144*0Sstevel@tonic-gate $start = $start{$name}; 1145*0Sstevel@tonic-gate $length = $sizeof{$name}; 1146*0Sstevel@tonic-gate } 1147*0Sstevel@tonic-gate else { 1148*0Sstevel@tonic-gate warn "can't grok stab for $name ($_) in line $line "; 1149*0Sstevel@tonic-gate next STAB; 1150*0Sstevel@tonic-gate } 1151*0Sstevel@tonic-gate 1152*0Sstevel@tonic-gate &panic("no length for $prefix.$fieldname") unless $length; 1153*0Sstevel@tonic-gate $struct{$name} .= join(',', $fieldname, $typeno, $scripts, $start, $length) . ';'; 1154*0Sstevel@tonic-gate } 1155*0Sstevel@tonic-gate if (s/;\d*,(\d+),(\d+);//) { 1156*0Sstevel@tonic-gate local($start, $size) = ($1, $2); 1157*0Sstevel@tonic-gate $sizeof{$prefix} = $size; 1158*0Sstevel@tonic-gate print "start of $prefix is $start, size of $sizeof{$prefix}\n" if $debug; 1159*0Sstevel@tonic-gate $start{$prefix} = $start; 1160*0Sstevel@tonic-gate } 1161*0Sstevel@tonic-gate $_; 1162*0Sstevel@tonic-gate} 1163*0Sstevel@tonic-gate 1164*0Sstevel@tonic-gatesub edecl { 1165*0Sstevel@tonic-gate s/;$//; 1166*0Sstevel@tonic-gate $enum{$name} = $_; 1167*0Sstevel@tonic-gate $_ = ''; 1168*0Sstevel@tonic-gate} 1169*0Sstevel@tonic-gate 1170*0Sstevel@tonic-gatesub resolve_types { 1171*0Sstevel@tonic-gate local($sou); 1172*0Sstevel@tonic-gate for $i (0 .. $#type) { 1173*0Sstevel@tonic-gate next unless defined $type[$i]; 1174*0Sstevel@tonic-gate $_ = $type[$i]; 1175*0Sstevel@tonic-gate unless (/\d/) { 1176*0Sstevel@tonic-gate print "type[$i] $type[$i]\n" if $debug; 1177*0Sstevel@tonic-gate next; 1178*0Sstevel@tonic-gate } 1179*0Sstevel@tonic-gate print "type[$i] $_ ==> " if $debug; 1180*0Sstevel@tonic-gate s/^(\d+)(\**)\&\*(\**)/"$2($3".&type($1) . ')()'/e; 1181*0Sstevel@tonic-gate s/^(\d+)\&/&type($1)/e; 1182*0Sstevel@tonic-gate s/^(\d+)/&type($1)/e; 1183*0Sstevel@tonic-gate s/(\*+)([^*]+)(\*+)/$1$3$2/; 1184*0Sstevel@tonic-gate s/\((\*+)(\w+)(\*+)\)/$3($1$2)/; 1185*0Sstevel@tonic-gate s/^(\d+)([\*\[].*)/&type($1).$2/e; 1186*0Sstevel@tonic-gate #s/(\d+)(\*|(\[[\[\]\d\*]+]\])+)/&type($1).$2/ge; 1187*0Sstevel@tonic-gate $type[$i] = $_; 1188*0Sstevel@tonic-gate print "$_\n" if $debug; 1189*0Sstevel@tonic-gate } 1190*0Sstevel@tonic-gate} 1191*0Sstevel@tonic-gatesub type { &psou($type[$_[0]] || "<UNDEFINED>"); } 1192*0Sstevel@tonic-gate 1193*0Sstevel@tonic-gatesub adjust_start_addrs { 1194*0Sstevel@tonic-gate for (sort keys %start) { 1195*0Sstevel@tonic-gate ($basename = $_) =~ s/\.[^.]+$//; 1196*0Sstevel@tonic-gate $start{$_} += $start{$basename}; 1197*0Sstevel@tonic-gate print "start: $_ @ $start{$_}\n" if $debug; 1198*0Sstevel@tonic-gate } 1199*0Sstevel@tonic-gate} 1200*0Sstevel@tonic-gate 1201*0Sstevel@tonic-gatesub sou { 1202*0Sstevel@tonic-gate local($what, $_) = @_; 1203*0Sstevel@tonic-gate /u/ && $isaunion{$what}++; 1204*0Sstevel@tonic-gate /s/ && $isastruct{$what}++; 1205*0Sstevel@tonic-gate} 1206*0Sstevel@tonic-gate 1207*0Sstevel@tonic-gatesub psou { 1208*0Sstevel@tonic-gate local($what) = @_; 1209*0Sstevel@tonic-gate local($prefix) = ''; 1210*0Sstevel@tonic-gate if ($isaunion{$what}) { 1211*0Sstevel@tonic-gate $prefix = 'union '; 1212*0Sstevel@tonic-gate } elsif ($isastruct{$what}) { 1213*0Sstevel@tonic-gate $prefix = 'struct '; 1214*0Sstevel@tonic-gate } 1215*0Sstevel@tonic-gate $prefix . $what; 1216*0Sstevel@tonic-gate} 1217*0Sstevel@tonic-gate 1218*0Sstevel@tonic-gatesub scrunch { 1219*0Sstevel@tonic-gate local($_) = @_; 1220*0Sstevel@tonic-gate 1221*0Sstevel@tonic-gate return '' if $_ eq ''; 1222*0Sstevel@tonic-gate 1223*0Sstevel@tonic-gate study; 1224*0Sstevel@tonic-gate 1225*0Sstevel@tonic-gate s/\$//g; 1226*0Sstevel@tonic-gate s/ / /g; 1227*0Sstevel@tonic-gate 1 while s/(\w) \1/$1$1/g; 1228*0Sstevel@tonic-gate 1229*0Sstevel@tonic-gate # i wanna say this, but perl resists my efforts: 1230*0Sstevel@tonic-gate # s/(\w)(\1+)/$2 . length($1)/ge; 1231*0Sstevel@tonic-gate 1232*0Sstevel@tonic-gate &quick_scrunch; 1233*0Sstevel@tonic-gate 1234*0Sstevel@tonic-gate s/ $//; 1235*0Sstevel@tonic-gate 1236*0Sstevel@tonic-gate $_; 1237*0Sstevel@tonic-gate} 1238*0Sstevel@tonic-gate 1239*0Sstevel@tonic-gatesub buildscrunchlist { 1240*0Sstevel@tonic-gate $scrunch_code = "sub quick_scrunch {\n"; 1241*0Sstevel@tonic-gate for (values %intrinsics) { 1242*0Sstevel@tonic-gate $scrunch_code .= "\ts/(${_}{2,})/'$_' . length(\$1)/ge;\n"; 1243*0Sstevel@tonic-gate } 1244*0Sstevel@tonic-gate $scrunch_code .= "}\n"; 1245*0Sstevel@tonic-gate print "$scrunch_code" if $debug; 1246*0Sstevel@tonic-gate eval $scrunch_code; 1247*0Sstevel@tonic-gate &panic("can't eval scrunch_code $@ \nscrunch_code") if $@; 1248*0Sstevel@tonic-gate} 1249*0Sstevel@tonic-gate 1250*0Sstevel@tonic-gatesub fetch_template { 1251*0Sstevel@tonic-gate local($mytype) = @_; 1252*0Sstevel@tonic-gate local($fmt); 1253*0Sstevel@tonic-gate local($count) = 1; 1254*0Sstevel@tonic-gate 1255*0Sstevel@tonic-gate &panic("why do you care?") unless $perl; 1256*0Sstevel@tonic-gate 1257*0Sstevel@tonic-gate if ($mytype =~ s/(\[\d+\])+$//) { 1258*0Sstevel@tonic-gate $count .= $1; 1259*0Sstevel@tonic-gate } 1260*0Sstevel@tonic-gate 1261*0Sstevel@tonic-gate if ($mytype =~ /\*/) { 1262*0Sstevel@tonic-gate $fmt = $template{'pointer'}; 1263*0Sstevel@tonic-gate } 1264*0Sstevel@tonic-gate elsif (defined $template{$mytype}) { 1265*0Sstevel@tonic-gate $fmt = $template{$mytype}; 1266*0Sstevel@tonic-gate } 1267*0Sstevel@tonic-gate elsif (defined $struct{$mytype}) { 1268*0Sstevel@tonic-gate if (!defined $template{&psou($mytype)}) { 1269*0Sstevel@tonic-gate &build_template($mytype) unless $mytype eq $name; 1270*0Sstevel@tonic-gate } 1271*0Sstevel@tonic-gate elsif ($template{&psou($mytype)} !~ /\$$/) { 1272*0Sstevel@tonic-gate #warn "incomplete template for $mytype\n"; 1273*0Sstevel@tonic-gate } 1274*0Sstevel@tonic-gate $fmt = $template{&psou($mytype)} || '?'; 1275*0Sstevel@tonic-gate } 1276*0Sstevel@tonic-gate else { 1277*0Sstevel@tonic-gate warn "unknown fmt for $mytype\n"; 1278*0Sstevel@tonic-gate $fmt = '?'; 1279*0Sstevel@tonic-gate } 1280*0Sstevel@tonic-gate 1281*0Sstevel@tonic-gate $fmt x $count . ' '; 1282*0Sstevel@tonic-gate} 1283*0Sstevel@tonic-gate 1284*0Sstevel@tonic-gatesub compute_intrinsics { 1285*0Sstevel@tonic-gate &safedir; 1286*0Sstevel@tonic-gate local($TMP) = "$SAFEDIR/c2ph-i.$$.c"; 1287*0Sstevel@tonic-gate open (TMP, ">$TMP") || die "can't open $TMP: $!"; 1288*0Sstevel@tonic-gate select(TMP); 1289*0Sstevel@tonic-gate 1290*0Sstevel@tonic-gate print STDERR "computing intrinsic sizes: " if $trace; 1291*0Sstevel@tonic-gate 1292*0Sstevel@tonic-gate undef %intrinsics; 1293*0Sstevel@tonic-gate 1294*0Sstevel@tonic-gate print <<'EOF'; 1295*0Sstevel@tonic-gatemain() { 1296*0Sstevel@tonic-gate char *mask = "%d %s\n"; 1297*0Sstevel@tonic-gateEOF 1298*0Sstevel@tonic-gate 1299*0Sstevel@tonic-gate for $type (@intrinsics) { 1300*0Sstevel@tonic-gate next if !$type || $type eq 'void' || $type =~ /complex/; # sun stuff 1301*0Sstevel@tonic-gate print <<"EOF"; 1302*0Sstevel@tonic-gate printf(mask,sizeof($type), "$type"); 1303*0Sstevel@tonic-gateEOF 1304*0Sstevel@tonic-gate } 1305*0Sstevel@tonic-gate 1306*0Sstevel@tonic-gate print <<'EOF'; 1307*0Sstevel@tonic-gate printf(mask,sizeof(char *), "pointer"); 1308*0Sstevel@tonic-gate exit(0); 1309*0Sstevel@tonic-gate} 1310*0Sstevel@tonic-gateEOF 1311*0Sstevel@tonic-gate close TMP; 1312*0Sstevel@tonic-gate 1313*0Sstevel@tonic-gate select(STDOUT); 1314*0Sstevel@tonic-gate open(PIPE, "cd $SAFEDIR && $CC $TMP && $SAFEDIR/a.out|"); 1315*0Sstevel@tonic-gate while (<PIPE>) { 1316*0Sstevel@tonic-gate chop; 1317*0Sstevel@tonic-gate split(' ',$_,2);; 1318*0Sstevel@tonic-gate print "intrinsic $_[1] is size $_[0]\n" if $debug; 1319*0Sstevel@tonic-gate $sizeof{$_[1]} = $_[0]; 1320*0Sstevel@tonic-gate $intrinsics{$_[1]} = $template{$_[0]}; 1321*0Sstevel@tonic-gate } 1322*0Sstevel@tonic-gate close(PIPE) || die "couldn't read intrinsics!"; 1323*0Sstevel@tonic-gate unlink($TMP, '$SAFEDIR/a.out'); 1324*0Sstevel@tonic-gate print STDERR "done\n" if $trace; 1325*0Sstevel@tonic-gate} 1326*0Sstevel@tonic-gate 1327*0Sstevel@tonic-gatesub scripts2count { 1328*0Sstevel@tonic-gate local($_) = @_; 1329*0Sstevel@tonic-gate 1330*0Sstevel@tonic-gate s/^\[//; 1331*0Sstevel@tonic-gate s/\]$//; 1332*0Sstevel@tonic-gate s/\]\[/*/g; 1333*0Sstevel@tonic-gate $_ = eval; 1334*0Sstevel@tonic-gate &panic("$_: $@") if $@; 1335*0Sstevel@tonic-gate $_; 1336*0Sstevel@tonic-gate} 1337*0Sstevel@tonic-gate 1338*0Sstevel@tonic-gatesub system { 1339*0Sstevel@tonic-gate print STDERR "@_\n" if $trace; 1340*0Sstevel@tonic-gate system @_; 1341*0Sstevel@tonic-gate} 1342*0Sstevel@tonic-gate 1343*0Sstevel@tonic-gatesub build_template { 1344*0Sstevel@tonic-gate local($name) = @_; 1345*0Sstevel@tonic-gate 1346*0Sstevel@tonic-gate &panic("already got a template for $name") if defined $template{$name}; 1347*0Sstevel@tonic-gate 1348*0Sstevel@tonic-gate local($build_templates) = 1; 1349*0Sstevel@tonic-gate 1350*0Sstevel@tonic-gate local($lparen) = '(' x $build_recursed; 1351*0Sstevel@tonic-gate local($rparen) = ')' x $build_recursed; 1352*0Sstevel@tonic-gate 1353*0Sstevel@tonic-gate print STDERR "$lparen$name$rparen " if $trace; 1354*0Sstevel@tonic-gate $build_recursed++; 1355*0Sstevel@tonic-gate &pstruct($name,$name,0); 1356*0Sstevel@tonic-gate print STDERR "TEMPLATE for $name is ", $template{&psou($name)}, "\n" if $debug; 1357*0Sstevel@tonic-gate --$build_recursed; 1358*0Sstevel@tonic-gate} 1359*0Sstevel@tonic-gate 1360*0Sstevel@tonic-gate 1361*0Sstevel@tonic-gatesub panic { 1362*0Sstevel@tonic-gate 1363*0Sstevel@tonic-gate select(STDERR); 1364*0Sstevel@tonic-gate 1365*0Sstevel@tonic-gate print "\npanic: @_\n"; 1366*0Sstevel@tonic-gate 1367*0Sstevel@tonic-gate exit 1 if $] <= 4.003; # caller broken 1368*0Sstevel@tonic-gate 1369*0Sstevel@tonic-gate local($i,$_); 1370*0Sstevel@tonic-gate local($p,$f,$l,$s,$h,$a,@a,@sub); 1371*0Sstevel@tonic-gate for ($i = 0; ($p,$f,$l,$s,$h,$w) = caller($i); $i++) { 1372*0Sstevel@tonic-gate @a = @DB'args; 1373*0Sstevel@tonic-gate for (@a) { 1374*0Sstevel@tonic-gate if (/^StB\000/ && length($_) == length($_main{'_main'})) { 1375*0Sstevel@tonic-gate $_ = sprintf("%s",$_); 1376*0Sstevel@tonic-gate } 1377*0Sstevel@tonic-gate else { 1378*0Sstevel@tonic-gate s/'/\\'/g; 1379*0Sstevel@tonic-gate s/([^\0]*)/'$1'/ unless /^-?[\d.]+$/; 1380*0Sstevel@tonic-gate s/([\200-\377])/sprintf("M-%c",ord($1)&0177)/eg; 1381*0Sstevel@tonic-gate s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg; 1382*0Sstevel@tonic-gate } 1383*0Sstevel@tonic-gate } 1384*0Sstevel@tonic-gate $w = $w ? '@ = ' : '$ = '; 1385*0Sstevel@tonic-gate $a = $h ? '(' . join(', ', @a) . ')' : ''; 1386*0Sstevel@tonic-gate push(@sub, "$w&$s$a from file $f line $l\n"); 1387*0Sstevel@tonic-gate last if $signal; 1388*0Sstevel@tonic-gate } 1389*0Sstevel@tonic-gate for ($i=0; $i <= $#sub; $i++) { 1390*0Sstevel@tonic-gate last if $signal; 1391*0Sstevel@tonic-gate print $sub[$i]; 1392*0Sstevel@tonic-gate } 1393*0Sstevel@tonic-gate exit 1; 1394*0Sstevel@tonic-gate} 1395*0Sstevel@tonic-gate 1396*0Sstevel@tonic-gatesub squishseq { 1397*0Sstevel@tonic-gate local($num); 1398*0Sstevel@tonic-gate local($last) = -1e8; 1399*0Sstevel@tonic-gate local($string); 1400*0Sstevel@tonic-gate local($seq) = '..'; 1401*0Sstevel@tonic-gate 1402*0Sstevel@tonic-gate while (defined($num = shift)) { 1403*0Sstevel@tonic-gate if ($num == ($last + 1)) { 1404*0Sstevel@tonic-gate $string .= $seq unless $inseq++; 1405*0Sstevel@tonic-gate $last = $num; 1406*0Sstevel@tonic-gate next; 1407*0Sstevel@tonic-gate } elsif ($inseq) { 1408*0Sstevel@tonic-gate $string .= $last unless $last == -1e8; 1409*0Sstevel@tonic-gate } 1410*0Sstevel@tonic-gate 1411*0Sstevel@tonic-gate $string .= ',' if defined $string; 1412*0Sstevel@tonic-gate $string .= $num; 1413*0Sstevel@tonic-gate $last = $num; 1414*0Sstevel@tonic-gate $inseq = 0; 1415*0Sstevel@tonic-gate } 1416*0Sstevel@tonic-gate $string .= $last if $inseq && $last != -e18; 1417*0Sstevel@tonic-gate $string; 1418*0Sstevel@tonic-gate} 1419*0Sstevel@tonic-gate 1420*0Sstevel@tonic-gatesub repeat_template { 1421*0Sstevel@tonic-gate # local($template, $scripts) = @_; have to change caller's values 1422*0Sstevel@tonic-gate 1423*0Sstevel@tonic-gate if ( $_[1] ) { 1424*0Sstevel@tonic-gate local($ncount) = &scripts2count($_[1]); 1425*0Sstevel@tonic-gate if ($_[0] =~ /^\s*c\s*$/i) { 1426*0Sstevel@tonic-gate $_[0] = "A$ncount "; 1427*0Sstevel@tonic-gate $_[1] = ''; 1428*0Sstevel@tonic-gate } else { 1429*0Sstevel@tonic-gate $_[0] = $template x $ncount; 1430*0Sstevel@tonic-gate } 1431*0Sstevel@tonic-gate } 1432*0Sstevel@tonic-gate} 1433*0Sstevel@tonic-gate!NO!SUBS! 1434*0Sstevel@tonic-gate 1435*0Sstevel@tonic-gateclose OUT or die "Can't close $file: $!"; 1436*0Sstevel@tonic-gatechmod 0755, $file or die "Can't reset permissions for $file: $!\n"; 1437*0Sstevel@tonic-gateunlink 'pstruct'; 1438*0Sstevel@tonic-gateprint "Linking c2ph to pstruct.\n"; 1439*0Sstevel@tonic-gateif (defined $Config{d_link}) { 1440*0Sstevel@tonic-gate link 'c2ph', 'pstruct'; 1441*0Sstevel@tonic-gate} else { 1442*0Sstevel@tonic-gate unshift @INC, '../lib'; 1443*0Sstevel@tonic-gate require File::Copy; 1444*0Sstevel@tonic-gate File::Copy::syscopy('c2ph', 'pstruct'); 1445*0Sstevel@tonic-gate} 1446*0Sstevel@tonic-gateexec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':'; 1447*0Sstevel@tonic-gatechdir $origdir; 1448