- my ($type,@lists)=split /\s+/, $_;
- die "No list? $type" if !@lists;
- foreach my $list (@lists) {
- my ($names,$special)=split /:/, $list , 2;
- $special ||= "";
- foreach my $name (split /,/,$names) {
- my $real= $name eq 'resume'
- ? "resume_$type"
- : "${type}_$name";
- my @suffix;
- if (!$special) {
- @suffix=("");
- } elsif ($special=~/\d/) {
- @suffix=(1..$special);
- } elsif ($special eq 'FAIL') {
- @suffix=("","_fail");
- } else {
- die "unknown :type ':$special'";
- }
- foreach my $suffix (@suffix) {
- $name[$ind]="$real$suffix";
- $type[$ind]=$type;
- $rest[$ind]="state for $type";
- ++$ind;
- }
+ die "Uknown optype '$node->{optype}' in ", Dumper($node);
+ }
+ $node->{id}= 0 + @all;
+ push @all, $node;
+ $all{ $node->{name} }= $node;
+
+ if ($node->{longj} && $node->{longj} != 1) {
+ die "longj field must be in [01] if present in ", Dumper($node);
+ }
+
+}
+
+# Parse and add an opcode definition to the global state.
+# What an opcode definition looks like is given in regcomp.sym.
+#
+# Not every opcode definition has all of the components. We should maybe make
+# this nicer/easier to read in the future. Also note that the above is tab
+# sensitive.
+
+# Special comments for an entry precede it, and begin with '#*' and are placed
+# in the generated pod file just before the entry.
+
+sub parse_opcode_def {
+ my ( $text, $line_num, $pod_comment )= @_;
+ my $node= {
+ line_num => $line_num,
+ pod_comment => $pod_comment,
+ optype => "op",
+ };
+
+ # first split the line into three, the initial NAME, a middle part
+ # that we call "desc" which contains various (not well documented) things,
+ # and a comment section.
+ @{$node}{qw(name desc comment)}= /^(\S+)\s+([^\t]+?)\s*;\s*(.*)/
+ or die "Failed to match $_";
+
+ # the content of the "desc" field from the first step is extracted here:
+ @{$node}{qw(type code suffix flags longj)}= split /[,\s]\s*/, $node->{desc};
+
+ defined $node->{$_} or $node->{$_} = ""
+ for qw(type code suffix flags longj);
+
+ register_node($node); # has to be before the type_alias code below
+
+ if ( !$all{ $node->{type} } and !$type_alias{ $node->{type} } ) {
+
+ #warn "Regop type '$node->{type}' from regcomp.sym line $line_num"
+ # ." is not an existing regop, and will be aliased to $node->{name}\n"
+ # if -t STDERR;
+ $type_alias{ $node->{type} }= $node->{name};
+ }
+
+ $longest_name_length= length $node->{name}
+ if length $node->{name} > $longest_name_length;
+}
+
+# parse out a state definition and add the resulting data
+# into the global state. may create multiple new states from
+# a single definition (this is part of the point).
+# Format for states:
+# REGOP \t typelist [ \t typelist]
+# typelist= namelist
+# = namelist:FAIL
+# = name:count
+# Eg:
+# WHILEM A_pre,A_min,A_max,B_min,B_max:FAIL
+# BRANCH next:FAIL
+# CURLYM A,B:FAIL
+#
+# The CURLYM definition would create the states:
+# CURLYM_A, CURLYM_A_fail, CURLYM_B, CURLYM_B_fail
+sub parse_state_def {
+ my ( $text, $line_num, $pod_comment )= @_;
+ my ( $type, @lists )= split /\s+/, $text;
+ die "No list? $type" if !@lists;
+ foreach my $list (@lists) {
+ my ( $names, $special )= split /:/, $list, 2;
+ $special ||= "";
+ foreach my $name ( split /,/, $names ) {
+ my $real=
+ $name eq 'resume'
+ ? "resume_$type"
+ : "${type}_$name";
+ my @suffix;
+ if ( !$special ) {
+ @suffix= ("");
+ }
+ elsif ( $special =~ /\d/ ) {
+ @suffix= ( 1 .. $special );
+ }
+ elsif ( $special eq 'FAIL' ) {
+ @suffix= ( "", "_fail" );
+ }
+ else {
+ die "unknown :type ':$special'";
+ }
+ foreach my $suffix (@suffix) {
+ my $node= {
+ name => "$real$suffix",
+ optype => "state",
+ type => $type || "",
+ comment => "state for $type",
+ line_num => $line_num,
+ };
+ register_node($node);