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