xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/utils/c2ph.PL (revision 0:68f95e015346)
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