1# 2# Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3# Use is subject to license terms. 4# 5# CDDL HEADER START 6# 7# The contents of this file are subject to the terms of the 8# Common Development and Distribution License, Version 1.0 only 9# (the "License"). You may not use this file except in compliance 10# with the License. 11# 12# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 13# or http://www.opensolaris.org/os/licensing. 14# See the License for the specific language governing permissions 15# and limitations under the License. 16# 17# When distributing Covered Code, include this CDDL HEADER in each 18# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 19# If applicable, add the following below this CDDL HEADER, with the 20# fields enclosed by brackets "[]" replaced with your own identifying 21# information: Portions Copyright [yyyy] [name of copyright owner] 22# 23# CDDL HEADER END 24# 25#ident "%Z%%M% %I% %E% SMI" 26# 27# This script scans the exacct header files and extracts the names of any 28# #defines that are to be exported by the Exacct modules. All such #defines 29# are written out as an array of structs to a file which is subsequently 30# included into the module. Parameters to this script are the name of the 31# module to generate for, and the output file to use. 32# 33 34use warnings; 35use strict; 36 37# Forward declarations 38sub default_typefn; 39sub catalog_typefn; 40 41# 42# Map of module names to files and lists + patterns of macros to declare. 43# Each entry in the hash is keyed by the module name, and the value of each 44# entry is a list of actions, where each action is a (keyword, param) pair. 45# The valid actions are: 46# typefn => <fn_ptr> 47# fn_ptr is a function which when given a constant name, 48# returns the type - see default_typefn and catalog_typefn. 49# declare => [ <constant>, ... ] 50# Add the passed list of constants. 51# scan => [ <file> <regular expression> ] 52# Scan the specified file in /usr/include 53# for #defines that match the passed RE. 54# 55our %ModMap = ( 56 Exacct => [ 57 typefn => \&default_typefn, 58 declare => [ qw(P_PID P_TASKID P_PROJID) ], 59 scan => [ 'sys/exacct.h' => 60 qr/(?:EW|EP|EXR)_\w+/ ], 61 ], 62 Catalog => [ 63 typefn => \&catalog_typefn, 64 scan => [ 'sys/exacct_catalog.h' => 65 qr/EX[TCD]_\w+/ ], 66 ], 67 File => [ 68 typefn => \&default_typefn, 69 # From exacct.h. 70 declare => [ qw(EO_HEAD EO_TAIL EO_NO_VALID_HDR 71 EO_POSN_MSK EO_VALIDATE_MSK) ], 72 ], 73 Object => [ 74 typefn => \&default_typefn, 75 # From sys/exacct.h. 76 declare => [ qw(EO_ERROR EO_NONE EO_ITEM EO_GROUP) ], 77 ], 78); 79 80# 81# Constants may have a 'type' associated, currently only used by ::Catalog 82# (see below). For all other cases the type is 'other'. 83# 84sub default_typefn 85{ 86 return('other'); 87} 88 89# 90# ::Catalog uses the 'type' field to determine whether a given constant is a 91# type, a catalog or a data id. This function works out what type of constant 92# has been passed and returns the appropriate type. 93# 94sub catalog_typefn 95{ 96 my ($define) = @_; 97 if ($define =~ /_MASK$/) { 98 return('other'); 99 } elsif ($define =~ /^EXT_/) { 100 return('type'); 101 } elsif ($define =~ /^EXC_/) { 102 return('catlg'); 103 } elsif ($define =~ /^EXD_/) { 104 return('id'); 105 } else { 106 return('other'); 107 } 108} 109 110# 111# Process a C header file, looking for #defines of interest. Candidates are 112# saved in the $defines arrayref. Note nested includes are not processed. 113# 114sub process_file 115{ 116 my ($file, $filelist, $pattern, $typefn, $defines) = @_; 117 my $fh; 118 if ($_ = (grep(m{/$file$}, @$filelist))[0]) { 119 open($fh, '<', $_) || die("Can't open $_: $!\n"); 120 } else { 121 die("Can't find $file\n"); 122 } 123 my $line; 124 while (defined($line = <$fh>)) { 125 if ($line =~ /#define\s+\b($pattern)\b/) { 126 $defines->{$1} = &$typefn($1); 127 } 128 } 129 close($fh); 130} 131 132# 133# Main routine. 134# 135 136# Check arguments and open the output file. 137die("Usage is extract_defines <module> <output file> <input files...>\n") 138 unless (@ARGV >= 2); 139my ($module, $outfile, @filelist) = @ARGV; 140my $mm; 141if (! defined($mm = $ModMap{$module})) { 142 die("Don't know how to handle module $module\n") 143} 144my $out; 145if (! open($out, ">$outfile")) { 146 die("Can't open $outfile: $!\n"); 147} 148 149# Perform the appropriate set of actions from ModMap for the specified module. 150my $defines = {}; 151my $tfn = \&default_typefn; 152my $i = 0; 153while ($i < @$mm) { 154 my $act = $$mm[$i++]; 155 my $parm = $$mm[$i++]; 156 if ($act eq 'typefn') { 157 $tfn = $parm; 158 } elsif ($act eq 'declare') { 159 foreach my $d (@$parm) { 160 $defines->{$d} = &$tfn($d); 161 } 162 } elsif ($act eq 'scan') { 163 process_file($parm->[0], \@filelist, $parm->[1], $tfn, 164 $defines); 165 } else { 166 die("Illegal action $act\n"); 167 } 168} 169 170# Print the structure definition. 171print $out ("static constval_t constants[] = {\n"); 172foreach my $def (sort(keys(%$defines))) { 173 my $type = $defines->{$def}; 174 my $len = length($def); 175 my $t = "\t" . "\t" x (3 - int(($len + 3) / 8)); 176 print $out ("\t\"$def\",$t$len,\t$type,\n\t (unsigned int) $def,\n"); 177} 178print $out ("\tNULL,\t\t\t\t0,\tother,\n\t 0,\n};\n"); 179close($out); 180exit(0); 181