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