home *** CD-ROM | disk | FTP | other *** search
- Article 484 of comp.lang.perl:
- Xref: netlabs comp.lang.perl:484 comp.lang.c:983 alt.sources:134
- Path: netlabs!psinntp!iggy.GW.Vitalink.COM!lll-winken!sun-barr!cronkite.Central.Sun.COM!spdev!texsun!convex!tchrist
- From: tchrist@convex.com (Tom Christiansen)
- Newsgroups: comp.lang.perl,comp.lang.c,alt.sources
- Subject: pstruct -- a C structure formatter; AKA c2ph, a C to perl header translator
- Keywords: C perl tranlator
- Message-ID: <1991Jul25.081021.8104@convex.com>
- Date: 25 Jul 91 08:10:21 GMT
- Sender: usenet@convex.com (news access account)
- Followup-To: comp.lang.perl
- Organization: CONVEX Computer Corporation, Richardson, Tx., USA
- Lines: 1208
- Nntp-Posting-Host: pixel.convex.com
-
- Once upon a time, I wrote a program called pstruct. It was a perl
- program that tried to parse out C structures and display their member
- offsets for you. This was especially useful for people looking at
- binary dumps or poking around the kernel.
-
- Pstruct was not a pretty program. Neither was it particularly robust.
- The problem, you see, was that the C compiler was much better at parsing
- C than I could ever hope to be.
-
- So I got smart: I decided to be lazy and let the C compiler parse the C,
- which would spit out debugger stabs for me to read. These were much
- easier to parse. It's still not a pretty program, but at least it's more
- robust.
-
- Pstruct takes any .c or .h files, or preferably .s ones, since that's
- the format it is going to massage them into anyway, and spits out
- listings like this:
-
- struct tty {
- int tty.t_locker 000 4
- int tty.t_mutex_index 004 4
- struct tty * tty.t_tp_virt 008 4
- struct clist tty.t_rawq 00c 20
- int tty.t_rawq.c_cc 00c 4
- int tty.t_rawq.c_cmax 010 4
- int tty.t_rawq.c_cfx 014 4
- int tty.t_rawq.c_clx 018 4
- struct tty * tty.t_rawq.c_tp_cpu 01c 4
- struct tty * tty.t_rawq.c_tp_iop 020 4
- unsigned char * tty.t_rawq.c_buf_cpu 024 4
- unsigned char * tty.t_rawq.c_buf_iop 028 4
- struct clist tty.t_canq 02c 20
- int tty.t_canq.c_cc 02c 4
- int tty.t_canq.c_cmax 030 4
- int tty.t_canq.c_cfx 034 4
- int tty.t_canq.c_clx 038 4
- struct tty * tty.t_canq.c_tp_cpu 03c 4
- struct tty * tty.t_canq.c_tp_iop 040 4
- unsigned char * tty.t_canq.c_buf_cpu 044 4
- unsigned char * tty.t_canq.c_buf_iop 048 4
- struct clist tty.t_outq 04c 20
- int tty.t_outq.c_cc 04c 4
- int tty.t_outq.c_cmax 050 4
- int tty.t_outq.c_cfx 054 4
- int tty.t_outq.c_clx 058 4
- struct tty * tty.t_outq.c_tp_cpu 05c 4
- struct tty * tty.t_outq.c_tp_iop 060 4
- unsigned char * tty.t_outq.c_buf_cpu 064 4
- unsigned char * tty.t_outq.c_buf_iop 068 4
- (*int)() tty.t_oproc_cpu 06c 4
- (*int)() tty.t_oproc_iop 070 4
- (*int)() tty.t_stopproc_cpu 074 4
- (*int)() tty.t_stopproc_iop 078 4
- struct thread * tty.t_rsel 07c 4
-
- etc.
-
-
- Actually, this was generated by a particular set of options. You can control
- the formatting of each column, whether you prefer wide or fat, hex or decimal,
- leading zeroes or whatever.
-
- All you need to be able to use this is a C compiler than generates
- BSD/GCC-style stabs. The -g option on native BSD compilers and GCC
- should get this for you.
-
- To learn more, just type a bogus option, like -\?, and a long usage message
- will be provided. There are a fair number of possibilities.
-
- If you're only a C programmer, than this is the end of the message for you.
- You can quit right now, and if you care to, save off the source and run it
- when you feel like it. Or not.
-
-
-
- But if you're a perl programmer, then for you I have something much more
- wondrous than just a structure offset printer.
-
- You see, if you call pstruct by its other incybernation, c2ph, you have a code
- generator that translates C code into perl code! Well, structure and union
- declarations at least, but that's quite a bit.
-
- Prior to this point, anyone programming in perl who wanted to interact
- with C programs, like the kernel, was forced to guess the layouts of the C
- strutures, and then hardwire these into his program. Of course, when you
- took your wonderfully to a system where the sgtty structure was laid out
- differently, you program broke. Which is a shame.
-
- We've had Larry's h2ph translator, which helped, but that only works on
- cpp symbols, not real C, which was also very much needed. What I offer
- you is a symbolic way of getting at all the C structures. I've couched
- them in terms of packages and functions. Consider the following program:
-
- #!/usr/local/bin/perl
-
- require 'syscall.ph';
- require 'sys/time.ph';
- require 'sys/resource.ph';
-
- $ru = "\0" x &rusage'sizeof();
-
- syscall(&SYS_getrusage, &RUSAGE_SELF, $ru) && die "getrusage: $!";
-
- @ru = unpack($t = &rusage'typedef(), $ru);
-
- $utime = $ru[ &rusage'ru_utime + &timeval'tv_sec ]
- + ($ru[ &rusage'ru_utime + &timeval'tv_usec ]) / 1e6;
-
- $stime = $ru[ &rusage'ru_stime + &timeval'tv_sec ]
- + ($ru[ &rusage'ru_stime + &timeval'tv_usec ]) / 1e6;
-
- printf "you have used %8.3fs+%8.3fu seconds.\n", $utime, $stime;
-
-
- As you see, the name of the package is the name of the structure. Regular
- fields are just their own names. Plus the follwoing accessor functions are
- provided for your convenience:
-
- struct This takes no arguments, and is merely the number of first-level
- elements in the structure. You would use this for indexing
- into arrays of structures, perhaps like this
-
-
- $usec = $u[ &user'u_utimer
- + (&ITIMER_VIRTUAL * &itimerval'struct)
- + &itimerval'it_value
- + &timeval'tv_usec
- ];
-
- sizeof Returns the bytes in the structure, or the member if
- you pass it an argument, such as
-
- &rusage'sizeof(&rusage'ru_utime)
-
- typedef This is the perl format definition for passing to pack and
- unpack. If you ask for the typedef of a nothing, you get
- the whole structure, otherwise you get that of the member
- you ask for. Padding is taken care of, as is the magic to
- guarantee that a union is unpacked into all its aliases.
- Bitfields are not quite yet supported however.
-
- offsetof This function is the byte offset into the array of that
- member. You may wish to use this for indexing directly
- into the packed structure with vec() if you're too lazy
- to unpack it.
-
- typeof Not to be confused with the typedef accessor function, this
- one returns the C type of that field. This would allow
- you to print out a nice structured pretty print of some
- structure without knoning anything about it beforehand.
- No args to this one is a noop. Someday I'll post such
- a thing to dump out your u structure for you.
-
-
- The way I see this being used is like basically this:
-
- % h2ph <some_include_file.h > /usr/lib/perl/tmp.ph
- % c2ph some_include_file.h >> /usr/lib/perl/tmp.ph
- % install
-
- It's a little tricker with c2ph because you have to get the includes right.
- I can't know this for your system, but it's not usually too terribly difficult.
-
- The code isn't pretty as I mentioned -- I never thought it would be a 1000-
- line program when I started, or I might not have begun. :-) But I would have
- been less cavalier in how the parts of the program communicated with each
- other, etc. It might also have helped if I didn't have to divine the makeup
- of the stabs on the fly, and then account for micro differences between my
- compiler and gcc.
-
- Anyway, here it is. Should run on perl v4 or greater. Maybe less.
-
-
- --tom
-
-
-