extract_defines revision 7c478bd95313f5f23a4c958a745db2134aa03244
#
# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License, Version 1.0 only
# (the "License"). You may not use this file except in compliance
# with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#ident "%Z%%M% %I% %E% SMI"
#
# This script scans the exacct header files and extracts the names of any
# #defines that are to be exported by the Exacct modules. All such #defines
# are written out as an array of structs to a file which is subsequently
# included into the module. Parameters to this script are the name of the
# module to generate for, and the output file to use.
#
use warnings;
use strict;
# Forward declarations
sub default_typefn;
sub catalog_typefn;
#
# Map of module names to files and lists + patterns of macros to declare.
# Each entry in the hash is keyed by the module name, and the value of each
# entry is a list of actions, where each action is a (keyword, param) pair.
# The valid actions are:
# typefn => <fn_ptr>
# fn_ptr is a function which when given a constant name,
# returns the type - see default_typefn and catalog_typefn.
# declare => [ <constant>, ... ]
# Add the passed list of constants.
# scan => [ <file> <regular expression> ]
# Scan the specified file in /usr/include
# for #defines that match the passed RE.
#
our %ModMap = (
Exacct => [
typefn => \&default_typefn,
declare => [ qw(P_PID P_TASKID P_PROJID) ],
scan => [ 'sys/exacct.h' =>
qr/(?:EW|EP|EXR)_\w+/ ],
],
Catalog => [
typefn => \&catalog_typefn,
scan => [ 'sys/exacct_catalog.h' =>
qr/EX[TCD]_\w+/ ],
],
File => [
typefn => \&default_typefn,
# From exacct.h.
declare => [ qw(EO_HEAD EO_TAIL EO_NO_VALID_HDR
EO_POSN_MSK EO_VALIDATE_MSK) ],
],
Object => [
typefn => \&default_typefn,
# From sys/exacct.h.
declare => [ qw(EO_ERROR EO_NONE EO_ITEM EO_GROUP) ],
],
);
#
# Constants may have a 'type' associated, currently only used by ::Catalog
# (see below). For all other cases the type is 'other'.
#
sub default_typefn
{
return('other');
}
#
# ::Catalog uses the 'type' field to determine whether a given constant is a
# type, a catalog or a data id. This function works out what type of constant
# has been passed and returns the appropriate type.
#
sub catalog_typefn
{
my ($define) = @_;
if ($define =~ /_MASK$/) {
return('other');
} elsif ($define =~ /^EXT_/) {
return('type');
} elsif ($define =~ /^EXC_/) {
return('catlg');
} elsif ($define =~ /^EXD_/) {
return('id');
} else {
return('other');
}
}
#
# Process a C header file, looking for #defines of interest. Candidates are
# saved in the $defines arrayref. Note nested includes are not processed.
#
sub process_file
{
my ($file, $filelist, $pattern, $typefn, $defines) = @_;
my $fh;
if ($_ = (grep(m{/$file$}, @$filelist))[0]) {
open($fh, '<', $_) || die("Can't open $_: $!\n");
} else {
die("Can't find $file\n");
}
my $line;
while (defined($line = <$fh>)) {
if ($line =~ /#define\s+\b($pattern)\b/) {
$defines->{$1} = &$typefn($1);
}
}
close($fh);
}
#
# Main routine.
#
# Check arguments and open the output file.
die("Usage is extract_defines <module> <output file> <input files...>\n")
unless (@ARGV >= 2);
my ($module, $outfile, @filelist) = @ARGV;
my $mm;
if (! defined($mm = $ModMap{$module})) {
die("Don't know how to handle module $module\n")
}
my $out;
if (! open($out, ">$outfile")) {
die("Can't open $outfile: $!\n");
}
# Perform the appropriate set of actions from ModMap for the specified module.
my $defines = {};
my $tfn = \&default_typefn;
my $i = 0;
while ($i < @$mm) {
my $act = $$mm[$i++];
my $parm = $$mm[$i++];
if ($act eq 'typefn') {
$tfn = $parm;
} elsif ($act eq 'declare') {
foreach my $d (@$parm) {
$defines->{$d} = &$tfn($d);
}
} elsif ($act eq 'scan') {
process_file($parm->[0], \@filelist, $parm->[1], $tfn,
$defines);
} else {
die("Illegal action $act\n");
}
}
# Print the structure definition.
print $out ("static constval_t constants[] = {\n");
foreach my $def (sort(keys(%$defines))) {
my $type = $defines->{$def};
my $len = length($def);
my $t = "\t" . "\t" x (3 - int(($len + 3) / 8));
print $out ("\t\"$def\",$t$len,\t$type,\n\t (unsigned int) $def,\n");
}
print $out ("\tNULL,\t\t\t\t0,\tother,\n\t 0,\n};\n");
close($out);
exit(0);