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