xref: /openbsd/gnu/usr.bin/perl/regen/embed_lib.pl (revision e0680481)
1#!/usr/bin/perl -w
2BEGIN {
3    for $n (qw(lib regen)) {
4        if (-e "../$n") {
5            push @INC, "../$n";
6        } elsif (-e "./$n") {
7            push @INC, "./$n";
8        }
9    }
10}
11use strict;
12use warnings;
13use HeaderParser;
14
15# read embed.fnc and regen/opcodes, needed by regen/embed.pl, makedef.pl,
16# autodoc.pl and t/porting/diag.t
17
18require 5.004;	# keep this compatible, an old perl is all we may have before
19                # we build the new one
20
21sub setup_embed {
22    my $prefix = shift || '';
23    my $parser= HeaderParser->new(
24        pre_process_content => sub {
25            my ($self,$line_data)= @_;
26            # HeaderParser knows how to parse and normalize embed_fnc.
27            # calling this here ensures sets up the embed subpacket.
28            $self->tidy_embed_fnc_entry($line_data);
29            my $embed= $line_data->{embed}
30                or return;
31        },
32        post_process_grouped_content => sub {
33            # sort the group content by name.
34            @{$_[1]}=
35                sort {
36                    $a->{embed}{name} cmp $b->{embed}{name}
37                } @{$_[1]};
38        },
39    )->read_file($prefix . 'embed.fnc');
40    my $lines= $parser->lines();
41
42    # add the opcode checker functions automatically.
43    open my $in_fh, '<', $prefix . 'regen/opcodes' or die $!;
44    {
45        my %syms;
46
47        my $line_num = 0;
48        while (my $line= <$in_fh>) {
49            $line_num++;
50            chomp($line);
51            next unless $line;
52            next if $line=~/^#/;
53            my $check = (split /\t+/, $line)[2];
54            next if $syms{$check}++;
55
56            # These are all indirectly referenced by globals.c.
57            my $new= HeaderLine->new(
58                cond => [["defined(PERL_IN_GLOBALS_C) || defined(PERL_IN_OP_C) || defined(PERL_IN_PEEP_C)"]],
59                raw => "pR|OP *|$check|NN OP *o",
60                line => "pR|OP *|$check|NN OP *o",
61                type => "content",
62                level => 1,
63                source => 'regen/opcodes',
64                start_line_num => $line_num,
65            );
66            $parser->tidy_embed_fnc_entry($new);
67            push @$lines, $new;
68        }
69    }
70    close $in_fh
71        or die "Problem reading regen/opcodes: $!";
72
73    # Cluster entries in embed.fnc that have the same #ifdef guards.
74    # Also, split out at the top level the three classes of functions.
75    # The result for each group_content() calls is an arrayref containing
76    # HeaderLine objects, with the embed.fnc data prenormalized, and each
77    # conditional clause containing a sorted list of functions, with
78    # any further conditional clauses following.
79    # Note this is a normalized and relatively smart grouping, and we can
80    # handle if/elif and etc properly. At the cost of being a touch slow.
81
82    return (
83        $parser->group_content($lines,
84                sub { $_[1]->{embed} }),                # everything
85        $parser->group_content($lines,
86                sub { $_[1]->{embed} &&
87                      $_[1]->{embed}{flags}=~/[AC]/ }), # only API and private API
88        $parser->group_content($lines,
89                sub { $_[1]->{embed} &&
90                      $_[1]->{embed}{flags}!~/[AC]/ &&  # otherwise Extensions
91                      $_[1]->{embed}{flags}=~/[E]/ }),
92        $parser->group_content($lines,
93                sub { $_[1]->{embed} &&
94                      $_[1]->{embed}{flags}!~/[AC]/ &&  # everything else.
95                      $_[1]->{embed}{flags}!~/[E]/ }),
96    );
97}
98
991;
100