diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /devtools/bin/make360def.pl | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'devtools/bin/make360def.pl')
| -rw-r--r-- | devtools/bin/make360def.pl | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/devtools/bin/make360def.pl b/devtools/bin/make360def.pl new file mode 100644 index 0000000..38aad9f --- /dev/null +++ b/devtools/bin/make360def.pl @@ -0,0 +1,329 @@ +############################################################### +# +# generateDEF.pl +# +# Parses a .map file and generates a .def file +# for exporting functions from a dll. +# +# Note: Map Exports must be enabled in the project properties +# +############################################################### + +my @baselist; +my @output; +my $baseLen = 63; + +###################################### +# Adds tabs for better formatting + +sub Add_Tabs +{ + my $name = shift; + my $num = int( ($baseLen - length( $name )) / 8 ); + + for( $i = 0; $i < $num; $i++ ) + { + push( @output, "\t" ); + } +} + +###################################### +# Open, validate, and read a file (not implemented yet) + +sub Read_File +{ + my $name = shift; + my @file = shift; + + # read in the file + if ( open(INFILE, "$name" ) ) + { + @file = <INFILE>; + close( INFILE ); + } + else + { + print( "Error opening file $name\n" ); + exit 1; + } +} + +##################################### +# Start of script + +print( "Valve Software - make360def.pl\n" ); +print( "Copyright (c) 1996-2006, Valve LLC, All rights reserved.\n" ); + +my $filename = $ARGV[0]; +my $numArgs = 1; +my @lines = (); +my @deflines = (); + +if ( $ARGV[0] =~ /-check$/i ) +{ + $numArgs = 3; + $check = 1; + $filename = $ARGV[1]; + $defname = $ARGV[2]; +} +elsif ( $ARGV[0] =~ /-checkauto/i ) +{ + $defname = $ARGV[1]; + $check = 2; +} + +if ( @ARGV < $numArgs ) +{ + print( "ERROR: Missing filename(s)\n" ); + exit 1; +} + +if ( $check == 1 ) +{ + # swap filenames if necessary + if ( $filename =~ /.def/ ) + { + my $temp = $filename; + $filename = $defname; + $defname = $temp; + } + + # validate extensions + unless ( $filename =~ /.map/ && $defname =~ /.def/ ) + { + print( "ERROR: Invalid file extensions. -check requires a .map file and a .def file.\n" ); + exit 1; + } + + # read in the def file + if ( open(INFILE, "$defname" ) ) + { + @deflines = <INFILE>; + close( INFILE ); + } + else + { + print( "ERROR: Couldn't open file $defname.\n" ); + exit 1; + } +} +elsif ( $check == 2 ) +{ + # read in the def file + if ( open(INFILE, "$defname" ) ) + { + @deflines = <INFILE>; + close( INFILE ); + } + else + { + print( "ERROR: Couldn't open file $defname.\n" ); + exit 1; + } + + # validate that the first export is CreateInterface* + # validate that the export ordinals are sequential and ordered + + my $line; + my $start = false; + my $idx = 1; + for ( @deflines ) + { + $line = $_; + + if ( $line =~ /@(\d+)[ |\n]/ ) + { + if ( $1 == 1 ) + { + unless ( $line =~ /CreateInterface/ ) + { + # first export must be CreateInterface* + $line =~ /\s+([\S]*)/; + + print( "**************************************************\n" ); + print( " ERROR: First export must be CreateInterface*. \n" ); + print( " Export \"", $1, "\" found instead! \n" ); + print( " This is a FATAL ERROR with the def file. \n" ); + print( " Please contact an Xbox 360 engineer immediately.\n" ); + print( "**************************************************\n" ); + exit 1; + } + } + + if ( $1 != $idx ) + { + # exports are out of order + print( "**************************************************\n" ); + print( " ERROR: Def file exports are not sequential \n" ); + print( " This may cause unexpected behavior at runtime. \n" ); + print( " Please contact an Xbox 360 engineer immediately.\n" ); + print( "**************************************************\n" ); + exit 1; + } + + ++$idx; + } + } + + exit 0; +} + +# Get the base name + +$filename =~ /(\w+(\.360)?).map/; +my $basename = $1; + +# Read in the source file + +if ( open(INFILE, "$filename" ) ) +{ + @lines = <INFILE>; + close( INFILE ); +} +else +{ + print( "ERROR: Couldn't open file $filename.\n" ); + exit 1; +} + +# Delete the lines up to the exports section + +my $len = 0; +my $exportsFound = 0; +for( @lines ) +{ + $len++; + if( /^ Exports$/ ) + { + splice( @lines, 0, $len+3 ); + $exportsFound = 1; + } +} + +if ( $exportsFound == 0 ) +{ + print( "ERROR: No Exports section found in $filename. " ); + print( "Relink the project with 'Map Exports' enabled.\n" ); + exit 1; +} + +if ( $check == 1 ) +{ + # Check for exports in the map that aren't in the def + print( "make360def: Comparing $filename and $defname\n" ); + + # strip the first 2 lines from the def + splice( @deflines, 0, 2 ); + + my $defEntryCt = $#deflines + 1; + my $defMatches = 0; + + # for each line in the map + for( @lines ) + { + my $found = 0; + + # Pull the export name from the map line + + my $mapline; + if ( /(\d+)\s+(\S+)/ ) + { + $mapline = $2; + } + else + { + # ignore this line + next; + } + + # for each line in the def + for( @deflines ) + { + /(\S+)/; + + if ( $1 =~ /^\Q$mapline\E$/ ) + { + $found = 1; + $defMatches++; + last; + } + } + + if ( $found == 0 ) + { + print( "ERROR: New export found in $filename, " ); + print( "so the map file and def file are out of sync. " ); + print( "You must relink the project to generate a new def file.\n" ); + exit 1; + } + } + + # Make sure all the def lines were matched + if ( $defMatches != $defEntryCt ) + { + print( "ERROR: An export was removed from $filename, " ); + print( "so the map file and def file are out of sync. " ); + print( "You must relink the project to generate a new def file.\n" ); + exit 1; + } + + print( "make360def: Comparison complete, files match.\n" ); + exit 0; +} + +# start the def file + +print( "make360def: Generating $basename.def\n" ); + +push( @output, "LIBRARY\t$basename.dll\n" ); +push( @output, "EXPORTS\n" ); + +# process each line in the export section + +my $interfacePrefix = "0000000000"; +for( @lines ) +{ + if ( /(\d+)\s+(\S+)/ ) + { + my $func = $2; + if ( $func =~ /CreateInterface/ ) + { + # Force createInterface to sort first + $func = join( '', $interfacePrefix, $func ); + } + + push( @baselist, $func ); + } +} + +# sort the list +my @sortedlist = sort {uc($a) cmp uc($b)} @baselist; +#my @sortedlist = @baselist; + +my $ordinal = 1; +for( @sortedlist ) +{ + my $func = $_; + if ( /$interfacePrefix(.*)/ ) + { + # Strip the added characters + $func = $1; + } + + push( @output, "\t$func\t" ); + Add_Tabs( $func ); + push( @output, "\@$ordinal\n" ); + $ordinal++; +} + +# write the def file + +print( "make360def: Saving $basename.def.\n" ); + +open ( OUTFILE, ">$basename.def" ); +print OUTFILE @output; +close ( OUTFILE ); + +print( "make360def: Finished.\n" ); + +exit 0; |