17aec1d6eScindi#!/bin/perl
27aec1d6eScindi#
37aec1d6eScindi# CDDL HEADER START
47aec1d6eScindi#
57aec1d6eScindi# The contents of this file are subject to the terms of the
6a307a255Sgavinm# Common Development and Distribution License (the "License").
7a307a255Sgavinm# You may not use this file except in compliance with the License.
87aec1d6eScindi#
97aec1d6eScindi# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107aec1d6eScindi# or http://www.opensolaris.org/os/licensing.
117aec1d6eScindi# See the License for the specific language governing permissions
127aec1d6eScindi# and limitations under the License.
137aec1d6eScindi#
147aec1d6eScindi# When distributing Covered Code, include this CDDL HEADER in each
157aec1d6eScindi# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167aec1d6eScindi# If applicable, add the following below this CDDL HEADER, with the
177aec1d6eScindi# fields enclosed by brackets "[]" replaced with your own identifying
187aec1d6eScindi# information: Portions Copyright [yyyy] [name of copyright owner]
197aec1d6eScindi#
207aec1d6eScindi# CDDL HEADER END
217aec1d6eScindi#
227aec1d6eScindi
237aec1d6eScindi#
247aec1d6eScindi# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
257aec1d6eScindi# Use is subject to license terms.
267aec1d6eScindi#
277aec1d6eScindi# ident	"%Z%%M%	%I%	%E% SMI"
287aec1d6eScindi#
297aec1d6eScindi
307aec1d6eScindiuse strict;
317aec1d6eScindiuse File::Basename;
327aec1d6eScindi
337aec1d6eScindimy $PROGNAME = basename($0);
347aec1d6eScindi
357aec1d6eScindimy ($funcunit, $error);
367aec1d6eScindimy @funcunits = ();
37*4156fc34Sgavinmmy @errorrefs = ();
38*4156fc34Sgavinm
39*4156fc34Sgavinmmy $codelinesin = 0;	# number of input 'code' lines for an ereport type
40*4156fc34Sgavinmmy $codeoutlen = 0;	# number of output lines from sub state_code
417aec1d6eScindi
427aec1d6eScindimy $state = "initial";
437aec1d6eScindi
447aec1d6eScindisub usage() {
457aec1d6eScindi	print STDERR "Usage: $PROGNAME inputfile\n";
467aec1d6eScindi	exit(2);
477aec1d6eScindi}
487aec1d6eScindi
497aec1d6eScindisub bail() {
507aec1d6eScindi	print STDERR "$PROGNAME: ", join(" ", @_), "\n";
517aec1d6eScindi	exit(1);
527aec1d6eScindi}
537aec1d6eScindi
547aec1d6eScindisub parsebail() {
557aec1d6eScindi	print STDERR "$PROGNAME: $::infile: $.: ", join(" ", @_), "\n";
567aec1d6eScindi	exit(1);
577aec1d6eScindi}
587aec1d6eScindi
59*4156fc34Sgavinmsub error_alloc() {
60*4156fc34Sgavinm	my @a = ();
61*4156fc34Sgavinm
62*4156fc34Sgavinm	push(@::errorrefs, \@a);
63*4156fc34Sgavinm	return (\@a);
64*4156fc34Sgavinm}
65*4156fc34Sgavinm
66*4156fc34Sgavinmsub error_dup() {
67*4156fc34Sgavinm	my ($drop) = @_;
68*4156fc34Sgavinm	my $newref = &error_alloc();
69*4156fc34Sgavinm
70*4156fc34Sgavinm	my $zeroref = $::errorrefs[0];
71*4156fc34Sgavinm
72*4156fc34Sgavinm	my $n = $#$zeroref - $drop;
73*4156fc34Sgavinm
74*4156fc34Sgavinm	@$newref = @$zeroref[0 .. $n];
75*4156fc34Sgavinm}
76*4156fc34Sgavinm
77*4156fc34Sgavinmsub code_lines() {
78*4156fc34Sgavinm	return ($::codelinesin++);
79*4156fc34Sgavinm}
80*4156fc34Sgavinm
81*4156fc34Sgavinmsub error_init() {
82*4156fc34Sgavinm	&error_alloc();
83*4156fc34Sgavinm	$::codelinesin = 0;
84*4156fc34Sgavinm}
85*4156fc34Sgavinm
86*4156fc34Sgavinmsub error_reset() {
87*4156fc34Sgavinm	@::errorrefs = ();
88*4156fc34Sgavinm	$::codelinesin = 0;
89*4156fc34Sgavinm	$::codeoutlen = 0;
90*4156fc34Sgavinm}
91*4156fc34Sgavinm
92*4156fc34Sgavinmsub errout() {
93*4156fc34Sgavinm	my ($line) = @_;
94*4156fc34Sgavinm
95*4156fc34Sgavinm	foreach my $ref (@::errorrefs) {
96*4156fc34Sgavinm		push(@$ref, $line);
97*4156fc34Sgavinm	}
98*4156fc34Sgavinm}
99*4156fc34Sgavinm
100*4156fc34Sgavinmsub errout_N() {
101*4156fc34Sgavinm	my ($instance, $line) = @_;
102*4156fc34Sgavinm	my $ref = @::errorrefs[$instance];
103*4156fc34Sgavinm	push(@$ref, $line);
104*4156fc34Sgavinm	return 1;
105*4156fc34Sgavinm}
106*4156fc34Sgavinm
107*4156fc34Sgavinmsub print_errout() {
108*4156fc34Sgavinm	foreach my $ref (@::errorrefs) {
109*4156fc34Sgavinm		print @$ref;
110*4156fc34Sgavinm	}
111*4156fc34Sgavinm}
112*4156fc34Sgavinm
1137aec1d6eScindisub print_header() {
1147aec1d6eScindi	print "#include \"ao_mca_disp.h\"\n\n";
1157aec1d6eScindi}
1167aec1d6eScindi
1177aec1d6eScindisub print_footer() {
118*4156fc34Sgavinm	print 'const ao_error_disp_t *ao_error_disp[] = {' . "\n";
1197aec1d6eScindi
1207aec1d6eScindi	foreach my $name (@funcunits) {
1217aec1d6eScindi		print "\t$name,\n";
1227aec1d6eScindi	}
1237aec1d6eScindi
1247aec1d6eScindi	print "};\n";
1257aec1d6eScindi}
1267aec1d6eScindi
1277aec1d6eScindisub funcunit_begin() {
1287aec1d6eScindi	my $arrnm = "ao_error_disp_" . $_[0];
1297aec1d6eScindi	print "static const ao_error_disp_t " . $arrnm . "[] = {\n";
1307aec1d6eScindi
1317aec1d6eScindi	@funcunits = (@funcunits, $arrnm);
1327aec1d6eScindi}
1337aec1d6eScindi
1347aec1d6eScindisub funcunit_end() {
135*4156fc34Sgavinm	print "\t{ NULL }\n};\n\n";
1367aec1d6eScindi}
1377aec1d6eScindi
1387aec1d6eScindisub error_begin() {
1397aec1d6eScindi	my ($ereport_name) = @_;
1407aec1d6eScindi
1417aec1d6eScindi	$ereport_name =~ tr/[a-z]./[A-Z]_/;
1427aec1d6eScindi	my $flags_name = $ereport_name;
1437aec1d6eScindi	$flags_name =~ s/EREPORT_/EREPORT_PAYLOAD_FLAGS_/;
1447aec1d6eScindi
145*4156fc34Sgavinm	&errout("\tFM_$ereport_name,\n\tFM_$flags_name,\n");
1467aec1d6eScindi}
1477aec1d6eScindi
1487aec1d6eScindisub error_end() {
149*4156fc34Sgavinm	&errout("\t},\n\n");
150*4156fc34Sgavinm
151*4156fc34Sgavinm	&print_errout();
152*4156fc34Sgavinm
153*4156fc34Sgavinm	&error_reset();
1547aec1d6eScindi}
1557aec1d6eScindi
1567aec1d6eScindisub print_bits() {
1577aec1d6eScindi	my $name = $_[0];
1587aec1d6eScindi	my @bits = @_[1..$#_];
159*4156fc34Sgavinm	my $out = "";
1607aec1d6eScindi
1617aec1d6eScindi	if (@bits == 0) {
162*4156fc34Sgavinm		$out = "\t0,";
1637aec1d6eScindi	} elsif (@bits == 1) {
164*4156fc34Sgavinm		$out = "\t$bits[0],";
1657aec1d6eScindi	} else {
166*4156fc34Sgavinm		$out = "\t( " . join(" | ", @bits) . " ),";
1677aec1d6eScindi	}
1687aec1d6eScindi
169*4156fc34Sgavinm	$out .= " /* $name */" if (defined $name);
170*4156fc34Sgavinm	$out .= "\n";
171*4156fc34Sgavinm
172*4156fc34Sgavinm	return ($out);
1737aec1d6eScindi}
1747aec1d6eScindi
1757aec1d6eScindisub field_burst() {
1767aec1d6eScindi	my ($field, $valuesref, $name, $prefix) = @_;
1777aec1d6eScindi
1787aec1d6eScindi	if ($field eq "-") {
1797aec1d6eScindi		return ();
1807aec1d6eScindi	}
1817aec1d6eScindi
1827aec1d6eScindi	map {
1837aec1d6eScindi		if (!defined ${$valuesref}{$_}) {
1847aec1d6eScindi			&parsebail("unknown $name value `$_'");
1857aec1d6eScindi		}
1867aec1d6eScindi		$_ = ${$valuesref}{$_};
1877aec1d6eScindi		tr/[a-z]/[A-Z]/;
1887aec1d6eScindi		$prefix . "_" . $_;
1897aec1d6eScindi	} split(/\//, $field);
1907aec1d6eScindi}
1917aec1d6eScindi
1927aec1d6eScindisub bin2dec() {
1937aec1d6eScindi	my $bin = $_[0];
1947aec1d6eScindi	my $dec = 0;
1957aec1d6eScindi
1967aec1d6eScindi	foreach my $bit (split(//, $bin)) {
1977aec1d6eScindi		$dec = $dec * 2 + ($bit eq "1" ? 1 : 0);
1987aec1d6eScindi	}
1997aec1d6eScindi
2007aec1d6eScindi	$dec;
2017aec1d6eScindi}
2027aec1d6eScindi
2037aec1d6eScindisub state_funcunit() {
2047aec1d6eScindi	my $val = $_[0];
2057aec1d6eScindi
2067aec1d6eScindi	if (defined $::funcunit) {
2077aec1d6eScindi		&funcunit_end();
2087aec1d6eScindi	}
2097aec1d6eScindi
2107aec1d6eScindi	$::funcunit = $val;
2117aec1d6eScindi	undef $::error;
2127aec1d6eScindi	&funcunit_begin($::funcunit);
2137aec1d6eScindi}
2147aec1d6eScindi
2157aec1d6eScindisub state_desc() {
2167aec1d6eScindi	my $desc = $_[0];
2177aec1d6eScindi
218*4156fc34Sgavinm	&error_init();
219*4156fc34Sgavinm
220*4156fc34Sgavinm	&errout("\t/* $desc */\n\t{\n");
2217aec1d6eScindi}
2227aec1d6eScindi
2237aec1d6eScindisub state_error() {
2247aec1d6eScindi	$::error = $_[0];
2257aec1d6eScindi	&error_begin($::error);
2267aec1d6eScindi}
2277aec1d6eScindi
2287aec1d6eScindisub state_mask_on() {
2297aec1d6eScindi	@::mask_on = map { tr/[a-z]/[A-Z]/; $_; } split(/,\s*/, $_[0]);
2307aec1d6eScindi}
2317aec1d6eScindi
2327aec1d6eScindisub state_mask_off() {
2337aec1d6eScindi	my @mask_off = map { tr/[a-z]/[A-Z]/; $_; } split(/,\s*/, $_[0]);
2347aec1d6eScindi
235*4156fc34Sgavinm	&errout(&print_bits("mask", @::mask_on, @mask_off));
236*4156fc34Sgavinm	&errout(&print_bits("mask_res", @::mask_on));
2377aec1d6eScindi}
2387aec1d6eScindi
2397aec1d6eScindisub state_code() {
240*4156fc34Sgavinm	my ($ext, $type, $pp, $t, $r4, $addr, $ii, $ll, $tt) =
241*4156fc34Sgavinm	    split(/\s+/, $_[0]);
2427aec1d6eScindi
2437aec1d6eScindi	my %tt_values = ( instr => 1, data => 1, gen => 1, '-' => 1 );
2447aec1d6eScindi	my %ll_values = ( l0 => 1, l1 => 1, l2 => 1, lg => 1 );
2457aec1d6eScindi
2467aec1d6eScindi	my %r4_values = (
2477aec1d6eScindi		gen => 'gen',
2487aec1d6eScindi		rd => 'rd',
2497aec1d6eScindi		wr => 'wr',
2507aec1d6eScindi		drd => 'drd',
2517aec1d6eScindi		dwr => 'dwr',
2527aec1d6eScindi		ird => 'ird',
2537aec1d6eScindi		pf => 'prefetch',
2547aec1d6eScindi		ev => 'evict',
2557aec1d6eScindi		snp => 'snoop',
2567aec1d6eScindi	        '-' => '-');
2577aec1d6eScindi
2587aec1d6eScindi	my %pp_values = (
2597aec1d6eScindi		src => 'src',
2607aec1d6eScindi		rsp => 'rsp',
2617aec1d6eScindi		obs => 'obs',
2627aec1d6eScindi		gen => 'gen',
2637aec1d6eScindi		'-' => '-' );
2647aec1d6eScindi
2657aec1d6eScindi	my %t_values = ( 0 => 1, 1 => 1, '-' => 1 );
2667aec1d6eScindi
2677aec1d6eScindi	my %ii_values = (
2687aec1d6eScindi		mem => 'mem',
2697aec1d6eScindi		io => 'io',
2707aec1d6eScindi		gen => 'gen',
2717aec1d6eScindi		'-' => '-' );
2727aec1d6eScindi
273*4156fc34Sgavinm	my $instance = &code_lines();
274*4156fc34Sgavinm	if ($instance > 0) {
275*4156fc34Sgavinm		&error_dup($::codeoutlen);	# dup info thus far
276*4156fc34Sgavinm	}
277*4156fc34Sgavinm
2787aec1d6eScindi	if (!defined $tt_values{$tt}) {
2797aec1d6eScindi		&parsebail("unknown tt value `$tt'");
2807aec1d6eScindi	}
2817aec1d6eScindi
2827aec1d6eScindi	if (!defined $ll_values{$ll}) {
2837aec1d6eScindi		&parsebail("unknown ll value `$ll'");
2847aec1d6eScindi	}
2857aec1d6eScindi
2867aec1d6eScindi	my @r4 = &field_burst($r4, \%r4_values, "r4", "AO_MCA_R4_BIT");
2877aec1d6eScindi
2887aec1d6eScindi	my @pp = ($pp eq '-') ? () :
2897aec1d6eScindi	    &field_burst($pp, \%pp_values, "pp", "AO_MCA_PP_BIT");
2907aec1d6eScindi
2917aec1d6eScindi	if (!defined $t_values{$t}) {
2927aec1d6eScindi		&parsebail("unknown t value `$t'");
2937aec1d6eScindi	}
2947aec1d6eScindi
2957aec1d6eScindi	my @ii = ($ii eq '-') ? () :
2967aec1d6eScindi	    &field_burst($ii, \%ii_values, "ii", "AO_MCA_II_BIT");
2977aec1d6eScindi
2987aec1d6eScindi	map {
2997aec1d6eScindi		tr/[a-z]/[A-Z]/;
3007aec1d6eScindi	} ($ii, $ll, $tt);
3017aec1d6eScindi
3027aec1d6eScindi	if ($type eq "bus") {
3037aec1d6eScindi		if ($pp eq "-" || $t eq "-" || $r4 eq "-" || $ii eq "-" ||
3047aec1d6eScindi		    $ll eq "-" ||
3057aec1d6eScindi		    $tt ne "-") {
3067aec1d6eScindi			&parsebail("invalid members for bus code type");
3077aec1d6eScindi		}
3087aec1d6eScindi
309*4156fc34Sgavinm		$::codeoutlen += &errout_N($instance, "\tAMD_ERRCODE_MKBUS(" .
3107aec1d6eScindi		    "0, " . # pp
3117aec1d6eScindi		    "AMD_ERRCODE_T_" . ($t ? "TIMEOUT" : "NONE") . ", " .
3127aec1d6eScindi		    "0, " . # r4
3137aec1d6eScindi		    "0, " . # ii
314*4156fc34Sgavinm		    "AMD_ERRCODE_LL_$ll),\n");
3157aec1d6eScindi
3167aec1d6eScindi	} elsif ($type eq "mem") {
3177aec1d6eScindi		if ($r4 eq "-" || $tt eq "-" || $ll eq "-" ||
3187aec1d6eScindi		    $pp ne "-" || $t ne "-" || $ii ne "-") {
3197aec1d6eScindi			&parsebail("invalid members for mem code type");
3207aec1d6eScindi		}
3217aec1d6eScindi
322*4156fc34Sgavinm		$::codeoutlen += &errout_N($instance, "\tAMD_ERRCODE_MKMEM(" .
3237aec1d6eScindi		    "0, " . # r4
3247aec1d6eScindi		    "AMD_ERRCODE_TT_$tt, " .
325*4156fc34Sgavinm		    "AMD_ERRCODE_LL_$ll),\n");
3267aec1d6eScindi
3277aec1d6eScindi	} elsif ($type eq "tlb") {
3287aec1d6eScindi		if ($tt eq "-" || $ll eq "-" ||
3297aec1d6eScindi		    $r4 ne "-" || $pp ne "-" || $t ne "-" || $ii ne "-") {
3307aec1d6eScindi			&parsebail("invalid members for tlb code type");
3317aec1d6eScindi		}
3327aec1d6eScindi
333*4156fc34Sgavinm		$::codeoutlen += &errout_N($instance, "\tAMD_ERRCODE_MKTLB(" .
3347aec1d6eScindi		    "AMD_ERRCODE_TT_$tt, " .
335*4156fc34Sgavinm		    "AMD_ERRCODE_LL_$ll),\n");
3367aec1d6eScindi	} else {
3377aec1d6eScindi		&parsebail("unknown code type `$type'");
3387aec1d6eScindi	}
3397aec1d6eScindi
340*4156fc34Sgavinm	$::codeoutlen += &errout_N($instance, "\t" . &bin2dec($ext) .
341*4156fc34Sgavinm	    ", /* ext code $ext */\n");
3427aec1d6eScindi
343*4156fc34Sgavinm	$::codeoutlen += &errout_N($instance, &print_bits("pp_bits", @pp));
344*4156fc34Sgavinm	$::codeoutlen += &errout_N($instance, &print_bits("ii_bits", @ii));
345*4156fc34Sgavinm	$::codeoutlen += &errout_N($instance, &print_bits("r4_bits", @r4));
346*4156fc34Sgavinm
347*4156fc34Sgavinm	my $valid_hi;
348*4156fc34Sgavinm	my $valid_lo;
349*4156fc34Sgavinm
350*4156fc34Sgavinm	if ($addr eq "none") {
351*4156fc34Sgavinm		$valid_hi = $valid_lo = 0;
352*4156fc34Sgavinm	} elsif ($addr =~ /<(\d+):(\d+)>/) {
353*4156fc34Sgavinm		$valid_hi = $1;
354*4156fc34Sgavinm		$valid_lo = $2;
355*4156fc34Sgavinm	} else {
356*4156fc34Sgavinm		&parsebail("invalid addr specification");
357*4156fc34Sgavinm	}
358*4156fc34Sgavinm	$::codeoutlen += &errout_N($instance, "\t" . $valid_hi .
359*4156fc34Sgavinm	    ", /* addr valid hi */\n");
360*4156fc34Sgavinm	$::codeoutlen += &errout_N($instance, "\t" . $valid_lo .
361*4156fc34Sgavinm	    ", /* addr valid lo */\n");
3627aec1d6eScindi}
3637aec1d6eScindi
3647aec1d6eScindisub state_panic() {
365a307a255Sgavinm	my @vals = split(/,\s*/, $_[0]);
3667aec1d6eScindi
367a307a255Sgavinm	if ($#vals < 0) {
368*4156fc34Sgavinm		&errout("\t0, /* panic_when */\n");
3697aec1d6eScindi	} else {
370a307a255Sgavinm		@vals = map { tr/[a-z]/[A-Z]/; "AO_AED_PANIC_" . $_; } @vals;
371*4156fc34Sgavinm		&errout(&print_bits("panic_when", @vals));
3727aec1d6eScindi	}
3737aec1d6eScindi}
3747aec1d6eScindi
3757aec1d6eScindisub state_flags() {
3767aec1d6eScindi	my @flags = split(/,\s*/, $_[0]);
3777aec1d6eScindi
3787aec1d6eScindi	@flags = map { tr/[a-z]/[A-Z]/; "AO_AED_F_" . $_; } @flags;
3797aec1d6eScindi
380*4156fc34Sgavinm	&errout(&print_bits("flags", @flags));
3817aec1d6eScindi}
3827aec1d6eScindi
3837aec1d6eScindimy %stateparse = (
384*4156fc34Sgavinm	funcunit	=> [ \&state_funcunit, 'desc' ],
385*4156fc34Sgavinm	desc		=> [ \&state_desc, 'error' ],
386*4156fc34Sgavinm	error		=> [ \&state_error, 'mask on' ],
387*4156fc34Sgavinm	'mask on'	=> [ \&state_mask_on, 'mask off' ],
388*4156fc34Sgavinm	'mask off'	=> [ \&state_mask_off, 'code' ],
389*4156fc34Sgavinm	code		=> [ \&state_code, 'code|panic' ],
390*4156fc34Sgavinm	panic		=> [ \&state_panic, 'flags' ],
391*4156fc34Sgavinm	flags		=> [ \&state_flags, 'initial' ]
3927aec1d6eScindi);
3937aec1d6eScindi
3947aec1d6eScindiusage unless (@ARGV == 1);
3957aec1d6eScindi
3967aec1d6eScindimy $infile = $ARGV[0];
3977aec1d6eScindiopen(INFILE, "<$infile") || &bail("failed to open $infile: $!");
3987aec1d6eScindi
3997aec1d6eScindi&print_header();
4007aec1d6eScindi
4017aec1d6eScindiwhile (<INFILE>) {
4027aec1d6eScindi	chop;
4037aec1d6eScindi
4047aec1d6eScindi	/^#/ && next;
4057aec1d6eScindi	/^$/ && next;
4067aec1d6eScindi
4077aec1d6eScindi	if (!/^\s*(\S[^=]*\S)\s*=\s*(\S.*)?$/) {
4087aec1d6eScindi		&parsebail("failed to parse");
4097aec1d6eScindi	}
4107aec1d6eScindi
4117aec1d6eScindi	my ($keyword, $val) = ($1, $2);
4127aec1d6eScindi
4137aec1d6eScindi	if ($state eq "initial") {
4147aec1d6eScindi		if ($keyword eq "funcunit") {
4157aec1d6eScindi			$state = "funcunit";
4167aec1d6eScindi		} elsif ($keyword eq "desc") {
4177aec1d6eScindi			$state = "desc";
4187aec1d6eScindi		} else {
4197aec1d6eScindi			&parsebail("unexpected keyword $keyword between " .
4207aec1d6eScindi			    "errors");
4217aec1d6eScindi		}
4227aec1d6eScindi
4237aec1d6eScindi	} elsif ($state eq "desc") {
4247aec1d6eScindi		if ($keyword eq "funcunit") {
4257aec1d6eScindi			$state = "funcunit";
4267aec1d6eScindi		}
4277aec1d6eScindi	}
4287aec1d6eScindi
429*4156fc34Sgavinm	if (!($keyword =~ /$state/)) {
430*4156fc34Sgavinm		&parsebail("keyword `$keyword' invalid here; expected " .
431*4156fc34Sgavinm		    "`$state'");
4327aec1d6eScindi	}
433*4156fc34Sgavinm	$state = $keyword;	# disambiguate between multiple legal states
4347aec1d6eScindi
4357aec1d6eScindi	if (!defined $stateparse{$state}) {
4367aec1d6eScindi		&parsebail("attempt to transition to invalid state `$state'");
4377aec1d6eScindi	}
4387aec1d6eScindi
4397aec1d6eScindi	my ($handler, $next) = @{$stateparse{$state}};
4407aec1d6eScindi
4417aec1d6eScindi	&{$handler}($val);
4427aec1d6eScindi
4437aec1d6eScindi	$state = $next;
4447aec1d6eScindi
4457aec1d6eScindi	if ($state eq "initial") {
4467aec1d6eScindi		&error_end();
4477aec1d6eScindi	}
4487aec1d6eScindi}
4497aec1d6eScindi
4507aec1d6eScindiclose(INFILE);
4517aec1d6eScindi
4527aec1d6eScindiif ($state ne "initial" && $state ne "desc") {
4537aec1d6eScindi	&bail("input file ended prematurely");
4547aec1d6eScindi}
4557aec1d6eScindi
4567aec1d6eScindiif (defined $::funcunit) {
4577aec1d6eScindi	&funcunit_end();
4587aec1d6eScindi} else {
4597aec1d6eScindi	&bail("no functional units defined");
4607aec1d6eScindi}
4617aec1d6eScindi
4627aec1d6eScindi&print_footer;
463