xref: /onnv-gate/usr/src/cmd/perl/contrib/Sun/Solaris/Exacct/extract_defines (revision 12388:1bc8d55b0dfd)
10Sstevel@tonic-gate#
2*12388SJohn.Sonnenschein@Sun.COM# Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
30Sstevel@tonic-gate#
4*12388SJohn.Sonnenschein@Sun.COM
50Sstevel@tonic-gate#
60Sstevel@tonic-gate# This script scans the exacct header files and extracts the names of any
70Sstevel@tonic-gate# #defines that are to be exported by the Exacct modules.  All such #defines
80Sstevel@tonic-gate# are written out as an array of structs to a file which is subsequently
90Sstevel@tonic-gate# included into the module.  Parameters to this script are the name of the
100Sstevel@tonic-gate# module to generate for, and the output file to use.
110Sstevel@tonic-gate#
120Sstevel@tonic-gate
130Sstevel@tonic-gateuse warnings;
140Sstevel@tonic-gateuse strict;
150Sstevel@tonic-gate
160Sstevel@tonic-gate# Forward declarations
170Sstevel@tonic-gatesub default_typefn;
180Sstevel@tonic-gatesub catalog_typefn;
190Sstevel@tonic-gate
200Sstevel@tonic-gate#
210Sstevel@tonic-gate# Map of module names to files and lists + patterns of macros to declare.
220Sstevel@tonic-gate# Each entry in the hash is keyed by the module name, and the value of each
230Sstevel@tonic-gate# entry is a list of actions, where each action is a (keyword, param) pair.
240Sstevel@tonic-gate# The valid actions are:
250Sstevel@tonic-gate#     typefn => <fn_ptr>
260Sstevel@tonic-gate#         fn_ptr is a function which when given a constant name,
270Sstevel@tonic-gate#         returns the type - see default_typefn and catalog_typefn.
280Sstevel@tonic-gate#     declare => [ <constant>, ... ]
290Sstevel@tonic-gate#         Add the passed list of constants.
300Sstevel@tonic-gate#     scan => [ <file> <regular expression> ]
310Sstevel@tonic-gate#         Scan the specified file in /usr/include
320Sstevel@tonic-gate#         for #defines that match the passed RE.
330Sstevel@tonic-gate#
340Sstevel@tonic-gateour %ModMap = (
350Sstevel@tonic-gate	Exacct => [
360Sstevel@tonic-gate		typefn	=> \&default_typefn,
370Sstevel@tonic-gate		declare	=> [ qw(P_PID P_TASKID P_PROJID) ],
380Sstevel@tonic-gate		scan 	=> [ 'sys/exacct.h' =>
390Sstevel@tonic-gate			     qr/(?:EW|EP|EXR)_\w+/ ],
400Sstevel@tonic-gate	],
410Sstevel@tonic-gate	Catalog => [
420Sstevel@tonic-gate		typefn	=> \&catalog_typefn,
430Sstevel@tonic-gate		scan 	=> [ 'sys/exacct_catalog.h' =>
440Sstevel@tonic-gate			     qr/EX[TCD]_\w+/ ],
450Sstevel@tonic-gate	],
460Sstevel@tonic-gate	File => [
470Sstevel@tonic-gate		typefn	=> \&default_typefn,
480Sstevel@tonic-gate		# From exacct.h.
490Sstevel@tonic-gate		declare	=> [ qw(EO_HEAD EO_TAIL EO_NO_VALID_HDR
500Sstevel@tonic-gate			     EO_POSN_MSK EO_VALIDATE_MSK) ],
510Sstevel@tonic-gate	],
520Sstevel@tonic-gate	Object => [
530Sstevel@tonic-gate		typefn	=> \&default_typefn,
540Sstevel@tonic-gate		# From sys/exacct.h.
550Sstevel@tonic-gate		declare	=> [ qw(EO_ERROR EO_NONE EO_ITEM EO_GROUP) ],
560Sstevel@tonic-gate	],
570Sstevel@tonic-gate);
580Sstevel@tonic-gate
590Sstevel@tonic-gate#
600Sstevel@tonic-gate# Constants may have a 'type' associated, currently only used by ::Catalog
610Sstevel@tonic-gate# (see below).  For all other cases the type is 'other'.
620Sstevel@tonic-gate#
630Sstevel@tonic-gatesub default_typefn
640Sstevel@tonic-gate{
650Sstevel@tonic-gate	return('other');
660Sstevel@tonic-gate}
670Sstevel@tonic-gate
680Sstevel@tonic-gate#
690Sstevel@tonic-gate# ::Catalog uses the 'type' field to determine whether a given constant is a
700Sstevel@tonic-gate# type, a catalog or a data id.  This function works out what type of constant
710Sstevel@tonic-gate# has been passed and returns the appropriate type.
720Sstevel@tonic-gate#
730Sstevel@tonic-gatesub catalog_typefn
740Sstevel@tonic-gate{
750Sstevel@tonic-gate	my ($define) = @_;
760Sstevel@tonic-gate	if ($define =~ /_MASK$/) {
770Sstevel@tonic-gate		return('other');
780Sstevel@tonic-gate	} elsif ($define =~ /^EXT_/) {
790Sstevel@tonic-gate		return('type');
800Sstevel@tonic-gate	} elsif ($define =~ /^EXC_/) {
810Sstevel@tonic-gate		return('catlg');
820Sstevel@tonic-gate	} elsif ($define =~ /^EXD_/) {
830Sstevel@tonic-gate		return('id');
840Sstevel@tonic-gate	} else {
850Sstevel@tonic-gate		return('other');
860Sstevel@tonic-gate	}
870Sstevel@tonic-gate}
880Sstevel@tonic-gate
890Sstevel@tonic-gate#
900Sstevel@tonic-gate# Process a C header file, looking for #defines of interest.  Candidates are
910Sstevel@tonic-gate# saved in the $defines arrayref.  Note nested includes are not processed.
920Sstevel@tonic-gate#
930Sstevel@tonic-gatesub process_file
940Sstevel@tonic-gate{
950Sstevel@tonic-gate	my ($file, $filelist, $pattern, $typefn, $defines) = @_;
960Sstevel@tonic-gate	my $fh;
970Sstevel@tonic-gate	if ($_ = (grep(m{/$file$}, @$filelist))[0]) {
980Sstevel@tonic-gate		open($fh, '<', $_) || die("Can't open $_: $!\n");
990Sstevel@tonic-gate	} else {
1000Sstevel@tonic-gate		die("Can't find $file\n");
1010Sstevel@tonic-gate	}
1020Sstevel@tonic-gate	my $line;
1030Sstevel@tonic-gate	while (defined($line = <$fh>)) {
1040Sstevel@tonic-gate		if ($line =~ /#define\s+\b($pattern)\b/) {
1050Sstevel@tonic-gate			$defines->{$1} = &$typefn($1);
1060Sstevel@tonic-gate		}
1070Sstevel@tonic-gate	}
1080Sstevel@tonic-gate	close($fh);
1090Sstevel@tonic-gate}
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate#
1120Sstevel@tonic-gate# Main routine.
1130Sstevel@tonic-gate#
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate# Check arguments and open the output file.
1160Sstevel@tonic-gatedie("Usage is extract_defines <module> <output file> <input files...>\n")
1170Sstevel@tonic-gate    unless (@ARGV >= 2);
1180Sstevel@tonic-gatemy ($module, $outfile, @filelist) = @ARGV;
1190Sstevel@tonic-gatemy $mm;
1200Sstevel@tonic-gateif (! defined($mm = $ModMap{$module})) {
1210Sstevel@tonic-gate	die("Don't know how to handle module $module\n")
1220Sstevel@tonic-gate}
1230Sstevel@tonic-gatemy $out;
1240Sstevel@tonic-gateif (! open($out, ">$outfile")) {
1250Sstevel@tonic-gate	die("Can't open $outfile: $!\n");
1260Sstevel@tonic-gate}
1270Sstevel@tonic-gate
1280Sstevel@tonic-gate# Perform the appropriate set of actions from ModMap for the specified module.
1290Sstevel@tonic-gatemy $defines = {};
1300Sstevel@tonic-gatemy $tfn = \&default_typefn;
1310Sstevel@tonic-gatemy $i = 0;
1320Sstevel@tonic-gatewhile ($i < @$mm) {
1330Sstevel@tonic-gate	my $act = $$mm[$i++];
1340Sstevel@tonic-gate	my $parm = $$mm[$i++];
1350Sstevel@tonic-gate	if ($act eq 'typefn') {
1360Sstevel@tonic-gate		$tfn = $parm;
1370Sstevel@tonic-gate	} elsif ($act eq 'declare') {
1380Sstevel@tonic-gate		foreach my $d (@$parm) {
1390Sstevel@tonic-gate			$defines->{$d} = &$tfn($d);
1400Sstevel@tonic-gate		}
1410Sstevel@tonic-gate	} elsif ($act eq 'scan') {
1420Sstevel@tonic-gate		process_file($parm->[0], \@filelist, $parm->[1], $tfn,
1430Sstevel@tonic-gate		    $defines);
1440Sstevel@tonic-gate	} else {
1450Sstevel@tonic-gate		die("Illegal action $act\n");
1460Sstevel@tonic-gate	}
1470Sstevel@tonic-gate}
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate# Print the structure definition.
1500Sstevel@tonic-gateprint $out ("static constval_t constants[] = {\n");
1510Sstevel@tonic-gateforeach my $def (sort(keys(%$defines))) {
1520Sstevel@tonic-gate	my $type = $defines->{$def};
1530Sstevel@tonic-gate	my $len = length($def);
1540Sstevel@tonic-gate	my $t = "\t" . "\t" x (3 - int(($len + 3) / 8));
1550Sstevel@tonic-gate	print $out ("\t\"$def\",$t$len,\t$type,\n\t    (unsigned int) $def,\n");
1560Sstevel@tonic-gate}
1570Sstevel@tonic-gateprint $out ("\tNULL,\t\t\t\t0,\tother,\n\t    0,\n};\n");
1580Sstevel@tonic-gateclose($out);
1590Sstevel@tonic-gateexit(0);
160