xref: /titanic_53/usr/src/lib/libbsm/auditxml (revision 3cccda98b87857542deb064ace0cec9c785dbeb9)
1c0c79a3fStz204579#!/usr/perl5/bin/perl -w
2c0c79a3fStz204579#
3c0c79a3fStz204579# CDDL HEADER START
4c0c79a3fStz204579#
5c0c79a3fStz204579# The contents of this file are subject to the terms of the
6c0c79a3fStz204579# Common Development and Distribution License (the "License").
7c0c79a3fStz204579# You may not use this file except in compliance with the License.
8c0c79a3fStz204579#
9c0c79a3fStz204579# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10c0c79a3fStz204579# or http://www.opensolaris.org/os/licensing.
11c0c79a3fStz204579# See the License for the specific language governing permissions
12c0c79a3fStz204579# and limitations under the License.
13c0c79a3fStz204579#
14c0c79a3fStz204579# When distributing Covered Code, include this CDDL HEADER in each
15c0c79a3fStz204579# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16c0c79a3fStz204579# If applicable, add the following below this CDDL HEADER, with the
17c0c79a3fStz204579# fields enclosed by brackets "[]" replaced with your own identifying
18c0c79a3fStz204579# information: Portions Copyright [yyyy] [name of copyright owner]
19c0c79a3fStz204579#
20c0c79a3fStz204579# CDDL HEADER END
21c0c79a3fStz204579#
22c0c79a3fStz204579#
235b7f77adStw21770# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24c0c79a3fStz204579# Use is subject to license terms.
25c0c79a3fStz204579#
26c0c79a3fStz204579#
27c0c79a3fStz204579
28c0c79a3fStz204579# auditxml [-d] <xml input file>
29c0c79a3fStz204579
30c0c79a3fStz204579# auditxml takes the audit record description (.xml file) and
31c0c79a3fStz204579# generates the files needed for the C audit api.
32c0c79a3fStz204579
33c0c79a3fStz204579use auditxml;
34c0c79a3fStz204579use Getopt::Std;
35c0c79a3fStz204579use vars qw($opt_d);
36c0c79a3fStz204579use strict;
37c0c79a3fStz204579
38c0c79a3fStz204579
39c0c79a3fStz204579our $debug = 0; # normal use is to set via the file being parsed.
40c0c79a3fStz204579               # <debug set="on"/> or <debug set="off"/> or <debug/>
41c0c79a3fStz204579               # if the set attribute is omitted, debug state is toggled
42c0c79a3fStz204579               # Override with appDebug, but toggle won't do what you
43c0c79a3fStz204579               # want.
44c0c79a3fStz204579my $appDebug = 0; # used after return from "new auditxml";
45c0c79a3fStz204579
46c0c79a3fStz204579my $genNotice = "
47c0c79a3fStz204579DO NOT EDIT. This file is auto generated by the Solaris Audit
48c0c79a3fStz204579system from adt.xml.
49c0c79a3fStz204579
50c0c79a3fStz204579See http://opensolaris.org/os/project/audit/
51c0c79a3fStz204579";
52c0c79a3fStz204579
53c0c79a3fStz204579# trim leading/trailing newlines
54c0c79a3fStz204579$genNotice =~ s/^\n//s;
55c0c79a3fStz204579$genNotice =~ s/\n$//s;
56c0c79a3fStz204579my $prog = $0; $prog =~ s|.*/||g;
57c0c79a3fStz204579my $usage = "usage: $prog [-d] file.xml\n";
58c0c79a3fStz204579
59c0c79a3fStz204579getopts('d');
60c0c79a3fStz204579
61c0c79a3fStz204579$appDebug = $opt_d;
62c0c79a3fStz204579
63c0c79a3fStz204579my $uniLabel = "adr";
64c0c79a3fStz204579my $xlateUniLabelInc = 0;
65c0c79a3fStz204579
66c0c79a3fStz204579die $usage if ($#ARGV < 0);
67c0c79a3fStz204579
68c0c79a3fStz204579# where everything comes from and where it goes:
69c0c79a3fStz204579
70c0c79a3fStz204579my $bsmBuildPath = "./common";
71c0c79a3fStz204579my $xlateFile = "$bsmBuildPath/adt_xlate.c";
72c0c79a3fStz204579my $headerFile = "$bsmBuildPath/adt_event_N.h";
73c0c79a3fStz204579
74c0c79a3fStz204579my $doc = new auditxml ($ARGV[0]);  # input XML file
75c0c79a3fStz204579
76c0c79a3fStz204579$debug = $appDebug;
77c0c79a3fStz204579
78c0c79a3fStz204579my %xlateEventTable = ();
79c0c79a3fStz204579my @xlateTypeList = ();
80c0c79a3fStz204579my %xlateTypeList = ();
81c0c79a3fStz204579my %eventAPI = ();
82c0c79a3fStz204579my %eventExtra = ();
83c0c79a3fStz204579my %headers = ();
84c0c79a3fStz204579my %externalIdNo = ();
85c0c79a3fStz204579my @outputState = ();
86c0c79a3fStz204579my %nameTranslation = ();
87c0c79a3fStz204579my @xlateDefaults = ();
88c0c79a3fStz204579my %xlateDefault = ();
89c0c79a3fStz204579my %msg_list = ();
90c0c79a3fStz204579
91c0c79a3fStz204579my $event;
92c0c79a3fStz204579while ($event = $doc->getNextEvent()) {
93c0c79a3fStz204579    my $eventId = $event->getId();
94c0c79a3fStz204579    my $eventHeader = $event->getHeader();
95c0c79a3fStz204579    my $idNo = $event->getIdNo();
96c0c79a3fStz204579    $externalIdNo{$eventId} = $idNo;
97c0c79a3fStz204579    addHeader($eventHeader) if defined ($eventHeader);
98c0c79a3fStz204579    my $super;
99c0c79a3fStz204579    my $omit = $event->getOmit();
100c0c79a3fStz204579    my $eventType = '';
101c0c79a3fStz204579    if ($super = $event->getSuperClass()) {
102c0c79a3fStz204579	$event = $super;
103c0c79a3fStz204579	$eventType = 'instance';
104c0c79a3fStz204579    } else {
105c0c79a3fStz204579	$eventType = $event->getType();
106c0c79a3fStz204579    }
107c0c79a3fStz204579
108c0c79a3fStz204579    # header file for API use
109c0c79a3fStz204579    generateAPIFile($event, $eventId, $eventType, $eventHeader, $idNo)
110c0c79a3fStz204579        unless $omit eq 'always';
111c0c79a3fStz204579
112c0c79a3fStz204579    # c file table for translation
113c0c79a3fStz204579    generateTableC($event, $eventId, $eventType, $eventHeader, $omit);
114c0c79a3fStz204579}
115c0c79a3fStz204579
116c0c79a3fStz204579my $textList;
117c0c79a3fStz204579while ($textList = $doc->getNextMsgId()) {
118c0c79a3fStz204579    generateMsgLists($textList);  # enum -> text mappings
119c0c79a3fStz204579}
120c0c79a3fStz204579
121c0c79a3fStz204579printTableC($xlateFile);
122c0c79a3fStz204579printAPIFile($headerFile, $doc);
123c0c79a3fStz204579
124c0c79a3fStz204579exit 0;
125c0c79a3fStz204579
126c0c79a3fStz204579
127c0c79a3fStz204579sub printTableC {
128c0c79a3fStz204579    my $file = shift;
129c0c79a3fStz204579
130c0c79a3fStz204579    unless (open(Cfile, ">$file")) {
131c0c79a3fStz204579	print STDERR "can't open output file ($file): $!\n";
132c0c79a3fStz204579	return;
133c0c79a3fStz204579    }
134c0c79a3fStz204579
135c0c79a3fStz204579    my $notice = $genNotice;
136c0c79a3fStz204579    $notice =~ s/\n/\n * /gs;
137c0c79a3fStz204579    $notice =~ s/\s+\n/\n/gs;
138c0c79a3fStz204579    print Cfile <<EOF;
139c0c79a3fStz204579/*
140c0c79a3fStz204579 * $notice
141c0c79a3fStz204579 */
142c0c79a3fStz204579
143c0c79a3fStz204579#include <bsm/libbsm.h>
144c0c79a3fStz204579#include <adt_xlate.h>
145c0c79a3fStz204579#include <libintl.h>
146c0c79a3fStz204579
147c0c79a3fStz204579EOF
148c0c79a3fStz204579    print Cfile "#ifndef _PRAUDIT\n";
149c0c79a3fStz204579    print Cfile "/* Internal data type definitions */\n\n";
150c0c79a3fStz204579    my $extDef;
151c0c79a3fStz204579    foreach $extDef (@xlateTypeList) {
152c0c79a3fStz204579      print Cfile "static $extDef\n";
153c0c79a3fStz204579    }
154c0c79a3fStz204579    @xlateTypeList = ();
155c0c79a3fStz204579
156c0c79a3fStz204579    print Cfile "\n/* External event structure to internal event structure */\n\n";
157c0c79a3fStz204579
158c0c79a3fStz204579    my @pointers = ();
159c0c79a3fStz204579
160c0c79a3fStz204579    foreach my $eventId (sort keys %xlateEventTable) {
161c0c79a3fStz204579	if ($xlateEventTable{$eventId}) {
162c0c79a3fStz204579	    my ($ref1, $eventType, $firstToken, $eventHeader) =
163c0c79a3fStz204579	      @{$xlateEventTable{$eventId}};
164c0c79a3fStz204579	    my @entries = @$ref1;
165c0c79a3fStz204579	    my $entry;
166c0c79a3fStz204579	    my $entries = $#entries;
167c0c79a3fStz204579	    my $count = $entries + 1;
168c0c79a3fStz204579	    my $externalName = $nameTranslation{$eventId};
169c0c79a3fStz204579	    my $externalRoot = $externalName;
170c0c79a3fStz204579	    $externalRoot =~ s/AUE_//;
171c0c79a3fStz204579	    my $structName = "XX_$externalRoot";
172c0c79a3fStz204579	    my $root = $eventId;
173c0c79a3fStz204579	    $root =~ s/AUE_//;
174c0c79a3fStz204579	    my $externalId = $eventId;
175c0c79a3fStz204579	    $externalId =~ s/AUE_/ADT_/;
176c0c79a3fStz204579
177c0c79a3fStz204579	    unless ($eventType eq 'generic') {
178c0c79a3fStz204579		print Cfile "static struct entry $structName\[$count\] = {\n";
179c0c79a3fStz204579		foreach $entry (@entries) {
180c0c79a3fStz204579		    if ($entries--) {
181c0c79a3fStz204579			$entry =~ s/EOL/,/;
182c0c79a3fStz204579		    }
183c0c79a3fStz204579		    else {
184c0c79a3fStz204579			$entry =~ s/EOL//;
185c0c79a3fStz204579		    }
186c0c79a3fStz204579		    $entry =~ s/selfReference/$structName/;
187c0c79a3fStz204579		    print Cfile "\t$entry\n";
188c0c79a3fStz204579		}
189c0c79a3fStz204579		print Cfile "};\n";
190c0c79a3fStz204579
191c0c79a3fStz204579		print Cfile "static struct translation X_$externalRoot = {\n";
192c0c79a3fStz204579		push (@pointers, "X_$externalRoot");
193c0c79a3fStz204579
194c0c79a3fStz204579		print Cfile "\t0,\n";   # tx_offsetsCalculated = 0
195c0c79a3fStz204579		print Cfile "\t$externalId,\n";
196c0c79a3fStz204579		print Cfile "\t$externalName,\n";
197c0c79a3fStz204579
198c0c79a3fStz204579		print Cfile "\t$count,\n";
199c0c79a3fStz204579		print Cfile "\t&XX_$externalRoot\[$firstToken\],\n";
200c0c79a3fStz204579		print Cfile "\t&XX_$externalRoot\[0\]\n};\n";
201c0c79a3fStz204579	    }
202c0c79a3fStz204579	} else {
203c0c79a3fStz204579	    print STDERR "expected entry for $eventId but none found\n";
204c0c79a3fStz204579	}
205c0c79a3fStz204579    }
206c0c79a3fStz204579
207c0c79a3fStz204579    my $count = $#pointers + 2;
208c0c79a3fStz204579    print Cfile "struct translation *xlate_table[$count] = {\n";
209c0c79a3fStz204579
210c0c79a3fStz204579    my $firstEvent = 1;
211c0c79a3fStz204579    foreach my $eventId (@pointers) {
212c0c79a3fStz204579	if ($firstEvent) {
213c0c79a3fStz204579	    $firstEvent = 0;
214c0c79a3fStz204579	}
215c0c79a3fStz204579	else {
216c0c79a3fStz204579	    print Cfile ",\n";
217c0c79a3fStz204579	}
218c0c79a3fStz204579	print Cfile "\t&$eventId";
219c0c79a3fStz204579    }
220c0c79a3fStz204579    print Cfile ",\n\tNULL\n};\n";
221c0c79a3fStz204579
222c0c79a3fStz204579    # generate the adt_preload() function
223c0c79a3fStz204579
224c0c79a3fStz204579    print Cfile <<EOF;
225c0c79a3fStz204579
226c0c79a3fStz204579void
227c0c79a3fStz204579adt_preload(au_event_t event_id, adt_event_data_t *event_data)
228c0c79a3fStz204579{
229c0c79a3fStz204579	switch (event_id) {
230c0c79a3fStz204579EOF
231c0c79a3fStz204579
232c0c79a3fStz204579        foreach my $id (@xlateDefaults) {
233c0c79a3fStz204579		my $adtID = $id;
234c0c79a3fStz204579		$adtID =~ s/AUE/ADT/;
235c0c79a3fStz204579
236c0c79a3fStz204579		print Cfile <<EOF;
237c0c79a3fStz204579	case $adtID:
238c0c79a3fStz204579EOF
239c0c79a3fStz204579		my @preloads = @{$xlateDefault{$id}};
240c0c79a3fStz204579		while (@preloads) {
241c0c79a3fStz204579			my $fieldName = shift @preloads;
242c0c79a3fStz204579			my $default = shift @preloads;
243c0c79a3fStz204579			my $lcid = lc $id;
244c0c79a3fStz204579			$lcid =~ s/aue_/adt_/;
245c0c79a3fStz204579
246c0c79a3fStz204579			print Cfile <<EOF;
247c0c79a3fStz204579		event_data->$lcid.$fieldName = $default;
248c0c79a3fStz204579EOF
249c0c79a3fStz204579		}
250c0c79a3fStz204579
251c0c79a3fStz204579		print Cfile <<EOF;
252c0c79a3fStz204579		break;
253c0c79a3fStz204579EOF
254c0c79a3fStz204579	}
255c0c79a3fStz204579
256c0c79a3fStz204579    print Cfile <<EOF;
257c0c79a3fStz204579	default:
258c0c79a3fStz204579		break;
259c0c79a3fStz204579	}
260c0c79a3fStz204579}
261c0c79a3fStz204579#endif
262c0c79a3fStz204579
263c0c79a3fStz204579/* message lists */
264c0c79a3fStz204579
265c0c79a3fStz204579EOF
266c0c79a3fStz204579    my $listName;
267c0c79a3fStz204579    my @listName;
268c0c79a3fStz204579    foreach $listName (sort keys %msg_list) {
269c0c79a3fStz204579        my ($listRef, $headref) = @{$msg_list{$listName}};
270c0c79a3fStz204579	my ($header, $start, $public, $deprecated) = @$headref;
271c0c79a3fStz204579
272c0c79a3fStz204579	my @listValue =  @$listRef;
273c0c79a3fStz204579	my $listValue;
274c0c79a3fStz204579	my $listLength = $#listValue + 1;
275c0c79a3fStz204579
276c0c79a3fStz204579	$listName = 'NULL' if ($#listValue < 0);
277c0c79a3fStz204579
278c0c79a3fStz204579        push (@listName, [$listName, $listLength - 1, $start, $public]);
279c0c79a3fStz204579
280c0c79a3fStz204579	next if ($#listValue < 0);
281c0c79a3fStz204579
282c0c79a3fStz204579	print Cfile "/* Deprecated message list */\n" if ($deprecated);
283c0c79a3fStz204579	print Cfile "static char *msg_$listName\[$listLength] = {\n";
284c0c79a3fStz204579
285c0c79a3fStz204579	my $ffirst = 1;
286c0c79a3fStz204579	foreach $listValue (@listValue) {
287c0c79a3fStz204579	    print Cfile ",\n" unless $ffirst;
288c0c79a3fStz204579	    $ffirst = 0;
289c0c79a3fStz204579	    my ($id, $text) = split(/\s*::\s*/, $listValue);
290c0c79a3fStz204579	    if ($text) {
291c0c79a3fStz204579	        print Cfile "\t\"$text\"";
292c0c79a3fStz204579	    }
293c0c79a3fStz204579	    else {
294c0c79a3fStz204579	        print Cfile "\tNULL";
295c0c79a3fStz204579	    }
296c0c79a3fStz204579	}
297c0c79a3fStz204579	print Cfile "\n};\n";
298c0c79a3fStz204579    }
299c0c79a3fStz204579    print Cfile "\nstruct msg_text adt_msg_text[", $#listName + 1,
300c0c79a3fStz204579                "] = {\n";
301c0c79a3fStz204579    my $ffirst = 1;
302c0c79a3fStz204579    foreach $listName (@listName) {
303c0c79a3fStz204579        my ($name, $max, $start) = @$listName;
304c0c79a3fStz204579	$start = -$start if $start;
305c0c79a3fStz204579        print Cfile ",\n" unless $ffirst;
306c0c79a3fStz204579	$ffirst = 0;
307c0c79a3fStz204579	$name = "msg_$name" if ($name ne 'NULL');
308c0c79a3fStz204579        print Cfile "\t{0, $max, $name, $start}";
309c0c79a3fStz204579    }
310c0c79a3fStz204579    print Cfile "\n};\n";
311c0c79a3fStz204579
312c0c79a3fStz204579    close Cfile;
313c0c79a3fStz204579}
314c0c79a3fStz204579
315c0c79a3fStz204579sub printAPIFile {
316c0c79a3fStz204579    my $file = shift;
317c0c79a3fStz204579    my $xmlDoc = shift;
318c0c79a3fStz204579
319c0c79a3fStz204579    my @Hfile;
320c0c79a3fStz204579    @Hfile = openHeaderFiles($file);
321c0c79a3fStz204579
322c0c79a3fStz204579    my $notice = $genNotice;
323c0c79a3fStz204579    $notice =~ s/\n/\n * /gs;
324c0c79a3fStz204579    $notice =~ s/\s+\n/\n/gs;
325c0c79a3fStz204579
326c0c79a3fStz204579    foreach my $header (keys %headers) {
327c0c79a3fStz204579    	next unless $Hfile[$header];
328c0c79a3fStz204579	*Hfile = $Hfile[$header];
329c0c79a3fStz204579	my $include = "adt.h";
330c0c79a3fStz204579	my $adt_event_n = "_ADT_EVENT_H";
331c0c79a3fStz204579	if ($header > 0) {
332c0c79a3fStz204579	    $include = "adt_event.h";
333c0c79a3fStz204579	    $adt_event_n = "_ADT_EVENT_".$header."_H";
334c0c79a3fStz204579	}
335c0c79a3fStz204579	print Hfile <<EOF;
336c0c79a3fStz204579/*
337c0c79a3fStz204579 * $notice
338c0c79a3fStz204579 */
339c0c79a3fStz204579
340c0c79a3fStz204579#ifndef $adt_event_n
341c0c79a3fStz204579#define	$adt_event_n
342c0c79a3fStz204579
343c0c79a3fStz204579#include <bsm/$include>
344c0c79a3fStz204579
345c0c79a3fStz204579#ifdef	__cplusplus
346c0c79a3fStz204579extern "C" {
347c0c79a3fStz204579#endif
348c0c79a3fStz204579
349c0c79a3fStz204579/*
350c0c79a3fStz204579 * adt_put_event() status values.  Positive values are for kernel-generated
351c0c79a3fStz204579 * failure, -1 for user-space.  For ADT_SUCCESS, the adt_put_event() return_val
352c0c79a3fStz204579 * is not used; the convention is to set it to ADT_SUCCESS.
353c0c79a3fStz204579 */
354c0c79a3fStz204579#define	ADT_SUCCESS	0
355c0c79a3fStz204579#define	ADT_FAILURE	-1
356c0c79a3fStz204579
357c0c79a3fStz204579EOF
358c0c79a3fStz204579    }
359c0c79a3fStz204579
360c0c79a3fStz204579    foreach my $listName (sort keys %msg_list) {
361c0c79a3fStz204579	my $shortName = uc $listName;
362c0c79a3fStz204579	$shortName =~ s/_TEXT//;
363c0c79a3fStz204579
364c0c79a3fStz204579        my ($listRef, $headref) = @{$msg_list{$listName}};
365c0c79a3fStz204579	my ($header, $start, $public, $deprecated) = @$headref;
366c0c79a3fStz204579	next unless $Hfile[$header];
367c0c79a3fStz204579	*Hfile = $Hfile[$header];
368c0c79a3fStz204579
369c0c79a3fStz204579	print Hfile "/* Deprecated message list */\n" if $deprecated;
370c0c79a3fStz204579	print Hfile "#define\tADT_$shortName\t$start\n" if $start;
371c0c79a3fStz204579
372c0c79a3fStz204579	my @listValue =  @$listRef;
373c0c79a3fStz204579	next unless ($#listValue >= 0);
374c0c79a3fStz204579	print Hfile "enum\tadt_$listName", " {\n";
375c0c79a3fStz204579
376c0c79a3fStz204579	my $listValue;
377c0c79a3fStz204579	my $i = 0;
378c0c79a3fStz204579	my $j = $#listValue;
379c0c79a3fStz204579	my $comma = ',';
380c0c79a3fStz204579	foreach $listValue (@listValue) {
381c0c79a3fStz204579	    my ($id, $text) = split(/\s*::\s*/, $listValue);
382c0c79a3fStz204579	    $comma = '' if $i++ == $j;
383c0c79a3fStz204579	    if ($start) {
384c0c79a3fStz204579		$start = " = $start$comma";
385c0c79a3fStz204579	    } else {
386c0c79a3fStz204579	        $start = "$comma\t";
387c0c79a3fStz204579	    }
388c0c79a3fStz204579	    $text = "(no token will be generated)" unless $text;
3896a3b10dbStz204579	    my $line = "\tADT_$shortName"."_$id$start\t/* ";
3906a3b10dbStz204579	    # ensure whole line does not exceed 80 chars
3916a3b10dbStz204579	    my $eline = $line.$text;
3926a3b10dbStz204579	    #expand tabs
3936a3b10dbStz204579	    1 while $eline =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
3946a3b10dbStz204579	    if ((length($eline) > 77) && ($line =~ /\t\t/)) {
3956a3b10dbStz204579	    	# 77 = 80 - length(" */")
3966a3b10dbStz204579		# strip off double tab so that comment can be longer
3976a3b10dbStz204579		$line =~ s/\t\t/\t/;
3986a3b10dbStz204579		# shorten eline; don't mind where the spaces are removed, it is
3996a3b10dbStz204579		# only $eline length which matters
4006a3b10dbStz204579		$eline =~ s/ {8}//;
4016a3b10dbStz204579	    }
4026a3b10dbStz204579	    if (length($eline) > 77) { # 80 - length(" */")
4036a3b10dbStz204579	    	# here we use negative length in substr to leave off from the
4046a3b10dbStz204579		# right side; 74 = 77 - length("...")
4056a3b10dbStz204579	    	$line .= substr($text, 0, 74 - length($eline));
4066a3b10dbStz204579		# strip off part of last word (already cut)
4076a3b10dbStz204579		$line =~ s/\s(\S+)$/ /;
4086a3b10dbStz204579		$line .= "...";
4096a3b10dbStz204579	    } else {
4106a3b10dbStz204579	    	$line .= $text;
4116a3b10dbStz204579	    }
4126a3b10dbStz204579	    print Hfile "$line */\n";
413c0c79a3fStz204579	    $start = '';
414c0c79a3fStz204579	}
415c0c79a3fStz204579	print Hfile "};\n";
416c0c79a3fStz204579    }
417c0c79a3fStz204579
418c0c79a3fStz204579    # generate defines for ADT_* external event names
419c0c79a3fStz204579
420c0c79a3fStz204579    foreach my $eventId (sort keys %eventAPI) {
421c0c79a3fStz204579        my ($header, $idNo) = @{$eventExtra{$eventId}};
422c0c79a3fStz204579	unless (defined ($header)) {
423c0c79a3fStz204579	    print STDERR "missing header selection for $eventId\n";
424c0c79a3fStz204579	    next;
425c0c79a3fStz204579	}
426c0c79a3fStz204579	*Hfile = $Hfile[$header];
427c0c79a3fStz204579	next unless $Hfile[$header];
428c0c79a3fStz204579
429c0c79a3fStz204579	my $l = length($eventId) + 8; # label plus preceding #define\t
430c0c79a3fStz204579	$l = 5 - int(($l + 8)/8);
431c0c79a3fStz204579	$l = 1 if $l < 1;
432c0c79a3fStz204579	my $tab = "\t" x $l;
433c0c79a3fStz204579
434c0c79a3fStz204579        print STDERR "missing id number for $eventId\n" unless $idNo;
435c0c79a3fStz204579
436c0c79a3fStz204579	$eventId =~ s/AUE_/ADT_/;
437c0c79a3fStz204579	print Hfile "#define\t$eventId$tab$idNo\n";
438c0c79a3fStz204579    }
439c0c79a3fStz204579
440c0c79a3fStz204579
441c0c79a3fStz204579    # generate per-event structures
442c0c79a3fStz204579
443c0c79a3fStz204579    foreach my $eventId (sort keys %eventAPI) {
444c0c79a3fStz204579        my ($header, $idNo) = @{$eventExtra{$eventId}};
445c0c79a3fStz204579	my $dataId = $eventId;
446c0c79a3fStz204579	$dataId =~ s/^AUE_/adt_/;
447c0c79a3fStz204579	unless(defined ($header)) {
448c0c79a3fStz204579	    print STDERR "$eventId is missing the header assignment\n";
449c0c79a3fStz204579	    next;
450c0c79a3fStz204579	}
451c0c79a3fStz204579	*Hfile = $Hfile[$header];
452c0c79a3fStz204579	next unless $Hfile[$header];
453c0c79a3fStz204579
454c0c79a3fStz204579	my $externalId = $eventId;
455c0c79a3fStz204579	$externalId =~ s/AUE_/ADT_/;
456c0c79a3fStz204579
457c0c79a3fStz204579	print Hfile "\nstruct $dataId {\t/* $externalId */\n";
458c0c79a3fStz204579
459c0c79a3fStz204579	my @entries = @{$eventAPI{$eventId}};
460c0c79a3fStz204579	my $entry;
461c0c79a3fStz204579	if ($#entries < 0) {
462c0c79a3fStz204579	    print Hfile "\tint\tdummy;\t/* not used */\n";
463c0c79a3fStz204579	} else {
464c0c79a3fStz204579	    foreach $entry (@entries) {
465c0c79a3fStz204579		$entry =~ s/termid/adt_termid_t/;
466c0c79a3fStz204579		print Hfile "\t$entry\n";
467c0c79a3fStz204579	    }
468c0c79a3fStz204579	}
469c0c79a3fStz204579	print Hfile "};\n";
470c0c79a3fStz204579	$eventId =~ s/^AUE_/adt_/;
471c0c79a3fStz204579	print Hfile "typedef struct $dataId $eventId","_t;\n";
472c0c79a3fStz204579    }
473c0c79a3fStz204579
474c0c79a3fStz204579    foreach my $header (sort keys %headers) {
475c0c79a3fStz204579	$outputState[$header] = 0;
476c0c79a3fStz204579    }
477c0c79a3fStz204579
478c0c79a3fStz204579    foreach my $eventId (sort keys %eventAPI) {
479c0c79a3fStz204579        my ($header, $idNo) = @{$eventExtra{$eventId}};
480c0c79a3fStz204579	unless(defined ($header)) {
481c0c79a3fStz204579	    # don't print duplicate error message
482c0c79a3fStz204579	    next;
483c0c79a3fStz204579	}
484c0c79a3fStz204579	*Hfile = $Hfile[$header];
485c0c79a3fStz204579	next unless $Hfile[$header];
486c0c79a3fStz204579	if ($outputState[$header] == 0) {
487c0c79a3fStz204579	    $outputState[$header] = 1;
488c0c79a3fStz204579	    my $suffix = '';
489c0c79a3fStz204579	    $suffix = "_$header" if $header;
490c0c79a3fStz204579	    print Hfile "\nunion adt_event_data$suffix {\n";
491c0c79a3fStz204579	}
492c0c79a3fStz204579        my $elementName = $eventId;
493c0c79a3fStz204579	$elementName =~ s/^AUE_/adt_/;
494c0c79a3fStz204579	$eventId =~ s/^AUE_/adt_/;
495c0c79a3fStz204579	$elementName =~ s/_t$//;
496c0c79a3fStz204579
497c0c79a3fStz204579	print Hfile "\t\t$eventId","_t\t$elementName;\n";
498c0c79a3fStz204579    }
499c0c79a3fStz204579    foreach my $header (sort keys %headers) {
500c0c79a3fStz204579	if ($outputState[$header]) {
501c0c79a3fStz204579	    *Hfile = $Hfile[$header];
502c0c79a3fStz204579	    next unless $Hfile[$header];
503c0c79a3fStz204579	    print Hfile "};\n";
504c0c79a3fStz204579	}
505c0c79a3fStz204579    }
506c0c79a3fStz204579    foreach my $header (keys %headers) {
507c0c79a3fStz204579    	next unless $Hfile[$header];
508c0c79a3fStz204579	*Hfile = $Hfile[$header];
509c0c79a3fStz204579	my $adt_event_n = "_ADT_EVENT_H";
510c0c79a3fStz204579	if ($header > 0) {
511c0c79a3fStz204579	    $adt_event_n = "_ADT_EVENT_".$header."_H";
512c0c79a3fStz204579	}
513c0c79a3fStz204579	print Hfile <<EOF;
514c0c79a3fStz204579
515c0c79a3fStz204579
516c0c79a3fStz204579#ifndef	ADT_PRIVATE
517c0c79a3fStz204579#define	ADT_PRIVATE
518c0c79a3fStz204579
519c0c79a3fStz204579/*
520c0c79a3fStz204579 * These interfaces are project private and will change without
521c0c79a3fStz204579 * notice as needed for the BSM API project.
522c0c79a3fStz204579 */
523c0c79a3fStz204579
524c0c79a3fStz204579extern	void	adt_get_auid(const adt_session_data_t *, au_id_t *);
525c0c79a3fStz204579extern	void	adt_set_auid(const adt_session_data_t *, const au_id_t);
526c0c79a3fStz204579
527c0c79a3fStz204579extern	void	adt_get_mask(const adt_session_data_t *, au_mask_t *);
528c0c79a3fStz204579extern	void	adt_set_mask(const adt_session_data_t *, const au_mask_t *);
529c0c79a3fStz204579
530c0c79a3fStz204579extern	void	adt_get_termid(const adt_session_data_t *, au_tid_addr_t *);
531c0c79a3fStz204579extern	void	adt_set_termid(const adt_session_data_t *,
532c0c79a3fStz204579    const au_tid_addr_t *);
533c0c79a3fStz204579
534c0c79a3fStz204579extern	void	adt_get_asid(const adt_session_data_t *, au_asid_t *);
535c0c79a3fStz204579extern	void	adt_set_asid(const adt_session_data_t *, const au_asid_t);
5365b7f77adStw21770extern	au_id_t	adt_get_unique_id(au_id_t);
537c0c79a3fStz204579
538c0c79a3fStz204579#endif
539c0c79a3fStz204579
540c0c79a3fStz204579#ifdef	__cplusplus
541c0c79a3fStz204579}
542c0c79a3fStz204579#endif
543c0c79a3fStz204579
544c0c79a3fStz204579#endif	/* $adt_event_n */
545c0c79a3fStz204579EOF
546c0c79a3fStz204579    }
547c0c79a3fStz204579    closeHeaderFiles(@Hfile);
548c0c79a3fStz204579}
549c0c79a3fStz204579
550c0c79a3fStz204579sub generateTableC {
551c0c79a3fStz204579    my $event = shift;
552c0c79a3fStz204579    my $eventId = shift;
553c0c79a3fStz204579    my $eventType = shift;
554c0c79a3fStz204579    my $eventHeader = shift;
555c0c79a3fStz204579    my $omit = shift;
556c0c79a3fStz204579
557c0c79a3fStz204579    my %tokenType = (
558f72effdeSgww	#
559f72effdeSgww	#	tokenTypes are the ones that are actually defined
560f72effdeSgww	#	for use in adt.xml audit records
561f72effdeSgww	#
562f72effdeSgww
563f72effdeSgww	#	  'acl'			=> 'AUT_ACL',		# not defined
564f72effdeSgww	#	  'arbitrary'		=> 'AUT_ARBITRARY',	# not defined
565f72effdeSgww	#	  'arg'			=> 'AUT_ARG',		# not defined
566f72effdeSgww	#	  'attr'		=> 'AUT_ATTR',
567c0c79a3fStz204579		  'command'		=> 'AUT_CMD',
568*3cccda98SJan Friedel		  'command_alt'		=> 'ADT_CMD_ALT',	# dummy token id
569f72effdeSgww	#	  'date'		=> 'AUT_TEXT',		# not used
570f72effdeSgww	#	  'exec_args'   	=> 'AUT_EXEC_ARGS',	# not defined
571f72effdeSgww	#	  'exec_env'    	=> 'AUT_EXEC_ENV',	# not defined
572f72effdeSgww	#	  'exit'        	=> 'AUT_EXIT',		# not defined
573c0c79a3fStz204579		  'fmri'        	=> 'AUT_FMRI',
574f72effdeSgww	#	  'groups'      	=> 'AUT_GROUPS',	# not defined
575f72effdeSgww	#	  'header'      	=> 'AUT_HEADER',	# not defined
576f72effdeSgww		  'in_peer'     	=> 'ADT_IN_PEER',	# dummy token id
577c0c79a3fStz204579		  'tid'          	=> 'AUT_TID',
578f72effdeSgww	#	  'ipc'         	=> 'AUT_IPC',		# not defined
579f72effdeSgww	#	  'ipc_perm'    	=> 'AUT_IPC_PERM',	# not defined
580f72effdeSgww	#	  'iport'		=> 'AUT_IPORT',		# not defined
581c0c79a3fStz204579		  'label'		=> 'AUT_LABEL',
582c0c79a3fStz204579		  'newgroups'   	=> 'AUT_NEWGROUPS',
583f72effdeSgww	#	  'opaque'      	=> 'AUT_OPAQUE',	# not defined
584c0c79a3fStz204579		  'path'        	=> 'AUT_PATH',
585c0c79a3fStz204579		  'path_list'		=> '-AUT_PATH',		# dummy token id
586c0c79a3fStz204579		  'process'     	=> 'AUT_PROCESS',
587c0c79a3fStz204579		  'priv_effective'	=> 'ADT_AUT_PRIV_E',	# dummy token id
588c0c79a3fStz204579		  'priv_limit'		=> 'ADT_AUT_PRIV_L', 	# dummy token id
589c0c79a3fStz204579		  'priv_inherit'	=> 'ADT_AUT_PRIV_I',	# dummy token id
590c0c79a3fStz204579		  'return'      	=> 'AUT_RETURN',
591f72effdeSgww	#	  'seq'         	=> 'AUT_SEQ',		# not defined
592f72effdeSgww	#	  'socket'      	=> 'AUT_SOCKET',	# not defined
593f72effdeSgww	#	  'socket-inet' 	=> 'AUT_SOCKET_INET',
594c0c79a3fStz204579		  'subject'     	=> 'AUT_SUBJECT',
595c0c79a3fStz204579		  'text'        	=> 'AUT_TEXT',
596f72effdeSgww	#	  'trailer'     	=> 'AUT_TRAILER',	# not defined
597c0c79a3fStz204579		  'uauth'		=> 'AUT_UAUTH',
598c0c79a3fStz204579		  'zonename'		=> 'AUT_ZONENAME'
599c0c79a3fStz204579		 );
600c0c79a3fStz204579
601c0c79a3fStz204579    my @xlateEntryList = ();
602c0c79a3fStz204579
603c0c79a3fStz204579    my $external = $event->getExternal();
604c0c79a3fStz204579    my $internal = $event->getInternal();
605c0c79a3fStz204579
606c0c79a3fStz204579    unless ($external) {
607c0c79a3fStz204579	print STDERR "No external object captured for event $eventId\n";
608c0c79a3fStz204579	return;
609c0c79a3fStz204579    }
610c0c79a3fStz204579    if ($eventType) {
611c0c79a3fStz204579	$nameTranslation{$eventId} = $eventId;
612c0c79a3fStz204579    } else {
613c0c79a3fStz204579	$nameTranslation{$eventId} = $external->getInternalName();
614c0c79a3fStz204579    }
615c0c79a3fStz204579    unless ($internal) {
616c0c79a3fStz204579	print STDERR "No internal object captured for event $eventId\n";
617c0c79a3fStz204579	return;
618c0c79a3fStz204579    }
619c0c79a3fStz204579    my @entryRef = $internal->getEntries();
620c0c79a3fStz204579    my $entryRef;
621c0c79a3fStz204579    my @tokenOrder = ();
622c0c79a3fStz204579    my $firstTokenIndex = 0; # djdj not used yet, djdj BUG!
623c0c79a3fStz204579    			     # needs to be used by translate table
624c0c79a3fStz204579
625c0c79a3fStz204579    if ($internal->isReorder()) { # prescan the entry list to get the token order
626c0c79a3fStz204579      my @inputOrder;
627c0c79a3fStz204579      foreach $entryRef (@entryRef) {
628c0c79a3fStz204579	my ($intEntry, $entry) = @$entryRef;
629c0c79a3fStz204579	push (@inputOrder, $intEntry->getAttr('order'));
630c0c79a3fStz204579      }
631c0c79a3fStz204579
632c0c79a3fStz204579      my $i; # walk down the inputOrder list once
633c0c79a3fStz204579      my $k = 1; # discover next in line
634c0c79a3fStz204579      my $l = 0; # who should point to next in line
635c0c79a3fStz204579      for ($i = 0; $i <= $#inputOrder; $i++) {
636c0c79a3fStz204579	my $j;
637c0c79a3fStz204579	for ($j = 0; $j <= $#inputOrder; $j++) {
638c0c79a3fStz204579	  if ($k == $inputOrder[$j]) {
639c0c79a3fStz204579	    if ($k == 1) {
640c0c79a3fStz204579	        $firstTokenIndex = $j;
641c0c79a3fStz204579	    } else {
642c0c79a3fStz204579	        $tokenOrder[$l] = "&(selfReference[$j])";
643c0c79a3fStz204579	    }
644c0c79a3fStz204579	    $l = $j;
645c0c79a3fStz204579	    last;
646c0c79a3fStz204579	  }
647c0c79a3fStz204579	}
648c0c79a3fStz204579	$k++;
649c0c79a3fStz204579      }
650c0c79a3fStz204579      $tokenOrder[$l] = 'NULL';
651c0c79a3fStz204579    }
652c0c79a3fStz204579    else { # default order -- input order same as output
653c0c79a3fStz204579      my $i;
654c0c79a3fStz204579      my $j;
655c0c79a3fStz204579      for ($i = 0; $i < $#entryRef; $i++) {
656c0c79a3fStz204579	my $j = $i + 1;
657c0c79a3fStz204579	$tokenOrder[$i] = "&(selfReference[$j])";
658c0c79a3fStz204579      }
659c0c79a3fStz204579      $tokenOrder[$#entryRef] = 'NULL';
660c0c79a3fStz204579    }
661c0c79a3fStz204579
662c0c79a3fStz204579    my $sequence = 0;
663c0c79a3fStz204579    foreach $entryRef (@entryRef) {
664c0c79a3fStz204579      my ($intEntry, $entry) = @$entryRef;
665c0c79a3fStz204579      my $entryId = $entry->getAttr('id');
666c0c79a3fStz204579
667c0c79a3fStz204579      my ($extEntry, $unusedEntry, $tokenId) =
668c0c79a3fStz204579	$external->getEntry($entryId);
669c0c79a3fStz204579      my $opt = $extEntry->getAttr('opt');
670c0c79a3fStz204579
671c0c79a3fStz204579      if ($opt eq 'none') {
672c0c79a3fStz204579	if (defined ($doc->getToken($tokenId))) {
673c0c79a3fStz204579	  if (defined ($tokenType{$tokenId})) {
674c0c79a3fStz204579	    $tokenId = $tokenType{$tokenId};
675c0c79a3fStz204579	  }
676c0c79a3fStz204579	  else {
677c0c79a3fStz204579	    print STDERR "token id $tokenId not implemented\n";
678c0c79a3fStz204579	  }
679c0c79a3fStz204579	}
680c0c79a3fStz204579	else {
681c0c79a3fStz204579	  print STDERR "token = $tokenId is undefined\n";
682c0c79a3fStz204579	  $tokenId = 'error';
683c0c79a3fStz204579	}
684c0c79a3fStz204579	my ($xlate, $jni) =
6855114d1adSgww	  formatTableEntry ('', $tokenId, $eventId, '', 0, 0,
6865114d1adSgww			    $tokenOrder[$sequence], 'NULL', $omit);
687c0c79a3fStz204579	push (@xlateEntryList, $xlate);
688c0c79a3fStz204579      }
689c0c79a3fStz204579      else {
690c0c79a3fStz204579	my $dataType = $extEntry->getAttr('type');
691c0c79a3fStz204579	$dataType =~ s/\s+//g;   # remove blanks (char * => char*)
692c0c79a3fStz204579
693c0c79a3fStz204579	my $enumGroup = '';
694c0c79a3fStz204579	if ($dataType =~ /^msg/i) {
695c0c79a3fStz204579	    $enumGroup = $dataType;
696c0c79a3fStz204579	    $enumGroup =~ s/^msg\s*//i;
697c0c79a3fStz204579	    $enumGroup = 'adt_' . $enumGroup;
698c0c79a3fStz204579	}
699c0c79a3fStz204579	my $required = ($opt eq 'required') ? 1 : 0;
700c0c79a3fStz204579	my $tsol = 0;
701c0c79a3fStz204579	my $tokenId = $intEntry->getAttr('token');
702c0c79a3fStz204579	my $token;
703c0c79a3fStz204579	my $tokenName;
704c0c79a3fStz204579	my $tokenFormat = $intEntry->getAttr('format');
705c0c79a3fStz204579	if (defined ($tokenFormat)) {
706c0c79a3fStz204579	  $tokenFormat = "\"$tokenFormat\"";
707c0c79a3fStz204579	}
708c0c79a3fStz204579	else {
709c0c79a3fStz204579	  $tokenFormat = 'NULL';
710c0c79a3fStz204579	}
711c0c79a3fStz204579
712c0c79a3fStz204579	if (defined ($token = $doc->getToken($tokenId))) {
713c0c79a3fStz204579	  $tsol = (lc $token->getUsage() eq 'tsol') ? 1 : 0;
714c0c79a3fStz204579	  if (defined ($tokenType{$tokenId})) {
715c0c79a3fStz204579	    $tokenName = $tokenType{$tokenId};
716c0c79a3fStz204579	  }
717c0c79a3fStz204579	  else {
718c0c79a3fStz204579	    print STDERR "token id $tokenId not implemented\n";
719c0c79a3fStz204579	  }
720c0c79a3fStz204579	}
721c0c79a3fStz204579	else {
722c0c79a3fStz204579	  print STDERR
723c0c79a3fStz204579	    "$tokenId is an unimplemented token ($entryId in $eventId)\n";
724c0c79a3fStz204579	  $tokenName = 'AUT_TEXT';
725c0c79a3fStz204579	}
726c0c79a3fStz204579	my ($xlate, $jni) =
727c0c79a3fStz204579	  formatTableEntry($entryId, $tokenName, $eventId, $dataType, $required,
728c0c79a3fStz204579			   $tsol, $tokenOrder[$sequence], $tokenFormat,
7295114d1adSgww			   $enumGroup, $omit);
730c0c79a3fStz204579	push (@xlateEntryList, $xlate);
731c0c79a3fStz204579      }
732c0c79a3fStz204579      $sequence++;
733c0c79a3fStz204579    }
734c0c79a3fStz204579    $xlateEventTable{$eventId} = [\@xlateEntryList, $eventType, $firstTokenIndex,
735c0c79a3fStz204579				 $eventHeader];
736c0c79a3fStz204579}
737c0c79a3fStz204579
738c0c79a3fStz204579sub formatTableEntry {
7395114d1adSgww    my ($id, $token, $eventId, $type, $required, $tsol, $sequence, $format,
7405114d1adSgww	$enumGroup, $omitEntry) = @_;
741c0c79a3fStz204579
742c0c79a3fStz204579
743c0c79a3fStz204579    # does this map belong in the xml source?  (at least the defaults?)
744c0c79a3fStz204579    # fill in the default value only if it is other than zero.
745c0c79a3fStz204579    #		      base type		    adt name,	default value
746c0c79a3fStz204579    my %entryDef = ( 'au_asid_t'       	=> ['ADT_UINT32',	''],
747c0c79a3fStz204579		     'uint_t'		=> ['ADT_UINT32',      	''],
748c0c79a3fStz204579		     'int'		=> ['ADT_INT',		''],
749c0c79a3fStz204579		     'int32_t'		=> ['ADT_INT32',	''],
750c0c79a3fStz204579		     'uid_t'		=> ['ADT_UID',		'AU_NOAUDITID'],
751c0c79a3fStz204579		     'gid_t'		=> ['ADT_GID',		'AU_NOAUDITID'],
752c0c79a3fStz204579		     'uid_t*'		=> ['ADT_UIDSTAR',	''],
753c0c79a3fStz204579		     'gid_t*'		=> ['ADT_GIDSTAR',	''],
754c0c79a3fStz204579		     'char'		=> ['ADT_CHAR',		''],
755c0c79a3fStz204579		     'char*'		=> ['ADT_CHARSTAR',	''],
756c0c79a3fStz204579		     'char**'		=> ['ADT_CHAR2STAR',	''],
757c0c79a3fStz204579		     'long'		=> ['ADT_LONG',		''],
758c0c79a3fStz204579		     'pid_t'		=> ['ADT_PID',		''],
759c0c79a3fStz204579		     'priv_set_t*'	=> ['ADT_PRIVSTAR',	''],
760c0c79a3fStz204579		     'ulong_t'		=> ['ADT_ULONG',	''],
761c0c79a3fStz204579		     'uint16_t',	=> ['ADT_UINT16',	''],
762c0c79a3fStz204579		     'uint32_t'		=> ['ADT_UINT32',	''],
763c0c79a3fStz204579		     'uint32_t*'	=> ['ADT_UINT32STAR',	''],
764c0c79a3fStz204579		     'uint32_t[]'	=> ['ADT_UINT32ARRAY',  ''],
765c0c79a3fStz204579		     'uint64_t'		=> ['ADT_UINT64',	''],
766c0c79a3fStz204579		     'uint64_t*'	=> ['ADT_UINT64STAR',	''],
767c0c79a3fStz204579		     'm_label_t*'	=> ['ADT_MLABELSTAR',	''],
76869987563Ssabdar		     'fd_t'		=> ['ADT_FD',		'-1'],
769c0c79a3fStz204579		    );
770c0c79a3fStz204579    my $xlateLabel = $uniLabel.$xlateUniLabelInc;
771c0c79a3fStz204579    my $xlateLabelInc = 0;
772c0c79a3fStz204579    my $xlateLine = '';
773c0c79a3fStz204579    my @jniLine = ();
774c0c79a3fStz204579
775c0c79a3fStz204579	# the list handling should be a simple loop with a loop of one
776c0c79a3fStz204579        # falling out naturally.
777c0c79a3fStz204579
778c0c79a3fStz204579    unless ($type =~ /,/) {	# if list, then generate sequence of entries
779c0c79a3fStz204579      my $dataType;
780c0c79a3fStz204579      my $dataSize;
781c0c79a3fStz204579      my $xlateLabelRef = '';
782c0c79a3fStz204579
783c0c79a3fStz204579      my $arraySize = '';
784c0c79a3fStz204579      $arraySize = $1 if ($type =~ s/\[(\d+)\]/[]/);
785c0c79a3fStz204579
786c0c79a3fStz204579      my $entryType = ${$entryDef{$type}}[0];
787c0c79a3fStz204579
788c0c79a3fStz204579      my @xlateType = ();	# for adt_xlate.c
789c0c79a3fStz204579      my $typeCount = 1;
790c0c79a3fStz204579
791c0c79a3fStz204579      if ($entryType) {
792c0c79a3fStz204579	$dataType = $entryType;
793c0c79a3fStz204579	$type =~ s/([^*]+)\s*(\*+)/$1 $2/;
794c0c79a3fStz204579	$type =~ s/\[\]//;
795c0c79a3fStz204579	$dataSize = "sizeof ($type)";
796c0c79a3fStz204579	if ($arraySize) {
797c0c79a3fStz204579		$dataSize = "$arraySize * " . $dataSize;
798c0c79a3fStz204579	}
799c0c79a3fStz204579	$xlateLine = "{{$dataType, $dataSize}}";
800c0c79a3fStz204579	push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]);
801c0c79a3fStz204579      } elsif ($type eq '') {
802c0c79a3fStz204579	  $xlateLabelRef = 'NULL';
803c0c79a3fStz204579      } elsif ($type =~ /^msg/i) {
804c0c79a3fStz204579	$type =~ s/^msg//i;
805c0c79a3fStz204579	$dataType = 'ADT_MSG';
806c0c79a3fStz204579	my $dataEnum = 'ADT_LIST_' . uc $type;
807c0c79a3fStz204579	$xlateLine = "{{$dataType, $dataEnum}}";
808c0c79a3fStz204579	push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]);
809c0c79a3fStz204579      } elsif ($type =~ /time_t/i) {
810c0c79a3fStz204579	$dataType = 'ADT_DATE';
811c0c79a3fStz204579	$dataSize = "sizeof (time_t)";
812c0c79a3fStz204579	$xlateLine = "{{$dataType, $dataSize}}";
813c0c79a3fStz204579	push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]);
814c0c79a3fStz204579      } elsif ($type =~ /termid/i) {
815c0c79a3fStz204579	$dataType = 'ADT_TERMIDSTAR';
816c0c79a3fStz204579	$dataSize = "sizeof (au_tid_addr_t *)";
817c0c79a3fStz204579	$xlateLine = "{{$dataType, $dataSize}}";
818c0c79a3fStz204579	push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]);
8195114d1adSgww      } elsif (uc $omitEntry eq 'JNI') {
820c0c79a3fStz204579	$xlateLabelRef = 'NULL';
821c0c79a3fStz204579      } else {
822c0c79a3fStz204579	print STDERR "$type is not an implemented data type\n";
823c0c79a3fStz204579	$xlateLabelRef = 'NULL';
824c0c79a3fStz204579      }
825c0c79a3fStz204579      if ($xlateLine && !($xlateTypeList{$xlateLine})) {
826c0c79a3fStz204579	$xlateTypeList{$xlateLine} = $xlateLabel;
827c0c79a3fStz204579	push (@xlateTypeList, "datadef\t$xlateLabel\[1\] =\t$xlateLine;");
828c0c79a3fStz204579	$xlateLabelInc = 1;
829c0c79a3fStz204579      } else {
830c0c79a3fStz204579	$xlateLabel = $xlateTypeList{$xlateLine};
831c0c79a3fStz204579      }
832c0c79a3fStz204579      $xlateLabelRef = '&' . $xlateLabel . '[0]'
833c0c79a3fStz204579	unless $xlateLabelRef eq 'NULL';
834c0c79a3fStz204579
835c0c79a3fStz204579      # "EOL" is where a comma should go unless end of list
836c0c79a3fStz204579      $xlateLine = "{$token,\t1,\t$xlateLabelRef,\t$sequence,\n" .
837c0c79a3fStz204579	  "\t\t0,\t$required,\t$tsol,\t$format}EOL";
838c0c79a3fStz204579
8395114d1adSgww      if (uc $omitEntry ne 'ALWAYS' && ${$entryDef{$type}}[1]) {
840c0c79a3fStz204579	  my @list = ();
841c0c79a3fStz204579	  if ($xlateDefault{$eventId}) {
842c0c79a3fStz204579	      @list = @{$xlateDefault{$eventId}};
843c0c79a3fStz204579	  } else {
844c0c79a3fStz204579	      push (@xlateDefaults, $eventId);
845c0c79a3fStz204579	  }
846c0c79a3fStz204579	  push (@list, $id, ${$entryDef{$type}}[1]);
847c0c79a3fStz204579	  $xlateDefault{$eventId} = \@list;
848c0c79a3fStz204579      }
849c0c79a3fStz204579    } else {	# is a list
850c0c79a3fStz204579      my @type = split(/,/, $type);
851c0c79a3fStz204579      my @arraySize = ();
852c0c79a3fStz204579      my @id   = split(/,/, $id);
853c0c79a3fStz204579      my @jniId  = @id;
854c0c79a3fStz204579      my $dataType;
855c0c79a3fStz204579      my $typeCount = ($#type + 1);
856c0c79a3fStz204579      my @xlateType = ();
857c0c79a3fStz204579      my @default = ();
858c0c79a3fStz204579
859c0c79a3fStz204579      foreach my $dtype (@type) {
860c0c79a3fStz204579	my $jniId = shift @jniId;
861c0c79a3fStz204579	my $id = shift @id;
862c0c79a3fStz204579	my $arraySize = '';
863c0c79a3fStz204579	$arraySize = $1 if ($dtype =~ s/\[(\d+)\]/[]/);
864c0c79a3fStz204579
865c0c79a3fStz204579	my $entryType = ${$entryDef{$dtype}}[0];
866c0c79a3fStz204579	if ($entryType) {
867c0c79a3fStz204579	  my $type = $dtype;
868c0c79a3fStz204579	  $type =~ s/([^*]+)\s*(\*+)/$1 $2/;
869c0c79a3fStz204579	  $type =~ s/\[\]//;
870c0c79a3fStz204579
871c0c79a3fStz204579	  my $sizeString = "sizeof";
872c0c79a3fStz204579	  $sizeString = "$arraySize * " . $sizeString if $arraySize;
873c0c79a3fStz204579	  push (@xlateType, "\{$entryType, $sizeString ($type)\}");
874c0c79a3fStz204579	  push (@jniLine, [$jniId, $entryType, $format, $enumGroup, $required]);
875c0c79a3fStz204579	} elsif ($type =~ /^msg/i) {
876c0c79a3fStz204579	  $type =~ s/^msg//i;
877c0c79a3fStz204579	  $dataType = 'ADT_MSG';
878c0c79a3fStz204579	  my $dataEnum = 'ADT_LIST_' . uc $type;
879c0c79a3fStz204579	  push (@xlateType, "\{$dataType, $dataEnum\}};");
880c0c79a3fStz204579	  push (@jniLine, [$jniId, $dataType, $format, $enumGroup, $required]);
881c0c79a3fStz204579	} elsif ($type =~ /time_t/i) {
882c0c79a3fStz204579	  $dataType = 'ADT_DATE';
883c0c79a3fStz204579	  push (@xlateType, "\{$entryType, sizeof ($type)\}");
884c0c79a3fStz204579	  push (@jniLine, [$jniId, $entryType, $format, $enumGroup, $required]);
885c0c79a3fStz204579	} elsif ($type =~ /termid/i) {
886c0c79a3fStz204579	  $dataType = 'ADT_TERMIDSTAR';
887c0c79a3fStz204579	  push (@xlateType, "\{$dataType, sizeof (au_tid_addr_t *)\}");
888c0c79a3fStz204579	  push (@jniLine, [$jniId, $dataType, $format, $enumGroup, $required]);
8895114d1adSgww	} elsif (uc $omitEntry eq 'JNI') {
890c0c79a3fStz204579	  # nothing to do.
891c0c79a3fStz204579	} else {
892c0c79a3fStz204579	  print STDERR "$dtype is not an implemented data type\n";
893c0c79a3fStz204579	}
8945114d1adSgww	if (uc $omitEntry ne 'ALWAYS' && ${$entryDef{$dtype}}[1]) {
895c0c79a3fStz204579	  push (@default, $id, ${$entryDef{$dtype}}[1]);
896c0c79a3fStz204579	}
897c0c79a3fStz204579      }
898c0c79a3fStz204579      my $xlateArray = "\[$typeCount\] =\t{" . join(",\n\t\t\t\t", @xlateType) . "};";
899c0c79a3fStz204579
900c0c79a3fStz204579      unless ($xlateTypeList{$xlateArray}) {
901c0c79a3fStz204579	$xlateTypeList{$xlateArray} = $xlateLabel;
902c0c79a3fStz204579	$xlateArray = "datadef\t$xlateLabel" . $xlateArray;
903c0c79a3fStz204579	push (@xlateTypeList, $xlateArray);
904c0c79a3fStz204579	$xlateLabelInc = 1;
905c0c79a3fStz204579      } else {
906c0c79a3fStz204579	$xlateLabel = $xlateTypeList{$xlateArray};
907c0c79a3fStz204579      }
908c0c79a3fStz204579      $xlateLine =
909c0c79a3fStz204579	"{$token,\t$typeCount,\t&$xlateLabel\[0\],\t$sequence,\n" .
910c0c79a3fStz204579        "\t\t0,\t$required,\t$tsol,\t$format}EOL";
911c0c79a3fStz204579      if (@default) {
912c0c79a3fStz204579	  my @list = ();
913c0c79a3fStz204579	  if ($xlateDefault{$eventId}) {
914c0c79a3fStz204579	      @list = @{$xlateDefault{$eventId}};
915c0c79a3fStz204579	  } else {
916c0c79a3fStz204579	      push (@xlateDefaults, $eventId);
917c0c79a3fStz204579	  }
918c0c79a3fStz204579	  push (@list, @default);
919c0c79a3fStz204579	  $xlateDefault{$eventId} = \@list;
920c0c79a3fStz204579      }
921c0c79a3fStz204579    }
922c0c79a3fStz204579    $xlateUniLabelInc++ if $xlateLabelInc;
923c0c79a3fStz204579    return ($xlateLine, \@jniLine);
924c0c79a3fStz204579}
925c0c79a3fStz204579
926c0c79a3fStz204579sub generateAPIFile {
927c0c79a3fStz204579    my $event = shift;
928c0c79a3fStz204579    my $eventId = shift;
929c0c79a3fStz204579    my $eventType = shift;
930c0c79a3fStz204579    my $eventHeader = shift;
931c0c79a3fStz204579    my $idNo = shift;
932c0c79a3fStz204579
933c0c79a3fStz204579    my @entryList = ();
934c0c79a3fStz204579
935c0c79a3fStz204579    my $external = $event->getExternal();
936c0c79a3fStz204579
937c0c79a3fStz204579    if ($eventType && $debug) {
938c0c79a3fStz204579	print STDERR "event $eventId is of type $eventType\n";
939c0c79a3fStz204579    }
940c0c79a3fStz204579
941c0c79a3fStz204579    return unless $external;
942c0c79a3fStz204579
943c0c79a3fStz204579    my ($extEntry, $entry, $tokenId, $format);
944c0c79a3fStz204579    while (($extEntry, $entry, $tokenId, $format) = $external->getNextEntry()) {
945c0c79a3fStz204579	last unless $entry;
946c0c79a3fStz204579	my $entryId = $entry->getAttr('id');
947c0c79a3fStz204579
948c0c79a3fStz204579	unless (defined $entryId) {
949c0c79a3fStz204579	    print STDERR "undefined entry id for external $eventId\n";
950c0c79a3fStz204579	    next;
951c0c79a3fStz204579	}
952c0c79a3fStz204579	my $option = $extEntry->getAttr('opt');
953c0c79a3fStz204579	next if ($option eq 'none');
954c0c79a3fStz204579
955c0c79a3fStz204579	if (defined (my $token = $doc->getToken($tokenId))) {
956c0c79a3fStz204579	  $option = 'Trusted Solaris only'
957c0c79a3fStz204579	    if (lc $token->getUsage() eq 'tsol') ? 1 : 0;
958c0c79a3fStz204579	}
959c0c79a3fStz204579	$option .= " (format: $format)" if $format;
960c0c79a3fStz204579
961c0c79a3fStz204579	my $dataType = $extEntry->getAttr('type');
962c0c79a3fStz204579	unless (defined $dataType) {
963c0c79a3fStz204579	  print STDERR "no type defined for external tag for $eventId\n";
964c0c79a3fStz204579	  $dataType = "error";
965c0c79a3fStz204579	}
966c0c79a3fStz204579
967c0c79a3fStz204579	my $comment = $entry->getContent();
968c0c79a3fStz204579
969c0c79a3fStz204579	if (($dataType =~ /,/) || ($entryId =~ /,/)) {
970c0c79a3fStz204579	  my @type = split(/\s*,\s*/, $dataType);
971c0c79a3fStz204579	  my @id   = split(/\s*,\s*/, $entryId);
972c0c79a3fStz204579	  if ($#type != $#id) {
973c0c79a3fStz204579	    print STDERR
974c0c79a3fStz204579	      "number of data types ($dataType) does not match number of ids ($entryId)",
975c0c79a3fStz204579	      " for event $eventId\n";
976c0c79a3fStz204579	    if ($#type < $#id) {
977c0c79a3fStz204579	      $#id = $#type;
978c0c79a3fStz204579	    }
979c0c79a3fStz204579	    else {
980c0c79a3fStz204579	      $#type = $#id;
981c0c79a3fStz204579	    }
982c0c79a3fStz204579	  }
983c0c79a3fStz204579
984c0c79a3fStz204579	  my $i;
985c0c79a3fStz204579	  my $line = '';
986c0c79a3fStz204579	  $line = "/* $comment */\n\t" if defined $comment;
987c0c79a3fStz204579	  for ($i = 0; $i <= $#type; $i++) {
988c0c79a3fStz204579	    my ($primitive, $dereference) =
989c0c79a3fStz204579	        ($type[$i] =~ /([^\*]+)\s*(\**)/);
990c0c79a3fStz204579	    $id[$i] .= $1 if ($primitive =~ s/(\[\d+\])//);
991c0c79a3fStz204579	    $line .= "$primitive\t$dereference$id[$i];\t/*  $option  */";
992c0c79a3fStz204579	    push (@entryList, $line);
993c0c79a3fStz204579	    $line = '';
994c0c79a3fStz204579	  }
995c0c79a3fStz204579	}
996c0c79a3fStz204579	else {
997c0c79a3fStz204579	  my $line = '';
998c0c79a3fStz204579	  $line = "/* $comment */\n\t" if defined $comment;
999c0c79a3fStz204579	  if ($dataType =~ /^msg/i) {
1000c0c79a3fStz204579	      $dataType =~ s/^msg\s*//i;
1001c0c79a3fStz204579	      $line .= "enum adt_$dataType" . "\t$entryId;\t/*  $option  */";
1002c0c79a3fStz204579	  }
1003c0c79a3fStz204579	  elsif ($dataType =~ /time_t/i) {
1004c0c79a3fStz204579	      $line .= "time_t\t$entryId;\t/* $option */";
1005c0c79a3fStz204579	  }
1006c0c79a3fStz204579	  else {
1007c0c79a3fStz204579	    my ($primitive, $dereference) =
1008c0c79a3fStz204579	        ($dataType =~ /([^\*]+)\s*(\**)/);
1009c0c79a3fStz204579	    $entryId .= $1 if ($primitive =~ s/(\[\d+\])//);
1010c0c79a3fStz204579	    $line .= "$primitive\t$dereference$entryId;\t/* $option */";
1011c0c79a3fStz204579	  }
1012c0c79a3fStz204579	  push (@entryList, $line);
1013c0c79a3fStz204579	}
1014c0c79a3fStz204579    }
1015c0c79a3fStz204579    $eventExtra{$eventId} = [$eventHeader, $idNo];
1016c0c79a3fStz204579    $eventAPI{$eventId} = \@entryList;
1017c0c79a3fStz204579}
1018c0c79a3fStz204579
1019c0c79a3fStz204579sub generateMsgLists {
1020c0c79a3fStz204579    my $textList = shift;
1021c0c79a3fStz204579
1022c0c79a3fStz204579    my $textName = $textList->getId();
1023c0c79a3fStz204579    my $header = $textList->getHeader();
1024c0c79a3fStz204579    my $start = $textList->getMsgStart();
1025c0c79a3fStz204579    my $public = $textList->getMsgPublic();
1026c0c79a3fStz204579    my $deprecated = $textList->getDeprecated();
1027c0c79a3fStz204579
1028c0c79a3fStz204579    addHeader($header);
1029c0c79a3fStz204579    print "$textName starts at $start\n" if $debug;
1030c0c79a3fStz204579
1031c0c79a3fStz204579    my $entry;
1032c0c79a3fStz204579    my @entry;
1033c0c79a3fStz204579    while ($entry = $textList->getNextMsg()) {
1034c0c79a3fStz204579        if ($debug) {
1035c0c79a3fStz204579	    my ($id, $text) = split(/\s*::\s*/, $entry);
1036c0c79a3fStz204579	    print "   $id = $text\n";
1037c0c79a3fStz204579	}
1038c0c79a3fStz204579	unshift (@entry, $entry);
1039c0c79a3fStz204579    }
1040c0c79a3fStz204579    $msg_list{$textName} =
1041c0c79a3fStz204579	[\@entry, [$header, $start, $public, $deprecated]];
1042c0c79a3fStz204579}
1043c0c79a3fStz204579
1044c0c79a3fStz204579sub addHeader {
1045c0c79a3fStz204579    my $header_index = shift;
1046c0c79a3fStz204579
1047c0c79a3fStz204579    die "invalid adt_event_N.h index: $header_index\n"
1048c0c79a3fStz204579        unless ($header_index =~ /^\d+$/);
1049c0c79a3fStz204579
1050c0c79a3fStz204579    $headers{$header_index} = $header_index;
1051c0c79a3fStz204579}
1052c0c79a3fStz204579
1053c0c79a3fStz204579# $header = 0 is a special case; it is for adt_event.h
1054c0c79a3fStz204579# $header > 0 creates adt_event_N.h, where N = $header
1055c0c79a3fStz204579
1056c0c79a3fStz204579sub openHeaderFiles {
1057c0c79a3fStz204579    my $outfile = shift;	# path to an adt_event_N.h file
1058c0c79a3fStz204579
1059c0c79a3fStz204579    my $header;
1060c0c79a3fStz204579    my @Hfile = (); # potentially sparse array of file handles
1061c0c79a3fStz204579    my @HfileName = (); # parallel array to Hfile, file name (not path)
1062c0c79a3fStz204579    foreach $header (sort keys %headers) {
1063c0c79a3fStz204579        my $file = $outfile;
1064c0c79a3fStz204579	if ($header > 0) {
1065c0c79a3fStz204579	    $file =~ s/_N/_$header/;
1066c0c79a3fStz204579	} else {
1067c0c79a3fStz204579	    $file =~ s/_N//;
1068c0c79a3fStz204579	}
1069c0c79a3fStz204579	unless (open($Hfile[$header], ">$file")) {
1070c0c79a3fStz204579	    print STDERR "can't open output ($file): $!\n";
1071c0c79a3fStz204579	    $HfileName[$header] = '';
1072c0c79a3fStz204579	    $Hfile[$header] = '';
1073c0c79a3fStz204579	} else {
1074c0c79a3fStz204579	    my @tmp = split(/\//, $file);
1075c0c79a3fStz204579	    $HfileName[$header] = $tmp[$#tmp];
1076c0c79a3fStz204579	}
1077c0c79a3fStz204579    }
1078c0c79a3fStz204579    return (@Hfile);
1079c0c79a3fStz204579}
1080c0c79a3fStz204579
1081c0c79a3fStz204579sub closeHeaderFiles {
1082c0c79a3fStz204579    my @Hfile = @_;
1083c0c79a3fStz204579
1084c0c79a3fStz204579    my $header;
1085c0c79a3fStz204579    foreach $header (sort keys %headers) {
1086c0c79a3fStz204579	close $Hfile[$header] if $Hfile[$header];
1087c0c79a3fStz204579    }
1088c0c79a3fStz204579}
1089