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# 24*20c794b3Sgavinm# Copyright 2007 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 = (); 374156fc34Sgavinmmy @errorrefs = (); 384156fc34Sgavinm 394156fc34Sgavinmmy $codelinesin = 0; # number of input 'code' lines for an ereport type 404156fc34Sgavinmmy $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 594156fc34Sgavinmsub error_alloc() { 604156fc34Sgavinm my @a = (); 614156fc34Sgavinm 624156fc34Sgavinm push(@::errorrefs, \@a); 634156fc34Sgavinm return (\@a); 644156fc34Sgavinm} 654156fc34Sgavinm 664156fc34Sgavinmsub error_dup() { 674156fc34Sgavinm my ($drop) = @_; 684156fc34Sgavinm my $newref = &error_alloc(); 694156fc34Sgavinm 704156fc34Sgavinm my $zeroref = $::errorrefs[0]; 714156fc34Sgavinm 724156fc34Sgavinm my $n = $#$zeroref - $drop; 734156fc34Sgavinm 744156fc34Sgavinm @$newref = @$zeroref[0 .. $n]; 754156fc34Sgavinm} 764156fc34Sgavinm 774156fc34Sgavinmsub code_lines() { 784156fc34Sgavinm return ($::codelinesin++); 794156fc34Sgavinm} 804156fc34Sgavinm 814156fc34Sgavinmsub error_init() { 824156fc34Sgavinm &error_alloc(); 834156fc34Sgavinm $::codelinesin = 0; 844156fc34Sgavinm} 854156fc34Sgavinm 864156fc34Sgavinmsub error_reset() { 874156fc34Sgavinm @::errorrefs = (); 884156fc34Sgavinm $::codelinesin = 0; 894156fc34Sgavinm $::codeoutlen = 0; 904156fc34Sgavinm} 914156fc34Sgavinm 924156fc34Sgavinmsub errout() { 934156fc34Sgavinm my ($line) = @_; 944156fc34Sgavinm 954156fc34Sgavinm foreach my $ref (@::errorrefs) { 964156fc34Sgavinm push(@$ref, $line); 974156fc34Sgavinm } 984156fc34Sgavinm} 994156fc34Sgavinm 1004156fc34Sgavinmsub errout_N() { 1014156fc34Sgavinm my ($instance, $line) = @_; 1024156fc34Sgavinm my $ref = @::errorrefs[$instance]; 1034156fc34Sgavinm push(@$ref, $line); 1044156fc34Sgavinm return 1; 1054156fc34Sgavinm} 1064156fc34Sgavinm 1074156fc34Sgavinmsub print_errout() { 1084156fc34Sgavinm foreach my $ref (@::errorrefs) { 1094156fc34Sgavinm print @$ref; 1104156fc34Sgavinm } 1114156fc34Sgavinm} 1124156fc34Sgavinm 1137aec1d6eScindisub print_header() { 114*20c794b3Sgavinm print "#include <sys/mca_x86.h>\n"; 1157aec1d6eScindi print "#include \"ao_mca_disp.h\"\n\n"; 1167aec1d6eScindi} 1177aec1d6eScindi 1187aec1d6eScindisub print_footer() { 1194156fc34Sgavinm print 'const ao_error_disp_t *ao_error_disp[] = {' . "\n"; 1207aec1d6eScindi 1217aec1d6eScindi foreach my $name (@funcunits) { 1227aec1d6eScindi print "\t$name,\n"; 1237aec1d6eScindi } 1247aec1d6eScindi 1257aec1d6eScindi print "};\n"; 1267aec1d6eScindi} 1277aec1d6eScindi 1287aec1d6eScindisub funcunit_begin() { 1297aec1d6eScindi my $arrnm = "ao_error_disp_" . $_[0]; 1307aec1d6eScindi print "static const ao_error_disp_t " . $arrnm . "[] = {\n"; 1317aec1d6eScindi 1327aec1d6eScindi @funcunits = (@funcunits, $arrnm); 1337aec1d6eScindi} 1347aec1d6eScindi 1357aec1d6eScindisub funcunit_end() { 1364156fc34Sgavinm print "\t{ NULL }\n};\n\n"; 1377aec1d6eScindi} 1387aec1d6eScindi 1397aec1d6eScindisub error_begin() { 1407aec1d6eScindi my ($ereport_name) = @_; 1417aec1d6eScindi 1427aec1d6eScindi $ereport_name =~ tr/[a-z]./[A-Z]_/; 1437aec1d6eScindi my $flags_name = $ereport_name; 1447aec1d6eScindi $flags_name =~ s/EREPORT_/EREPORT_PAYLOAD_FLAGS_/; 1457aec1d6eScindi 1464156fc34Sgavinm &errout("\tFM_$ereport_name,\n\tFM_$flags_name,\n"); 1477aec1d6eScindi} 1487aec1d6eScindi 1497aec1d6eScindisub error_end() { 1504156fc34Sgavinm &errout("\t},\n\n"); 1514156fc34Sgavinm 1524156fc34Sgavinm &print_errout(); 1534156fc34Sgavinm 1544156fc34Sgavinm &error_reset(); 1557aec1d6eScindi} 1567aec1d6eScindi 1577aec1d6eScindisub print_bits() { 1587aec1d6eScindi my $name = $_[0]; 1597aec1d6eScindi my @bits = @_[1..$#_]; 1604156fc34Sgavinm my $out = ""; 1617aec1d6eScindi 1627aec1d6eScindi if (@bits == 0) { 1634156fc34Sgavinm $out = "\t0,"; 1647aec1d6eScindi } elsif (@bits == 1) { 1654156fc34Sgavinm $out = "\t$bits[0],"; 1667aec1d6eScindi } else { 1674156fc34Sgavinm $out = "\t( " . join(" | ", @bits) . " ),"; 1687aec1d6eScindi } 1697aec1d6eScindi 1704156fc34Sgavinm $out .= " /* $name */" if (defined $name); 1714156fc34Sgavinm $out .= "\n"; 1724156fc34Sgavinm 1734156fc34Sgavinm return ($out); 1747aec1d6eScindi} 1757aec1d6eScindi 1767aec1d6eScindisub field_burst() { 1777aec1d6eScindi my ($field, $valuesref, $name, $prefix) = @_; 1787aec1d6eScindi 1797aec1d6eScindi if ($field eq "-") { 1807aec1d6eScindi return (); 1817aec1d6eScindi } 1827aec1d6eScindi 1837aec1d6eScindi map { 1847aec1d6eScindi if (!defined ${$valuesref}{$_}) { 1857aec1d6eScindi &parsebail("unknown $name value `$_'"); 1867aec1d6eScindi } 1877aec1d6eScindi $_ = ${$valuesref}{$_}; 1887aec1d6eScindi tr/[a-z]/[A-Z]/; 1897aec1d6eScindi $prefix . "_" . $_; 1907aec1d6eScindi } split(/\//, $field); 1917aec1d6eScindi} 1927aec1d6eScindi 1937aec1d6eScindisub bin2dec() { 1947aec1d6eScindi my $bin = $_[0]; 1957aec1d6eScindi my $dec = 0; 1967aec1d6eScindi 1977aec1d6eScindi foreach my $bit (split(//, $bin)) { 1987aec1d6eScindi $dec = $dec * 2 + ($bit eq "1" ? 1 : 0); 1997aec1d6eScindi } 2007aec1d6eScindi 2017aec1d6eScindi $dec; 2027aec1d6eScindi} 2037aec1d6eScindi 2047aec1d6eScindisub state_funcunit() { 2057aec1d6eScindi my $val = $_[0]; 2067aec1d6eScindi 2077aec1d6eScindi if (defined $::funcunit) { 2087aec1d6eScindi &funcunit_end(); 2097aec1d6eScindi } 2107aec1d6eScindi 2117aec1d6eScindi $::funcunit = $val; 2127aec1d6eScindi undef $::error; 2137aec1d6eScindi &funcunit_begin($::funcunit); 2147aec1d6eScindi} 2157aec1d6eScindi 2167aec1d6eScindisub state_desc() { 2177aec1d6eScindi my $desc = $_[0]; 2187aec1d6eScindi 2194156fc34Sgavinm &error_init(); 2204156fc34Sgavinm 2214156fc34Sgavinm &errout("\t/* $desc */\n\t{\n"); 2227aec1d6eScindi} 2237aec1d6eScindi 2247aec1d6eScindisub state_error() { 2257aec1d6eScindi $::error = $_[0]; 2267aec1d6eScindi &error_begin($::error); 2277aec1d6eScindi} 2287aec1d6eScindi 2297aec1d6eScindisub state_mask_on() { 2307aec1d6eScindi @::mask_on = map { tr/[a-z]/[A-Z]/; $_; } split(/,\s*/, $_[0]); 2317aec1d6eScindi} 2327aec1d6eScindi 2337aec1d6eScindisub state_mask_off() { 2347aec1d6eScindi my @mask_off = map { tr/[a-z]/[A-Z]/; $_; } split(/,\s*/, $_[0]); 2357aec1d6eScindi 2364156fc34Sgavinm &errout(&print_bits("mask", @::mask_on, @mask_off)); 2374156fc34Sgavinm &errout(&print_bits("mask_res", @::mask_on)); 2387aec1d6eScindi} 2397aec1d6eScindi 2407aec1d6eScindisub state_code() { 2414156fc34Sgavinm my ($ext, $type, $pp, $t, $r4, $addr, $ii, $ll, $tt) = 2424156fc34Sgavinm split(/\s+/, $_[0]); 2437aec1d6eScindi 2447aec1d6eScindi my %tt_values = ( instr => 1, data => 1, gen => 1, '-' => 1 ); 2457aec1d6eScindi my %ll_values = ( l0 => 1, l1 => 1, l2 => 1, lg => 1 ); 2467aec1d6eScindi 2477aec1d6eScindi my %r4_values = ( 248*20c794b3Sgavinm 'err' => 'err', 249*20c794b3Sgavinm 'rd' => 'rd', 250*20c794b3Sgavinm 'wr' => 'wr', 251*20c794b3Sgavinm 'drd' => 'drd', 252*20c794b3Sgavinm 'dwr' => 'dwr', 253*20c794b3Sgavinm 'ird' => 'ird', 254*20c794b3Sgavinm 'pf' => 'prefetch', 255*20c794b3Sgavinm 'ev' => 'evict', 256*20c794b3Sgavinm 'snp' => 'snoop', 2577aec1d6eScindi '-' => '-'); 2587aec1d6eScindi 2597aec1d6eScindi my %pp_values = ( 260*20c794b3Sgavinm 'src' => 'src', 261*20c794b3Sgavinm 'res' => 'res', 262*20c794b3Sgavinm 'obs' => 'obs', 263*20c794b3Sgavinm 'gen' => 'gen', 2647aec1d6eScindi '-' => '-' ); 2657aec1d6eScindi 2667aec1d6eScindi my %t_values = ( 0 => 1, 1 => 1, '-' => 1 ); 2677aec1d6eScindi 2687aec1d6eScindi my %ii_values = ( 269*20c794b3Sgavinm 'mem' => 'mem', 270*20c794b3Sgavinm 'io' => 'io', 271*20c794b3Sgavinm 'gen' => 'gen', 2727aec1d6eScindi '-' => '-' ); 2737aec1d6eScindi 2744156fc34Sgavinm my $instance = &code_lines(); 2754156fc34Sgavinm if ($instance > 0) { 2764156fc34Sgavinm &error_dup($::codeoutlen); # dup info thus far 2774156fc34Sgavinm } 2784156fc34Sgavinm 2797aec1d6eScindi if (!defined $tt_values{$tt}) { 2807aec1d6eScindi &parsebail("unknown tt value `$tt'"); 2817aec1d6eScindi } 2827aec1d6eScindi 2837aec1d6eScindi if (!defined $ll_values{$ll}) { 2847aec1d6eScindi &parsebail("unknown ll value `$ll'"); 2857aec1d6eScindi } 2867aec1d6eScindi 2877aec1d6eScindi my @r4 = &field_burst($r4, \%r4_values, "r4", "AO_MCA_R4_BIT"); 2887aec1d6eScindi 2897aec1d6eScindi my @pp = ($pp eq '-') ? () : 2907aec1d6eScindi &field_burst($pp, \%pp_values, "pp", "AO_MCA_PP_BIT"); 2917aec1d6eScindi 2927aec1d6eScindi if (!defined $t_values{$t}) { 2937aec1d6eScindi &parsebail("unknown t value `$t'"); 2947aec1d6eScindi } 2957aec1d6eScindi 2967aec1d6eScindi my @ii = ($ii eq '-') ? () : 2977aec1d6eScindi &field_burst($ii, \%ii_values, "ii", "AO_MCA_II_BIT"); 2987aec1d6eScindi 2997aec1d6eScindi map { 3007aec1d6eScindi tr/[a-z]/[A-Z]/; 3017aec1d6eScindi } ($ii, $ll, $tt); 3027aec1d6eScindi 3037aec1d6eScindi if ($type eq "bus") { 3047aec1d6eScindi if ($pp eq "-" || $t eq "-" || $r4 eq "-" || $ii eq "-" || 3057aec1d6eScindi $ll eq "-" || 3067aec1d6eScindi $tt ne "-") { 3077aec1d6eScindi &parsebail("invalid members for bus code type"); 3087aec1d6eScindi } 3097aec1d6eScindi 3104156fc34Sgavinm $::codeoutlen += &errout_N($instance, "\tAMD_ERRCODE_MKBUS(" . 3117aec1d6eScindi "0, " . # pp 312*20c794b3Sgavinm "MCAX86_ERRCODE_T_" . ($t ? "TIMEOUT" : "NONE") . ", " . 3137aec1d6eScindi "0, " . # r4 3147aec1d6eScindi "0, " . # ii 315*20c794b3Sgavinm "MCAX86_ERRCODE_LL_$ll),\n"); 3167aec1d6eScindi 3177aec1d6eScindi } elsif ($type eq "mem") { 3187aec1d6eScindi if ($r4 eq "-" || $tt eq "-" || $ll eq "-" || 3197aec1d6eScindi $pp ne "-" || $t ne "-" || $ii ne "-") { 3207aec1d6eScindi &parsebail("invalid members for mem code type"); 3217aec1d6eScindi } 3227aec1d6eScindi 3234156fc34Sgavinm $::codeoutlen += &errout_N($instance, "\tAMD_ERRCODE_MKMEM(" . 3247aec1d6eScindi "0, " . # r4 325*20c794b3Sgavinm "MCAX86_ERRCODE_TT_$tt, " . 326*20c794b3Sgavinm "MCAX86_ERRCODE_LL_$ll),\n"); 3277aec1d6eScindi 3287aec1d6eScindi } elsif ($type eq "tlb") { 3297aec1d6eScindi if ($tt eq "-" || $ll eq "-" || 3307aec1d6eScindi $r4 ne "-" || $pp ne "-" || $t ne "-" || $ii ne "-") { 3317aec1d6eScindi &parsebail("invalid members for tlb code type"); 3327aec1d6eScindi } 3337aec1d6eScindi 3344156fc34Sgavinm $::codeoutlen += &errout_N($instance, "\tAMD_ERRCODE_MKTLB(" . 335*20c794b3Sgavinm "MCAX86_ERRCODE_TT_$tt, " . 336*20c794b3Sgavinm "MCAX86_ERRCODE_LL_$ll),\n"); 3377aec1d6eScindi } else { 3387aec1d6eScindi &parsebail("unknown code type `$type'"); 3397aec1d6eScindi } 3407aec1d6eScindi 3414156fc34Sgavinm $::codeoutlen += &errout_N($instance, "\t" . &bin2dec($ext) . 3424156fc34Sgavinm ", /* ext code $ext */\n"); 3437aec1d6eScindi 3444156fc34Sgavinm $::codeoutlen += &errout_N($instance, &print_bits("pp_bits", @pp)); 3454156fc34Sgavinm $::codeoutlen += &errout_N($instance, &print_bits("ii_bits", @ii)); 3464156fc34Sgavinm $::codeoutlen += &errout_N($instance, &print_bits("r4_bits", @r4)); 3474156fc34Sgavinm 3484156fc34Sgavinm my $valid_hi; 3494156fc34Sgavinm my $valid_lo; 3504156fc34Sgavinm 3514156fc34Sgavinm if ($addr eq "none") { 3524156fc34Sgavinm $valid_hi = $valid_lo = 0; 3534156fc34Sgavinm } elsif ($addr =~ /<(\d+):(\d+)>/) { 3544156fc34Sgavinm $valid_hi = $1; 3554156fc34Sgavinm $valid_lo = $2; 3564156fc34Sgavinm } else { 3574156fc34Sgavinm &parsebail("invalid addr specification"); 3584156fc34Sgavinm } 3594156fc34Sgavinm $::codeoutlen += &errout_N($instance, "\t" . $valid_hi . 3604156fc34Sgavinm ", /* addr valid hi */\n"); 3614156fc34Sgavinm $::codeoutlen += &errout_N($instance, "\t" . $valid_lo . 3624156fc34Sgavinm ", /* addr valid lo */\n"); 3637aec1d6eScindi} 3647aec1d6eScindi 3657aec1d6eScindisub state_panic() { 366a307a255Sgavinm my @vals = split(/,\s*/, $_[0]); 3677aec1d6eScindi 368a307a255Sgavinm if ($#vals < 0) { 3694156fc34Sgavinm &errout("\t0, /* panic_when */\n"); 3707aec1d6eScindi } else { 371a307a255Sgavinm @vals = map { tr/[a-z]/[A-Z]/; "AO_AED_PANIC_" . $_; } @vals; 3724156fc34Sgavinm &errout(&print_bits("panic_when", @vals)); 3737aec1d6eScindi } 3747aec1d6eScindi} 3757aec1d6eScindi 3767aec1d6eScindisub state_flags() { 3777aec1d6eScindi my @flags = split(/,\s*/, $_[0]); 3787aec1d6eScindi 3797aec1d6eScindi @flags = map { tr/[a-z]/[A-Z]/; "AO_AED_F_" . $_; } @flags; 3807aec1d6eScindi 3814156fc34Sgavinm &errout(&print_bits("flags", @flags)); 3827aec1d6eScindi} 3837aec1d6eScindi 384*20c794b3Sgavinmsub state_errtype() { 385*20c794b3Sgavinm my @types = split(/,\s*/, $_[0]); 386*20c794b3Sgavinm 387*20c794b3Sgavinm @types = map { tr/[a-z]/[A-Z]/; "AO_AED_ET_" . $_; } @types; 388*20c794b3Sgavinm 389*20c794b3Sgavinm &errout(&print_bits("errtype", @types)); 390*20c794b3Sgavinm} 391*20c794b3Sgavinm 3927aec1d6eScindimy %stateparse = ( 3934156fc34Sgavinm funcunit => [ \&state_funcunit, 'desc' ], 3944156fc34Sgavinm desc => [ \&state_desc, 'error' ], 3954156fc34Sgavinm error => [ \&state_error, 'mask on' ], 3964156fc34Sgavinm 'mask on' => [ \&state_mask_on, 'mask off' ], 3974156fc34Sgavinm 'mask off' => [ \&state_mask_off, 'code' ], 3984156fc34Sgavinm code => [ \&state_code, 'code|panic' ], 3994156fc34Sgavinm panic => [ \&state_panic, 'flags' ], 400*20c794b3Sgavinm flags => [ \&state_flags, 'errtype' ], 401*20c794b3Sgavinm errtype => [ \&state_errtype, 'initial' ] 4027aec1d6eScindi); 4037aec1d6eScindi 4047aec1d6eScindiusage unless (@ARGV == 1); 4057aec1d6eScindi 4067aec1d6eScindimy $infile = $ARGV[0]; 4077aec1d6eScindiopen(INFILE, "<$infile") || &bail("failed to open $infile: $!"); 4087aec1d6eScindi 4097aec1d6eScindi&print_header(); 4107aec1d6eScindi 4117aec1d6eScindiwhile (<INFILE>) { 4127aec1d6eScindi chop; 4137aec1d6eScindi 4147aec1d6eScindi /^#/ && next; 4157aec1d6eScindi /^$/ && next; 4167aec1d6eScindi 4177aec1d6eScindi if (!/^\s*(\S[^=]*\S)\s*=\s*(\S.*)?$/) { 4187aec1d6eScindi &parsebail("failed to parse"); 4197aec1d6eScindi } 4207aec1d6eScindi 4217aec1d6eScindi my ($keyword, $val) = ($1, $2); 4227aec1d6eScindi 4237aec1d6eScindi if ($state eq "initial") { 4247aec1d6eScindi if ($keyword eq "funcunit") { 4257aec1d6eScindi $state = "funcunit"; 4267aec1d6eScindi } elsif ($keyword eq "desc") { 4277aec1d6eScindi $state = "desc"; 4287aec1d6eScindi } else { 4297aec1d6eScindi &parsebail("unexpected keyword $keyword between " . 4307aec1d6eScindi "errors"); 4317aec1d6eScindi } 4327aec1d6eScindi 4337aec1d6eScindi } elsif ($state eq "desc") { 4347aec1d6eScindi if ($keyword eq "funcunit") { 4357aec1d6eScindi $state = "funcunit"; 4367aec1d6eScindi } 4377aec1d6eScindi } 4387aec1d6eScindi 4394156fc34Sgavinm if (!($keyword =~ /$state/)) { 4404156fc34Sgavinm &parsebail("keyword `$keyword' invalid here; expected " . 4414156fc34Sgavinm "`$state'"); 4427aec1d6eScindi } 4434156fc34Sgavinm $state = $keyword; # disambiguate between multiple legal states 4447aec1d6eScindi 4457aec1d6eScindi if (!defined $stateparse{$state}) { 4467aec1d6eScindi &parsebail("attempt to transition to invalid state `$state'"); 4477aec1d6eScindi } 4487aec1d6eScindi 4497aec1d6eScindi my ($handler, $next) = @{$stateparse{$state}}; 4507aec1d6eScindi 4517aec1d6eScindi &{$handler}($val); 4527aec1d6eScindi 4537aec1d6eScindi $state = $next; 4547aec1d6eScindi 4557aec1d6eScindi if ($state eq "initial") { 4567aec1d6eScindi &error_end(); 4577aec1d6eScindi } 4587aec1d6eScindi} 4597aec1d6eScindi 4607aec1d6eScindiclose(INFILE); 4617aec1d6eScindi 4627aec1d6eScindiif ($state ne "initial" && $state ne "desc") { 4637aec1d6eScindi &bail("input file ended prematurely"); 4647aec1d6eScindi} 4657aec1d6eScindi 4667aec1d6eScindiif (defined $::funcunit) { 4677aec1d6eScindi &funcunit_end(); 4687aec1d6eScindi} else { 4697aec1d6eScindi &bail("no functional units defined"); 4707aec1d6eScindi} 4717aec1d6eScindi 4727aec1d6eScindi&print_footer; 473