+#!/usr/bin/perl
+
+use IO;
+use Data::Dumper;
+
+parse('builtins','DATA');
+
+while (@ARGV) {
+ $_= shift @ARGV;
+ die if m/^\-/;
+ $x= new IO::File $_,'r';
+ parse($_,$x);
+}
+
+sub parse ($$) {
+ my ($wh,$f) = @_;
+ while (defined($_= $f->getline)) {
+ chomp; s/^\s+//; s/\s+$//;
+ next if m/^\#/;
+ next if !m/\S/;
+ s/\t/ ' 'x(8-(length $`) % 8) /eg;
+
+ s/^\s+//;
+ $this_indent= length $&;
+ while (@i && $this_indent < $i[0]) { shift @i; }
+ if ($this_indent && (!@i || $this_indent > $i[0])) {
+ unshift @i, $this_indent;
+ }
+
+ if (@i==0 && m/^Table\s+(\w+)$/) {
+ $c_table= $1;
+ undef $c_entry;
+ } elsif (@i==1 && m/^([a-z]\w*)$/ && defined $c_table) {
+ $c_entry= $1;
+ $tables{$c_table}{$c_entry}{A} = [ ];
+ } elsif (@i==2 && m/^(?:\?)?([a-z]\w*)\s.*(\S.*)/
+ && defined $c_entry) {
+ push @{ $tables{$c_table}{$c_entry}{A} }, [ $2, $3, $1 eq '?' ];
+ } elsif (@i==2 && m/^\=\>\s.*(\S.*)/ && defined $c_entry) {
+ $tables{$c_table}{$c_entry}{R}= $1;
+ } elsif (@i==2 && m/^\.\.\.$/ && defined $c_entry) {
+ $tables{$c_table}{$c_entry}{V}= 1;
+ } elsif (@i==0 && s/^Type\s+$//) {
+
+ ($typename,$_)= ($1,$2);
+ $_ .= '@' unless m/\@/;
+ $types{$typename}= $_;
+ } else {
+ badsyntax($wh,$., sprintf
+ "bad directive (indent level %d)", scalar @i);
+ }
+ }
+ $f->error and die $!;
+ $f->close;
+}
+
+print Dumper(\%tables),"\n";
+print Dumper(\%types),"\n";
+
+sub badsyntax ($$$) {
+ die "$_[0]:$_[1]: $_[2]\n";
+}
+
+__DATA__
+Type int
+ int
+Type obj
+ Tcl_Obj *
+Type charfrom
+ (const char*)