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