4 use File::Basename qw(&basename &dirname);
7 # List explicitly here the variables you want Configure to
8 # generate. Metaconfig only looks for shell variables, so you
9 # have to mention them as if they were shell variables, not
10 # %Config entries. Thus you write
12 # to ensure Configure will look for $Config{startperl}.
14 # This forces PL files to create target in same directory as PL file.
15 # This is so that make depend always knows where to find PL derivatives.
18 $file = basename($0, '.PL');
19 $file .= '.com' if $^O eq 'VMS';
21 open OUT,">$file" or die "Can't create $file: $!";
23 print "Extracting $file (with variable substitutions)\n";
25 # In this section, perl variables will be expanded during extraction.
26 # You can use $Config{...} to use Configure variables.
28 print OUT <<"!GROK!THIS!";
30 eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}'
31 if \$running_under_some_shell;
34 # In the following, perl variables are not expanded during extraction.
36 print OUT <<'!NO!SUBS!';
40 # Tom Christiansen, <tchrist@convex.com>
42 # As pstruct, dump C structures as generated from 'cc -g -S' stabs.
43 # As c2ph, do this PLUS generate perl code for getting at the structures.
45 # See the usage message for more. If this isn't enough, read the code.
50 c2ph, pstruct - Dump C structures as generated from C<cc -g -S> stabs
54 c2ph [-dpnP] [var=val] [files ...]
60 -w wide; short for: type_width=45 member_width=35 offset_width=8
61 -x hex; short for: offset_fmt=x offset_width=08 size_fmt=x size_width=04
63 -n do not generate perl code (default when invoked as pstruct)
64 -p generate perl code (default when invoked as c2ph)
65 -v generate perl code, with C decls as comments
67 -i do NOT recompute sizes for intrinsic datatypes
68 -a dump information on intrinsics also
71 -d spew reams of debugging output
73 -slist give comma-separated list a structures to dump
77 The following is the old c2ph.doc documentation by Tom Christiansen
79 Date: 25 Jul 91 08:10:21 GMT
81 Once upon a time, I wrote a program called pstruct. It was a perl
82 program that tried to parse out C structures and display their member
83 offsets for you. This was especially useful for people looking at
84 binary dumps or poking around the kernel.
86 Pstruct was not a pretty program. Neither was it particularly robust.
87 The problem, you see, was that the C compiler was much better at parsing
88 C than I could ever hope to be.
90 So I got smart: I decided to be lazy and let the C compiler parse the C,
91 which would spit out debugger stabs for me to read. These were much
92 easier to parse. It's still not a pretty program, but at least it's more
95 Pstruct takes any .c or .h files, or preferably .s ones, since that's
96 the format it is going to massage them into anyway, and spits out
100 int tty.t_locker 000 4
101 int tty.t_mutex_index 004 4
102 struct tty * tty.t_tp_virt 008 4
103 struct clist tty.t_rawq 00c 20
104 int tty.t_rawq.c_cc 00c 4
105 int tty.t_rawq.c_cmax 010 4
106 int tty.t_rawq.c_cfx 014 4
107 int tty.t_rawq.c_clx 018 4
108 struct tty * tty.t_rawq.c_tp_cpu 01c 4
109 struct tty * tty.t_rawq.c_tp_iop 020 4
110 unsigned char * tty.t_rawq.c_buf_cpu 024 4
111 unsigned char * tty.t_rawq.c_buf_iop 028 4
112 struct clist tty.t_canq 02c 20
113 int tty.t_canq.c_cc 02c 4
114 int tty.t_canq.c_cmax 030 4
115 int tty.t_canq.c_cfx 034 4
116 int tty.t_canq.c_clx 038 4
117 struct tty * tty.t_canq.c_tp_cpu 03c 4
118 struct tty * tty.t_canq.c_tp_iop 040 4
119 unsigned char * tty.t_canq.c_buf_cpu 044 4
120 unsigned char * tty.t_canq.c_buf_iop 048 4
121 struct clist tty.t_outq 04c 20
122 int tty.t_outq.c_cc 04c 4
123 int tty.t_outq.c_cmax 050 4
124 int tty.t_outq.c_cfx 054 4
125 int tty.t_outq.c_clx 058 4
126 struct tty * tty.t_outq.c_tp_cpu 05c 4
127 struct tty * tty.t_outq.c_tp_iop 060 4
128 unsigned char * tty.t_outq.c_buf_cpu 064 4
129 unsigned char * tty.t_outq.c_buf_iop 068 4
130 (*int)() tty.t_oproc_cpu 06c 4
131 (*int)() tty.t_oproc_iop 070 4
132 (*int)() tty.t_stopproc_cpu 074 4
133 (*int)() tty.t_stopproc_iop 078 4
134 struct thread * tty.t_rsel 07c 4
139 Actually, this was generated by a particular set of options. You can control
140 the formatting of each column, whether you prefer wide or fat, hex or decimal,
141 leading zeroes or whatever.
143 All you need to be able to use this is a C compiler than generates
144 BSD/GCC-style stabs. The B<-g> option on native BSD compilers and GCC
145 should get this for you.
147 To learn more, just type a bogus option, like B<-\?>, and a long usage message
148 will be provided. There are a fair number of possibilities.
150 If you're only a C programmer, than this is the end of the message for you.
151 You can quit right now, and if you care to, save off the source and run it
152 when you feel like it. Or not.
156 But if you're a perl programmer, then for you I have something much more
157 wondrous than just a structure offset printer.
159 You see, if you call pstruct by its other incybernation, c2ph, you have a code
160 generator that translates C code into perl code! Well, structure and union
161 declarations at least, but that's quite a bit.
163 Prior to this point, anyone programming in perl who wanted to interact
164 with C programs, like the kernel, was forced to guess the layouts of
165 the C strutures, and then hardwire these into his program. Of course,
166 when you took your wonderfully crafted program to a system where the
167 sgtty structure was laid out differently, you program broke. Which is
170 We've had Larry's h2ph translator, which helped, but that only works on
171 cpp symbols, not real C, which was also very much needed. What I offer
172 you is a symbolic way of getting at all the C structures. I've couched
173 them in terms of packages and functions. Consider the following program:
175 #!/usr/local/bin/perl
177 require 'syscall.ph';
178 require 'sys/time.ph';
179 require 'sys/resource.ph';
181 $ru = "\0" x &rusage'sizeof();
183 syscall(&SYS_getrusage, &RUSAGE_SELF, $ru) && die "getrusage: $!";
185 @ru = unpack($t = &rusage'typedef(), $ru);
187 $utime = $ru[ &rusage'ru_utime + &timeval'tv_sec ]
188 + ($ru[ &rusage'ru_utime + &timeval'tv_usec ]) / 1e6;
190 $stime = $ru[ &rusage'ru_stime + &timeval'tv_sec ]
191 + ($ru[ &rusage'ru_stime + &timeval'tv_usec ]) / 1e6;
193 printf "you have used %8.3fs+%8.3fu seconds.\n", $utime, $stime;
196 As you see, the name of the package is the name of the structure. Regular
197 fields are just their own names. Plus the following accessor functions are
198 provided for your convenience:
200 struct This takes no arguments, and is merely the number of first-level
201 elements in the structure. You would use this for indexing
202 into arrays of structures, perhaps like this
205 $usec = $u[ &user'u_utimer
206 + (&ITIMER_VIRTUAL * &itimerval'struct)
207 + &itimerval'it_value
211 sizeof Returns the bytes in the structure, or the member if
212 you pass it an argument, such as
214 &rusage'sizeof(&rusage'ru_utime)
216 typedef This is the perl format definition for passing to pack and
217 unpack. If you ask for the typedef of a nothing, you get
218 the whole structure, otherwise you get that of the member
219 you ask for. Padding is taken care of, as is the magic to
220 guarantee that a union is unpacked into all its aliases.
221 Bitfields are not quite yet supported however.
223 offsetof This function is the byte offset into the array of that
224 member. You may wish to use this for indexing directly
225 into the packed structure with vec() if you're too lazy
228 typeof Not to be confused with the typedef accessor function, this
229 one returns the C type of that field. This would allow
230 you to print out a nice structured pretty print of some
231 structure without knoning anything about it beforehand.
232 No args to this one is a noop. Someday I'll post such
233 a thing to dump out your u structure for you.
236 The way I see this being used is like basically this:
238 % h2ph <some_include_file.h > /usr/lib/perl/tmp.ph
239 % c2ph some_include_file.h >> /usr/lib/perl/tmp.ph
242 It's a little tricker with c2ph because you have to get the includes right.
243 I can't know this for your system, but it's not usually too terribly difficult.
245 The code isn't pretty as I mentioned -- I never thought it would be a 1000-
246 line program when I started, or I might not have begun. :-) But I would have
247 been less cavalier in how the parts of the program communicated with each
248 other, etc. It might also have helped if I didn't have to divine the makeup
249 of the stabs on the fly, and then account for micro differences between my
252 Anyway, here it is. Should run on perl v4 or greater. Maybe less.
259 $RCSID = '$Id: c2ph,v 1.7 95/10/28 10:41:47 tchrist Exp Locker: tchrist $';
262 ######################################################################
264 # some handy data definitions. many of these can be reset later.
266 $bitorder = 'b'; # ascending; set to B for descending bit fields
271 'unsigned char', 'C',
274 'unsigned short', 'S',
275 'unsigned short int', 'S',
276 'short unsigned int', 'S',
281 'unsigned long', 'L',
282 'unsigned long', 'L',
283 'long unsigned int', 'L',
284 'unsigned long int', 'L',
286 'long long int', 'q',
287 'unsigned long long', 'Q',
288 'unsigned long long int', 'Q',
298 delete $intrinsics{'neganull'};
299 delete $intrinsics{'bit'};
300 delete $intrinsics{'null'};
302 # use -s to recompute sizes
305 'unsigned char', '1',
308 'unsigned short', '2',
309 'unsigned short int', '2',
310 'short unsigned int', '2',
315 'unsigned long', '4',
316 'unsigned long int', '4',
317 'long unsigned int', '4',
319 'long long int', '8',
320 'unsigned long long', '8',
321 'unsigned long long int', '8',
327 ($type_width, $member_width, $offset_width, $size_width) = (20, 20, 6, 5);
329 ($offset_fmt, $size_fmt) = ('d', 'd');
337 $perl++ if $0 =~ m#/?c2ph$#;
339 require 'getopts.pl';
341 eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift;
343 &Getopts('aixdpvtnws:') || &usage(0);
348 $opt_v && $verbose++;
349 $opt_n && ($perl = 0);
352 ($type_width, $member_width, $offset_width) = (45, 35, 8);
355 ($offset_fmt, $offset_width, $size_fmt, $size_width) = ( 'x', '08', 'x', 04 );
358 eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift;
362 print "oops, apperent pager foulup\n";
374 print "hit <RETURN> for further explanation: ";
376 open (PIPE, "|". ($ENV{PAGER} || 'more'));
377 $SIG{PIPE} = PLUMBER;
381 print "usage: $0 [-dpnP] [var=val] [files ...]\n";
389 -w wide; short for: type_width=45 member_width=35 offset_width=8
390 -x hex; short for: offset_fmt=x offset_width=08 size_fmt=x size_width=04
392 -n do not generate perl code (default when invoked as pstruct)
393 -p generate perl code (default when invoked as c2ph)
394 -v generate perl code, with C decls as comments
396 -i do NOT recompute sizes for intrinsic datatypes
397 -a dump information on intrinsics also
400 -d spew reams of debugging output
402 -slist give comma-separated list a structures to dump
405 Var Name Default Value Meaning
409 &defvar('CC', 'which_compiler to call');
410 &defvar('CFLAGS', 'how to generate *.s files with stabs');
411 &defvar('DEFINES','any extra cflags or cpp defines, like -I, -D, -U');
415 &defvar('type_width', 'width of type field (column 1)');
416 &defvar('member_width', 'width of member field (column 2)');
417 &defvar('offset_width', 'width of offset field (column 3)');
418 &defvar('size_width', 'width of size field (column 4)');
422 &defvar('offset_fmt', 'sprintf format type for offset');
423 &defvar('size_fmt', 'sprintf format type for size');
427 &defvar('indent', 'how far to indent each nesting level');
431 If any *.[ch] files are given, these will be catted together into
432 a temporary *.c file and sent through:
434 and the resulting *.s groped for stab information. If no files are
435 supplied, then stdin is read directly with the assumption that it
436 contains stab information. All other liens will be ignored. At
437 most one *.s file should be supplied.
445 local($var, $msg) = @_;
446 printf "%-16s%-15s %s\n", $var, eval "\$$var", $msg;
452 if (grep(!/\.[csh]$/,@ARGV)) {
453 warn "Only *.[csh] files expected!\n";
456 elsif (grep(/\.s$/,@ARGV)) {
458 warn "Only one *.s file allowed!\n";
462 elsif (@ARGV == 1 && $ARGV[0] =~ /\.c$/) {
463 local($dir, $file) = $ARGV[0] =~ m#(.*/)?(.*)$#;
464 $chdir = "cd $dir; " if $dir;
465 &system("$chdir$CC $CFLAGS $DEFINES $file") && exit 1;
466 $ARGV[0] =~ s/\.c$/.s/;
469 $TMP = "/tmp/c2ph.$$.c";
470 &system("cat @ARGV > $TMP") && exit 1;
471 &system("cd /tmp; $CC $CFLAGS $DEFINES $TMP") && exit 1;
479 for (split(/[\s,]+/, $opt_s)) {
491 print STDERR "reading from your keyboard: ";
493 print STDERR "reading from " . (@ARGV ? "@ARGV" : "<STDIN>").": ";
498 if ($trace && !($. % 10)) {
500 print STDERR $lineno, "\b" x length($lineno);
502 next unless /^\s*\.stabs\s+/;
505 if (s/\\\\"[d,]+$//) {
516 $savebar = $saveline = undef;
518 print STDERR "$.\n" if $trace;
521 &compute_intrinsics if $perl && !$opt_i;
523 print STDERR "resolving types\n" if $trace;
528 $sum = 2 + $type_width + $member_width;
529 $pmask1 = "%-${type_width}s %-${member_width}s";
530 $pmask2 = "%-${sum}s %${offset_width}${offset_fmt}%s %${size_width}${size_fmt}%s";
535 # resolve template -- should be in stab define order, but even this isn't enough.
536 print STDERR "\nbuilding type templates: " if $trace;
537 for $i (reverse 0..$#type) {
538 next unless defined($name = $type[$i]);
539 next unless defined $struct{$name};
540 ($iname = $name) =~ s/\..*//;
542 &build_template($name) unless defined $template{&psou($name)} ||
543 $opt_s && !$interested{$iname};
545 print STDERR "\n\n" if $trace;
548 print STDERR "dumping structs: " if $trace;
554 foreach $name (sort keys %struct) {
555 ($iname = $name) =~ s/\..*//;
556 next if $opt_s && !$interested{$iname};
557 print STDERR "$name " if $trace;
566 $mname = &munge($name);
568 $fname = &psou($name);
570 print "# " if $perl && $verbose;
572 print "$fname {\n" if !$perl || $verbose;
573 $template{$fname} = &scrunch($template{$fname}) if $perl;
574 &pstruct($name,$name,0);
575 print "# " if $perl && $verbose;
576 print "}\n" if !$perl || $verbose;
577 print "\n" if $perl && $verbose;
582 printf("\nsub %-32s { %4d; }\n\n", "${mname}'struct", $countof{$name});
585 sub ${mname}'typedef {
586 local(\$${mname}'index) = shift;
587 defined \$${mname}'index
588 ? \$${mname}'typedef[\$${mname}'index]
589 : \$${mname}'typedef;
594 sub ${mname}'sizeof {
595 local(\$${mname}'index) = shift;
596 defined \$${mname}'index
597 ? \$${mname}'sizeof[\$${mname}'index]
603 sub ${mname}'offsetof {
604 local(\$${mname}'index) = shift;
605 defined \$${mname}index
606 ? \$${mname}'offsetof[\$${mname}'index]
612 sub ${mname}'typeof {
613 local(\$${mname}'index) = shift;
614 defined \$${mname}index
615 ? \$${mname}'typeof[\$${mname}'index]
621 sub ${mname}'fieldnames {
622 \@${mname}'fieldnames;
626 $iam = ($isastruct{$name} && 's') || ($isaunion{$name} && 'u');
629 sub ${mname}'isastruct {
634 print "\$${mname}'typedef = '" . &scrunch($template{$fname})
637 print "\$${mname}'sizeof = $sizeof{$name};\n\n";
640 print "\@${mname}'indices = (", &squishseq(@indices), ");\n";
644 print "\@${mname}'typedef[\@${mname}'indices] = (",
645 join("\n\t", '', @typedef), "\n );\n\n";
646 print "\@${mname}'sizeof[\@${mname}'indices] = (",
647 join("\n\t", '', @sizeof), "\n );\n\n";
648 print "\@${mname}'offsetof[\@${mname}'indices] = (",
649 join("\n\t", '', @offsetof), "\n );\n\n";
650 print "\@${mname}'typeof[\@${mname}'indices] = (",
651 join("\n\t", '', @typeof), "\n );\n\n";
652 print "\@${mname}'fieldnames[\@${mname}'indices] = (",
653 join("\n\t", '', @fieldnames), "\n );\n\n";
655 $template_printed{$fname}++;
656 $size_printed{$fname}++;
661 print STDERR "\n" if $trace;
663 unless ($perl && $opt_a) {
664 print "\n1;\n" if $perl;
670 foreach $name (sort bysizevalue keys %intrinsics) {
671 next if $size_printed{$name};
672 print '$',&munge($name),"'sizeof = ", $sizeof{$name}, ";\n";
677 sub bysizevalue { $sizeof{$a} <=> $sizeof{$b}; }
680 foreach $name (sort keys %intrinsics) {
681 print '$',&munge($name),"'typedef = '", $template{$name}, "';\n";
684 print "\n1;\n" if $perl;
689 ########################################################################################
693 next unless $continued || /:[\$\w]+(\(\d+,\d+\))?=[\*\$\w]+/; # (\d+,\d+) is for sun
695 s/",([x\d]+),([x\d]+),([x\d]+),.*// || next;
700 $_ = $continued . $_ if length($continued);
702 # if last 2 chars of string are '\\' then stab is continued
713 if (($name, $pdecl) = /^([\$ \w]+):[tT]((\d+)(=[rufs*](\d+))+)$/) {
714 print "$name is a typedef for some funky pointers: $pdecl\n" if $debug;
721 if (/(([ \w]+):t(\d+|\(\d+,\d+\)))=r?(\d+|\(\d+,\d+\))(;\d+;\d+;)?/) {
723 push(@intrinsics, $ident);
724 $typeno = &typeno($3);
725 $type[$typeno] = $ident;
726 print STDERR "intrinsic $ident in new type $typeno\n" if $debug;
730 if (($name, $typeordef, $typeno, $extra, $struct, $_)
731 = /^([\$ \w]+):([ustT])(\d+|\(\d+,\d+\))(=[rufs*](\d+))?(.*)$/)
733 $typeno = &typeno($typeno); # sun foolery
735 elsif (/^[\$\w]+:/) {
739 warn "can't grok stab: <$_> in: $line " if $_;
743 #warn "got size $size for $name\n";
744 $sizeof{$name} = $size if $size;
746 s/;[-\d]*;[-\d]*;$//; # we don't care about ranges
748 $typenos{$name} = $typeno;
750 unless (defined $type[$typeno]) {
751 &panic("type 0??") unless $typeno;
752 $type[$typeno] = $name unless defined $type[$typeno];
753 printf "new type $typeno is $name" if $debug;
754 if ($extra =~ /\*/ && defined $type[$struct]) {
755 print ", a typedef for a pointer to " , $type[$struct] if $debug;
758 printf "%s is type %d", $name, $typeno if $debug;
759 print ", a typedef for " , $type[$typeno] if $debug;
761 print "\n" if $debug;
762 #next unless $extra =~ /[su*]/;
764 #$type[$struct] = $name;
766 if ($extra =~ /[us*]/) {
768 $_ = &sdecl($name, $_, 0);
771 print "it's a bare array typedef -- that's pretty sick\n" if $debug;
777 elsif (s/((\w+):t(\d+|\(\d+,\d+\)))?=r?(;\d+;\d+;)?//) { # the ?'s are for gcc
778 push(@intrinsics, $2);
779 $typeno = &typeno($3);
781 print STDERR "intrinsic $2 in new type $typeno\n" if $debug;
783 elsif (s/^=e//) { # blessed be thy compiler; mine won't do this
787 warn "Funny remainder for $name on line $_ left in $line " if $_;
791 sub typeno { # sun thinks types are (0,27) instead of just 27
798 local($what,$prefix,$base) = @_;
799 local($field, $fieldname, $typeno, $count, $offset, $entry);
801 local($type, $tname);
802 local($mytype, $mycount, $entry2);
803 local($struct_count) = 0;
804 local($pad, $revpad, $length, $prepad, $lastoffset, $lastlength, $fmt);
809 local($mname) = &munge($name);
817 local($sname) = &psou($what);
821 for $field (split(/;/, $struct{$what})) {
824 ($fieldname, $typeno, $count, $offset, $length) = split(/,/, $field);
826 $type = $type[$typeno];
828 $type =~ /([^[]*)(\[.*\])?/;
831 $fieldtype = &psou($mytype);
833 local($fname) = &psou($name);
835 if ($build_templates) {
837 $pad = ($offset - ($lastoffset + $lastlength))/8
838 if defined $lastoffset;
840 if (! $finished_template{$sname}) {
841 if ($isaunion{$what}) {
842 $template{$sname} .= 'X' x $revpad . ' ' if $revpad;
844 $template{$sname} .= 'x' x $pad . ' ' if $pad;
848 $template = &fetch_template($type);
849 &repeat_template($template,$count);
851 if (! $finished_template{$sname}) {
852 $template{$sname} .= $template;
855 $revpad = $length/8 if $isaunion{$what};
857 ($lastoffset, $lastlength) = ($offset, $length);
860 print '# ' if $perl && $verbose;
861 $entry = sprintf($pmask1,
862 ' ' x ($nesting * $indent) . $fieldtype,
863 "$prefix.$fieldname" . $count);
865 $entry =~ s/(\*+)( )/$2$1/;
870 ($bits = ($base+$offset)%8) ? ".$bits" : " ",
872 ($bits = $length % 8) ? ".$bits": ""
873 if !$perl || $verbose;
876 $template = &fetch_template($type);
877 &repeat_template($template,$count);
880 if ($perl && $nesting == 1) {
882 push(@sizeof, int($length/8) .",\t# $fieldname");
883 push(@offsetof, int($offset/8) .",\t# $fieldname");
884 local($little) = &scrunch($template);
885 push(@typedef, "'$little', \t# $fieldname");
886 $type =~ s/(struct|union) //;
887 push(@typeof, "'$mytype" . ($count ? $count : '') .
889 push(@fieldnames, "'$fieldname',");
892 print ' ', ' ' x $indent x $nesting, $template
893 if $perl && $verbose;
895 print "\n" if !$perl || $verbose;
899 local($mycount) = defined $struct{$mytype} ? $countof{$mytype} : 1;
900 $mycount *= &scripts2count($count) if $count;
901 if ($nesting==1 && !$build_templates) {
902 $pcode .= sprintf("sub %-32s { %4d; }\n",
903 "${mname}'${fieldname}", $struct_count);
904 push(@indices, $struct_count);
906 $struct_count += $mycount;
910 &pstruct($type, "$prefix.$fieldname", $base+$offset)
911 if $recurse && defined $struct{$type};
914 $countof{$what} = $struct_count unless defined $countof{$whati};
916 $template{$sname} .= '$' if $build_templates;
917 $finished_template{$sname}++;
919 if ($build_templates && !defined $sizeof{$name}) {
920 local($fmt) = &scrunch($template{$sname});
921 print STDERR "no size for $name, punting with $fmt..." if $debug;
922 eval '$sizeof{$name} = length(pack($fmt, ()))';
925 warn "couldn't get size for \$name: $@";
927 print STDERR $sizeof{$name}, "\n" if $debUg;
937 local($amstruct) = $struct{$me} ? 'struct ' : '';
939 print '$sizeof{\'', $amstruct, $me, '\'} = ';
940 printf "%d;\n", $sizeof{$me};
948 warn "pdecl: $pdecl\n" if $debug;
950 $pdecl =~ s/\(\d+,(\d+)\)/$1/g;
952 @pdecls = split(/=/, $pdecl);
953 $typeno = $pdecls[0];
954 $tname = pop @pdecls;
956 if ($tname =~ s/^f//) { $tname = "$tname&"; }
957 #else { $tname = "$tname*"; }
959 for (reverse @pdecls) {
960 $tname .= s/^f// ? "&" : "*";
961 #$tname =~ s/^f(.*)/$1&/;
962 print "type[$_] is $tname\n" if $debug;
963 $type[$_] = $tname unless defined $type[$_];
970 ($arraytype, $unknown, $lower, $upper) = ();
972 # global $typeno, @type
973 local($_, $typedef) = @_;
975 while (s/^((\d+|\(\d+,\d+\))=)?ar(\d+|\(\d+,\d+\));//) {
976 ($arraytype, $unknown) = ($2, $3);
977 $arraytype = &typeno($arraytype);
978 $unknown = &typeno($unknown);
979 if (s/^(\d+);(\d+);//) {
980 ($lower, $upper) = ($1, $2);
981 $scripts .= '[' . ($upper+1) . ']';
983 warn "can't find array bounds: $_";
986 if (s/^([(,)\d*f=]*),(\d+),(\d+);//) {
987 ($start, $length) = ($2, $3);
989 if ($whatis =~ /^(\d+|\(\d+,\d+\))=/) {
990 $typeno = &typeno($1);
993 $typeno = &typeno($whatis);
995 } elsif (s/^(\d+)(=[*suf]\d*)//) {
998 if ($whatis =~ /[f*]/) {
1000 } elsif ($whatis =~ /[su]/) { #
1001 print "$prefix.$fieldname is an array$scripts anon structs; disgusting\n"
1003 #$type[$typeno] = $name unless defined $type[$typeno];
1004 ##printf "new type $typeno is $name" if $debug;
1006 $type[$typeno] = "$prefix.$fieldname";
1007 local($name) = $type[$typeno];
1008 &sou($name, $whatis);
1009 $_ = &sdecl($name, $_, $start+$offset);
1011 $start = $start{$name};
1012 $offset = $sizeof{$name};
1015 warn "what's this? $whatis in $line ";
1020 warn "bad array stab: $_ in $line ";
1023 #local($wasdef) = defined($type[$typeno]) && $debug;
1025 #print "redefining $type[$typeno] to " if $wasdef;
1026 #$type[$typeno] = "$whatis$scripts"; # unless defined $type[$typeno];
1027 #print "$type[$typeno]\n" if $wasdef;
1029 #$type[$arraytype] = $type[$typeno] unless defined $type[$arraytype];
1031 $type[$arraytype] = "$type[$typeno]$scripts" if defined $type[$typeno];
1032 print "type[$arraytype] is $type[$arraytype]\n" if $debug;
1033 print "$prefix.$fieldname is an array of $type[$arraytype]\n" if $debug;
1040 local($prefix, $_, $offset) = @_;
1042 local($fieldname, $scripts, $type, $arraytype, $unknown,
1043 $whatis, $pdecl, $upper,$lower, $start,$length) = ();
1044 local($typeno,$sou);
1048 while (/^([^;]+);/) {
1050 warn "sdecl $_\n" if $debug;
1051 if (s/^([\$\w]+)://) {
1053 } elsif (s/(\d+)=([us])(\d+|\(\d+,\d+\))//) { #
1054 $typeno = &typeno($1);
1055 $type[$typeno] = "$prefix.$fieldname";
1056 local($name) = "$prefix.$fieldname";
1058 $_ = &sdecl("$prefix.$fieldname", $_, $start+$offset);
1059 $start = $start{$name};
1060 $offset += $sizeof{$name};
1061 #print "done with anon, start is $start, offset is $offset\n";
1064 warn "weird field $_ of $line" if $debug;
1066 #$fieldname = &gensym;
1067 #$_ = &sdecl("$prefix.$fieldname", $_, $start+$offset);
1070 if (/^(\d+|\(\d+,\d+\))=ar/) {
1073 elsif (s/^(\d+|\(\d+,\d+\))?,(\d+),(\d+);//) {
1074 ($start, $length) = ($2, $3);
1075 &panic("no length?") unless $length;
1076 $typeno = &typeno($1) if $1;
1078 elsif (s/^(\d+)=xs\w+:,(\d+),(\d+);//) {
1079 ($start, $length) = ($2, $3);
1080 &panic("no length?") unless $length;
1081 $typeno = &typeno($1) if $1;
1083 elsif (s/^((\d+|\(\d+,\d+\))(=[*f](\d+|\(\d+,\d+\)))+),(\d+),(\d+);//) {
1084 ($pdecl, $start, $length) = ($1,$5,$6);
1087 elsif (s/(\d+)=([us])(\d+|\(\d+,\d+\))//) { # the dratted anon struct
1088 ($typeno, $sou) = ($1, $2);
1089 $typeno = &typeno($typeno);
1090 if (defined($type[$typeno])) {
1091 warn "now how did we get type $1 in $fieldname of $line?";
1093 print "anon type $typeno is $prefix.$fieldname\n" if $debug;
1094 $type[$typeno] = "$prefix.$fieldname" unless defined $type[$typeno];
1096 local($name) = "$prefix.$fieldname";
1098 print "anon ".($isastruct{$name}) ? "struct":"union"." for $prefix.$fieldname\n" if $debug;
1099 $type[$typeno] = "$prefix.$fieldname";
1100 $_ = &sdecl("$prefix.$fieldname", $_, $start+$offset);
1101 $start = $start{$name};
1102 $length = $sizeof{$name};
1105 warn "can't grok stab for $name ($_) in line $line ";
1109 &panic("no length for $prefix.$fieldname") unless $length;
1110 $struct{$name} .= join(',', $fieldname, $typeno, $scripts, $start, $length) . ';';
1112 if (s/;\d*,(\d+),(\d+);//) {
1113 local($start, $size) = ($1, $2);
1114 $sizeof{$prefix} = $size;
1115 print "start of $prefix is $start, size of $sizeof{$prefix}\n" if $debug;
1116 $start{$prefix} = $start;
1129 for $i (0 .. $#type) {
1130 next unless defined $type[$i];
1133 print "type[$i] $type[$i]\n" if $debug;
1136 print "type[$i] $_ ==> " if $debug;
1137 s/^(\d+)(\**)\&\*(\**)/"$2($3".&type($1) . ')()'/e;
1138 s/^(\d+)\&/&type($1)/e;
1139 s/^(\d+)/&type($1)/e;
1140 s/(\*+)([^*]+)(\*+)/$1$3$2/;
1141 s/\((\*+)(\w+)(\*+)\)/$3($1$2)/;
1142 s/^(\d+)([\*\[].*)/&type($1).$2/e;
1143 #s/(\d+)(\*|(\[[\[\]\d\*]+]\])+)/&type($1).$2/ge;
1145 print "$_\n" if $debug;
1148 sub type { &psou($type[$_[0]] || "<UNDEFINED>"); }
1150 sub adjust_start_addrs {
1151 for (sort keys %start) {
1152 ($basename = $_) =~ s/\.[^.]+$//;
1153 $start{$_} += $start{$basename};
1154 print "start: $_ @ $start{$_}\n" if $debug;
1159 local($what, $_) = @_;
1160 /u/ && $isaunion{$what}++;
1161 /s/ && $isastruct{$what}++;
1166 local($prefix) = '';
1167 if ($isaunion{$what}) {
1169 } elsif ($isastruct{$what}) {
1170 $prefix = 'struct ';
1178 return '' if $_ eq '';
1184 1 while s/(\w) \1/$1$1/g;
1186 # i wanna say this, but perl resists my efforts:
1187 # s/(\w)(\1+)/$2 . length($1)/ge;
1196 sub buildscrunchlist {
1197 $scrunch_code = "sub quick_scrunch {\n";
1198 for (values %intrinsics) {
1199 $scrunch_code .= "\ts/(${_}{2,})/'$_' . length(\$1)/ge;\n";
1201 $scrunch_code .= "}\n";
1202 print "$scrunch_code" if $debug;
1204 &panic("can't eval scrunch_code $@ \nscrunch_code") if $@;
1207 sub fetch_template {
1208 local($mytype) = @_;
1212 &panic("why do you care?") unless $perl;
1214 if ($mytype =~ s/(\[\d+\])+$//) {
1218 if ($mytype =~ /\*/) {
1219 $fmt = $template{'pointer'};
1221 elsif (defined $template{$mytype}) {
1222 $fmt = $template{$mytype};
1224 elsif (defined $struct{$mytype}) {
1225 if (!defined $template{&psou($mytype)}) {
1226 &build_template($mytype) unless $mytype eq $name;
1228 elsif ($template{&psou($mytype)} !~ /\$$/) {
1229 #warn "incomplete template for $mytype\n";
1231 $fmt = $template{&psou($mytype)} || '?';
1234 warn "unknown fmt for $mytype\n";
1238 $fmt x $count . ' ';
1241 sub compute_intrinsics {
1242 local($TMP) = "/tmp/c2ph-i.$$.c";
1243 open (TMP, ">$TMP") || die "can't open $TMP: $!";
1246 print STDERR "computing intrinsic sizes: " if $trace;
1252 char *mask = "%d %s\n";
1255 for $type (@intrinsics) {
1256 next if !$type || $type eq 'void' || $type =~ /complex/; # sun stuff
1258 printf(mask,sizeof($type), "$type");
1263 printf(mask,sizeof(char *), "pointer");
1270 open(PIPE, "cd /tmp && $CC $TMP && /tmp/a.out|");
1274 print "intrinsic $_[1] is size $_[0]\n" if $debug;
1275 $sizeof{$_[1]} = $_[0];
1276 $intrinsics{$_[1]} = $template{$_[0]};
1278 close(PIPE) || die "couldn't read intrinsics!";
1279 unlink($TMP, '/tmp/a.out');
1280 print STDERR "done\n" if $trace;
1290 &panic("$_: $@") if $@;
1295 print STDERR "@_\n" if $trace;
1299 sub build_template {
1302 &panic("already got a template for $name") if defined $template{$name};
1304 local($build_templates) = 1;
1306 local($lparen) = '(' x $build_recursed;
1307 local($rparen) = ')' x $build_recursed;
1309 print STDERR "$lparen$name$rparen " if $trace;
1311 &pstruct($name,$name,0);
1312 print STDERR "TEMPLATE for $name is ", $template{&psou($name)}, "\n" if $debug;
1321 print "\npanic: @_\n";
1323 exit 1 if $] <= 4.003; # caller broken
1326 local($p,$f,$l,$s,$h,$a,@a,@sub);
1327 for ($i = 0; ($p,$f,$l,$s,$h,$w) = caller($i); $i++) {
1330 if (/^StB\000/ && length($_) == length($_main{'_main'})) {
1331 $_ = sprintf("%s",$_);
1335 s/([^\0]*)/'$1'/ unless /^-?[\d.]+$/;
1336 s/([\200-\377])/sprintf("M-%c",ord($1)&0177)/eg;
1337 s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg;
1340 $w = $w ? '@ = ' : '$ = ';
1341 $a = $h ? '(' . join(', ', @a) . ')' : '';
1342 push(@sub, "$w&$s$a from file $f line $l\n");
1345 for ($i=0; $i <= $#sub; $i++) {
1354 local($last) = -1e8;
1358 while (defined($num = shift)) {
1359 if ($num == ($last + 1)) {
1360 $string .= $seq unless $inseq++;
1364 $string .= $last unless $last == -1e8;
1367 $string .= ',' if defined $string;
1372 $string .= $last if $inseq && $last != -e18;
1376 sub repeat_template {
1377 # local($template, $scripts) = @_; have to change caller's values
1380 local($ncount) = &scripts2count($_[1]);
1381 if ($_[0] =~ /^\s*c\s*$/i) {
1382 $_[0] = "A$ncount ";
1385 $_[0] = $template x $ncount;
1391 close OUT or die "Can't close $file: $!";
1392 chmod 0755, $file or die "Can't reset permissions for $file: $!\n";
1394 print "Linking c2ph to pstruct.\n";
1395 if (defined $Config{d_link}) {
1396 link 'c2ph', 'pstruct';
1398 unshift @INC, '../lib';
1400 File::Copy::syscopy('c2ph', 'pstruct');
1402 exec("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';