uid issue

This commit is contained in:
KittenPopo
2021-07-24 21:11:47 -07:00
commit c2130ba4e9
13850 changed files with 6241419 additions and 0 deletions

BIN
devtools/bin.zip Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,22 @@
use File::DosGlob;
@ARGV = map {
my @g = File::DosGlob::glob($_) if /[*?]/;
@g ? @g : $_;
} @ARGV;
open FILE, ">__tmpshaderlist.txt";
foreach $arg (@ARGV)
{
if( $arg =~ m/\.fxc$/i || $arg =~ m/\.vsh$/i || $arg =~ m/\.psh$/i )
{
print $arg . "\n";
print FILE $arg . "\n";
}
}
close FILE;
system "buildshaders.bat __tmpshaderlist";
unlink "__tmpshaderlist.txt";

View File

@ -0,0 +1,116 @@
use String::CRC32;
BEGIN {use File::Basename; push @INC, dirname($0); }
require "valve_perl_helpers.pl";
sub GetShaderType
{
my $shadername = shift;
my $shadertype;
if( $shadername =~ m/\.vsh/i )
{
$shadertype = "vsh";
}
elsif( $shadername =~ m/\.psh/i )
{
$shadertype = "psh";
}
elsif( $shadername =~ m/\.fxc/i )
{
$shadertype = "fxc";
}
else
{
die;
}
return $shadertype;
}
sub GetShaderSrc
{
my $shadername = shift;
if ( $shadername =~ m/^(.*)-----/i )
{
return $1;
}
else
{
return $shadername;
}
}
sub GetShaderType
{
my $shadername = shift;
my $shadertype;
if( $shadername =~ m/\.vsh/i )
{
$shadertype = "vsh";
}
elsif( $shadername =~ m/\.psh/i )
{
$shadertype = "psh";
}
elsif( $shadername =~ m/\.fxc/i )
{
$shadertype = "fxc";
}
else
{
die;
}
return $shadertype;
}
sub GetShaderBase
{
my $shadername = shift;
if ( $shadername =~ m/-----(.*)$/i )
{
return $1;
}
else
{
my $shadertype = &GetShaderType( $shadername );
$shadername =~ s/\.$shadertype//i;
return $shadername;
}
}
$g_x360 = 0;
$g_vcsext = ".vcs";
while( 1 )
{
$inputbase = shift;
if( $inputbase =~ m/-x360/ )
{
$g_x360 = 1;
$g_vcsext = ".360.vcs";
}
else
{
last;
}
}
# rip the txt off the end if it's there.
$inputbase =~ s/\.txt//i;
my @srcfiles = &LoadShaderListFile( $inputbase );
foreach $srcfile ( @srcfiles )
{
my $shadertype = &GetShaderType( $srcfile );
my $shaderbase = &GetShaderBase( $srcfile );
my $shadersrc = &GetShaderSrc( $srcfile );
my $vcsFileName = "..\\..\\..\\game\\platform\\shaders\\$shadertype\\$shaderbase" . $g_vcsext;
# print "shadersrc: $shadersrc vcsFileName: $vcsFileName\n";
if( $g_x360 && ( $shaderbase =~ m/_ps20$/i ) )
{
next; # skip _ps20 files for 360
}
&CheckCRCAgainstTarget( $shadersrc, $vcsFileName, 1 );
}

View File

@ -0,0 +1,92 @@
BEGIN {use File::Basename; push @INC, dirname($0); }
require "valve_perl_helpers.pl";
use Cwd;
use String::CRC32;
my $txtfilename = shift;
my $arg = shift;
my $is360 = 0;
my $platformextension = "";
if( $arg =~ m/-x360/i )
{
$is360 = 1;
$platformextension = ".360";
}
# Get the changelist number for the Shader Auto Checkout changelist. Will create the changelist if it doesn't exist.
my $changelistnumber = `valve_p4_create_changelist.cmd ..\\..\\..\\game\\platform\\shaders \"Shader Auto Checkout VCS\"`;
# Get rid of the newline
$changelistnumber =~ s/\n//g;
my $changelistarg = "";
if( $changelistnumber != 0 )
{
$changelistarg = "-c $changelistnumber"
}
open TXTFILE, "<$txtfilename";
my $src;
my $dst;
while( $src = <TXTFILE> )
{
# get rid of comments
$src =~ s,//.*,,g;
# skip blank lines
if( $src =~ m/^\s*$/ )
{
next;
}
# Get rid of newlines.
$src =~ s/\n//g;
# Save off the shader source filename.
my $dst = $src;
$dst =~ s/_tmp//gi;
# Does the dst exist?
my $dstexists = -e $dst;
my $srcexists = -e $src;
# What are the time stamps for the src and dst?
my $srcmodtime = ( stat $src )[9];
my $dstmodtime = ( stat $dst )[9];
if( $dstexists && !$srcexists )
{
printf STDERR "$src doesn't exist, deleting $dst\n";
unlink $dst;
}
# Open for edit or add if different than what is in perforce already.
if( !$dstexists || ( $srcmodtime != $dstmodtime ) )
{
# Make the target writable if it exists
if( $dstexists )
{
MakeFileWritable( $dst );
}
my $dir = $dst;
$dir =~ s,([^/\\]*$),,; # rip the filename off the end
my $filename = $1;
# create the target directory if it doesn't exist
if( !$dstexists )
{
&MakeDirHier( $dir, 0777 );
}
# copy the file to its targets. . . we want to see STDERR here if there is an error.
my $cmd = "copy $src $dst > nul";
# print STDERR "$cmd\n";
system $cmd;
MakeFileReadOnly( $dst );
}
}
close TXTFILE;

179
devtools/bin/copyshaders.pl Normal file
View File

@ -0,0 +1,179 @@
BEGIN {use File::Basename; push @INC, dirname($0); }
require "valve_perl_helpers.pl";
use Cwd;
use String::CRC32;
sub ReadInputFileWithIncludes
{
local( $filename ) = shift;
local( *INPUT );
local( $output );
open INPUT, "<$filename" || die;
local( $line );
local( $linenum ) = 1;
while( $line = <INPUT> )
{
if( $line =~ m/\#include\s+\"(.*)\"/i )
{
$output.= ReadInputFileWithIncludes( $1 );
}
else
{
$output .= $line;
}
}
close INPUT;
return $output;
}
sub PatchCRC
{
my $filename = shift;
my $crc = shift;
# print STDERR "*** PatchCRC( $filename, $crc )\n";
local( *FP );
open FP, "+<$filename" || die;
binmode( FP );
seek FP, 6 * 4, 0;
my $uInt = "I";
if ( ( $filename =~ m/\.ps3\./ ) || ( $filename =~ m/\.360\./ ) )
{
# print STDERR "*** PatchCRC found ps3 or 360\n";
$uInt = "N";
}
print FP pack $uInt, $crc;
close FP;
}
my $txtfilename = shift;
my $arg = shift;
my $is360 = 0;
my $isPS3 = 0;
my $platformextension = "";
if( $arg =~ m/-x360/i )
{
$is360 = 1;
$platformextension = ".360";
}
elsif( $arg =~ m/-ps3/i )
{
$isPS3 = 1;
$platformextension = ".ps3";
}
# Get the changelist number for the Shader Auto Checkout changelist. Will create the changelist if it doesn't exist.
my $changelistnumber = `valve_p4_create_changelist.cmd ..\\..\\..\\game\\platform\\shaders \"Shader Auto Checkout VCS\"`;
# Get rid of the newline
$changelistnumber =~ s/\n//g;
my $changelistarg = "";
if( $changelistnumber != 0 )
{
$changelistarg = "-c $changelistnumber"
}
open TXTFILE, "<$txtfilename";
my $src;
my $dst;
while( $src = <TXTFILE> )
{
# get rid of comments
$src =~ s,//.*,,g;
# skip blank lines
if( $src =~ m/^\s*$/ )
{
next;
}
# Get rid of newlines.
$src =~ s/\n//g;
# Save off the shader source filename.
my $shadersrcfilename = $src;
$shadersrcfilename =~ s/-----.*$//;
# use only target basename.
$src =~ s/^.*-----//;
# where the binary vcs file is
my $spath = "";
if ( $shadersrcfilename =~ m@\.fxc@i )
{
$spath = "shaders\\fxc\\";
}
if ( $shadersrcfilename =~ m@\.vsh@i )
{
$spath = "shaders\\vsh\\";
}
if ( $shadersrcfilename =~ m@\.psh@i )
{
$spath = "shaders\\psh\\";
}
# make the source have path and extension
$src = $spath . $src . $platformextension . ".vcs";
# build the dest filename.
$dst = $src;
$dst =~ s/shaders\\/..\\..\\..\\game\\platform\\shaders\\/i;
# Does the dst exist?
my $dstexists = -e $dst;
my $srcexists = -e $src;
# What are the time stamps for the src and dst?
my $srcmodtime = ( stat $src )[9];
my $dstmodtime = ( stat $dst )[9];
# Write $dst to a file so that we can do perforce stuff to it later.
local( *VCSLIST );
open VCSLIST, ">>vcslist.txt" || die;
print VCSLIST $dst . "\n";
close VCSLIST;
# Open for edit or add if different than what is in perforce already.
if( !$dstexists || ( $srcmodtime != $dstmodtime ) )
{
if ( $srcexists && $shadersrcfilename =~ m@\.fxc@i )
{
# Get the CRC for the source file.
my $srccode = ReadInputFileWithIncludes( $shadersrcfilename );
my $crc = crc32( $srccode );
# Patch the source VCS file with the CRC32 of the source code used to build that file.
PatchCRC( $src, $crc );
}
# Make the target vcs writable if it exists
if( $dstexists )
{
MakeFileWritable( $dst );
}
my $dir = $dst;
$dir =~ s,([^/\\]*$),,; # rip the filename off the end
my $filename = $1;
# create the target directory if it doesn't exist
if( !$dstexists )
{
&MakeDirHier( $dir, 0777 );
}
# copy the file to its targets. . . we want to see STDERR here if there is an error.
my $cmd = "copy $src $dst > nul";
# print STDERR "$cmd\n";
system $cmd;
MakeFileReadOnly( $dst );
}
}
close TXTFILE;

View File

@ -0,0 +1,110 @@
#!perl
use File::Find;
&BuildRemapTable;
find(\&convert, "." );
sub convert
{
return unless (/\.pcf$/i);
return if (/^tmp\.pcf$/i);
return if (/^tmp2\.pcf$/i);
return if (/360\.pcf$/i);
print STDERR "process ", $File::Find::name," ($_) dir=",`cd`," \n";
my $fname=$_;
print `p4 edit $fname`;
print `dmxconvert -i $_ -o tmp.pcf -oe keyvalues2`;
open(TMP, "tmp.pcf" ) || return;
open(OUT, ">tmp2.pcf" ) || die;
while(<TMP>)
{
s/[\n\r]//g;
if ( (/^(\s*\"functionName\"\s*\"string\"\s*\")(.*)\"(.*)$/) &&
length($map{$2}) )
{
$_=$1.$map{$2}.'"'.$3;
}
if ( (/^(\s*\"name\"\s*\"string\"\s*\")(.*)\"(.*)$/) &&
length($map{$2}) )
{
$_=$1.$map{$2}.'"'.$3;
}
print OUT "$_\n";
}
close OUT;
close TMP;
print `dmxconvert -i tmp2.pcf -o $fname -ie keyvalues2 -oe binary`;
unlink "tmp.pcf";
unlink "tmp2.pcf";
}
sub BuildRemapTable
{
$map{"alpha_fade"}= "Alpha Fade and Decay";
$map{"alpha_fade_in_random"}= "Alpha Fade In Random";
$map{"alpha_fade_out_random"}= "Alpha Fade Out Random";
$map{"basic_movement"}= "Movement Basic";
$map{"color_fade"}= "Color Fade";
$map{"controlpoint_light"}= "Color Light From Control Point";
$map{"Dampen Movement Relative to Control Point"}= "Movement Dampen Relative to Control Point";
$map{"Distance Between Control Points Scale"}= "Remap Distance Between Two Control Points to Scalar";
$map{"Distance to Control Points Scale"}= "Remap Distance to Control Point to Scalar";
$map{"lifespan_decay"}= "Lifespan Decay";
$map{"lock to bone"}= "Movement Lock to Bone";
$map{"postion_lock_to_controlpoint"}= "Movement Lock to Control Point";
$map{"maintain position along path"}= "Movement Maintain Position Along Path";
$map{"Match Particle Velocities"}= "Movement Match Particle Velocities";
$map{"Max Velocity"}= "Movement Max Velocity";
$map{"noise"}= "Noise Scalar";
$map{"vector noise"}= "Noise Vector";
$map{"oscillate_scalar"}= "Oscillate Scalar";
$map{"oscillate_vector"}= "Oscillate Vector";
$map{"Orient Rotation to 2D Direction"}= "Rotation Orient to 2D Direction";
$map{"radius_scale"}= "Radius Scale";
$map{"Random Cull"}= "Cull Random";
$map{"remap_scalar"}= "Remap Scalar";
$map{"rotation_movement"}= "Rotation Basic";
$map{"rotation_spin"}= "Rotation Spin Roll";
$map{"rotation_spin yaw"}= "Rotation Spin Yaw";
$map{"alpha_random"}= "Alpha Random";
$map{"color_random"}= "Color Random";
$map{"create from parent particles"}= "Position From Parent Particles";
$map{"Create In Hierarchy"}= "Position In CP Hierarchy";
$map{"random position along path"}= "Position Along Path Random";
$map{"random position on model"}= "Position on Model Random";
$map{"sequential position along path"}= "Position Along Path Sequential";
$map{"position_offset_random"}= "Position Modify Offset Random";
$map{"position_warp_random"}= "Position Modify Warp Random";
$map{"position_within_box"}= "Position Within Box Random";
$map{"position_within_sphere"}= "Position Within Sphere Random";
$map{"Inherit Velocity"}= "Velocity Inherit from Control Point";
$map{"Initial Repulsion Velocity"}= "Velocity Repulse from World";
$map{"Initial Velocity Noise"}= "Velocity Noise";
$map{"Initial Scalar Noise"}= "Remap Noise to Scalar";
$map{"Lifespan from distance to world"}= "Lifetime from Time to Impact";
$map{"Pre-Age Noise"}= "Lifetime Pre-Age Noise";
$map{"lifetime_random"}= "Lifetime Random";
$map{"radius_random"}= "Radius Random";
$map{"random yaw"}= "Rotation Yaw Random";
$map{"Randomly Flip Yaw"}= "Rotation Yaw Flip Random";
$map{"rotation_random"}= "Rotation Random";
$map{"rotation_speed_random"}= "Rotation Speed Random";
$map{"sequence_random"}= "Sequence Random";
$map{"second_sequence_random"}= "Sequence Two Random";
$map{"trail_length_random"}= "Trail Length Random";
$map{"velocity_random"}= "Velocity Random";
}

1185
devtools/bin/fxc_prep.pl Normal file

File diff suppressed because it is too large Load Diff

BIN
devtools/bin/linux/ccache Normal file

Binary file not shown.

BIN
devtools/bin/linux/vpc Normal file

Binary file not shown.

BIN
devtools/bin/osx/vpc Normal file

Binary file not shown.

View File

@ -0,0 +1,96 @@
#!/usr/bin/env python
import datetime
import getopt
import glob
import os
import pickle
import shutil
import sys
import zipfile
import re
import subprocess as sp
import pdb
def ShowUsage():
print "breakpad_build_symbols.py [options] bindirectory symboldirectory]"
print "-f/--force Force rebuild of .sym files."
#
# Set program defaults.
#
g_bForce = False
def main():
global g_bForce
try:
opts, args = getopt.getopt( sys.argv[1:], "f", [ "force" ] )
except getopt.GetoptError, e:
print ""
print "Argument error: ", e
print ""
ShowUsage()
sys.exit(1)
for o, a in opts:
if o in ( "-f", "--force" ):
g_bForce = True
# now look for all files in the specified path
print "building symbols for %s to %s" % ( args[ 0 ], args[ 1 ] )
dump_syms = os.getcwd() + "/dump_syms"
rebuildcount = 0
visitcount = 0
for root, dirs, files in os.walk(args[ 0 ]):
for name in dirs:
dsymdirname = os.path.join(root, name)
#print "checking %s" % dsymdirname
if dsymdirname[-5:] == '.dSYM':
visitcount += 1
dylibfiletime = os.path.getmtime( dsymdirname )
# get the first line
command = dump_syms + " -g " + dsymdirname
p = sp.Popen( command, stdout=sp.PIPE, stderr=sp.PIPE, shell=True )
firstline = p.communicate()[ 0 ];
#line syntax
# MODULE mac x86 59C9A56A5EB38C85A185BA60877C89610 engine.dylib
tokens = firstline.split()
if ( len( tokens ) != 5 ):
continue
rawlibname = tokens[ 4 ]
# print "shortname %s\n" % rawlibname
symdir = args[1] + "/" + tokens[ 4 ] + "/" + tokens[ 3 ]
if not os.path.isdir( symdir ):
os.makedirs( symdir )
symfile = symdir + "/" + rawlibname + ".sym"
if ( os.path.exists( symfile ) ):
# check time stamp
symfilefiletime = os.path.getmtime( symfile )
symfilesize = os.path.getsize( symfile )
# print " %s %d %d" % (symfile, dylibfiletime, symfilefiletime)
if ( symfilefiletime >= dylibfiletime and not g_bForce and symfilesize > 0 ):
continue
# do full processing
command = dump_syms + " " + dsymdirname
p = sp.Popen( command, stdout=sp.PIPE, stderr=sp.PIPE, shell=True )
symbols = p.communicate()[ 0 ]
print " :%s" % symfile
# print " %s" % symbols
fd = open( symfile, 'wb' )
fd.write( symbols )
fd.close()
# force time stamp
os.utime( symfile, ( dylibfiletime, dylibfiletime ) )
rebuildcount += 1
print " rebuilt %d out of %d symbol files" % ( rebuildcount, visitcount )
if __name__ == '__main__':
main()

View File

@ -0,0 +1,10 @@
#!/bin/bash
# rm -rf /tmp/symbols/
./breakpad_build_symbols.py ~/Perforce/perforce_1666/yahn_mac/Steam/main/src/ /tmp/symbols
./breakpad_build_symbols.py ~/Perforce/perforce_1666/yahn_mac/Steam/main/client/osx32/ /tmp/symbols
#./breakpad_build_symbols.py ~/Perforce/perforce_1666/yahn_mac/Steam/main/client/ /tmp/symbols
#./breakpad_build_symbols.py ~/Perforce/perforce_1666/yahn_staging/game/ /tmp/symbols
./breakpad_build_symbols.py ~/Perforce/perforce_1666/yahn_staging/src/ /tmp/symbols
rsync -r /tmp/symbols/ socorro-test:./symbols

BIN
devtools/bin/osx32/ccache Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,3 @@
#!/bin/bash
exec $(dirname $0)/ccache ${DT_TOOLCHAIN_DIR}/usr/bin/clang -Qunused-arguments $@

View File

@ -0,0 +1,294 @@
#!perl
use strict;
BEGIN {use File::Basename; push @INC, dirname($0); }
require "valve_perl_helpers.pl";
sub PrintCleanPerforceOutput
{
my $line;
while( $line = shift )
{
if( $line =~ m/currently opened/i )
{
next;
}
if( $line =~ m/already opened for edit/i )
{
next;
}
if( $line =~ m/also opened/i )
{
next;
}
if( $line =~ m/add of existing file/i )
{
next;
}
print $line;
}
}
# HACK!!!! Need to pass something in to do this rather than hard coding.
sub NormalizePerforceFilename
{
my $line = shift;
# remove newlines.
$line =~ s/\n//;
# downcase.
$line =~ tr/[A-Z]/[a-z]/;
# backslash to forwardslash
$line =~ s,\\,/,g;
# for inc files HACK!
$line =~ s/^.*(fxctmp9.*)/$1/i;
$line =~ s/^.*(vshtmp9.*)/$1/i;
# for vcs files. HACK!
$line =~ s,^.*game/platform/shaders/,,i;
return $line;
}
# COMMAND-LINE ARGUMENTS
my $x360 = 0;
my $ps3 = 0;
my $filename = shift;
if( $filename =~ m/-x360/i )
{
$x360 = 1;
$filename = shift;
}
elsif( $filename =~ m/-ps3/i )
{
$ps3 = 1;
$filename = shift;
}
my $changelistname = shift;
my $perforcebasepath = shift;
my $diffpath = join " ", @ARGV;
#print STDERR "\$filename: $filename\n";
#print STDERR "\$changelistname: $changelistname\n";
#print STDERR "\$perforcebasepath: $perforcebasepath\n";
#print STDERR "\$diffpath: $diffpath\n";
# Read the input file list before changing to the perforce directory.
open FILELIST, "<$filename";
my @inclist = <FILELIST>;
close FILELIST;
# change from the perforce directory so that our client will be correct from here out.
#print STDERR "chdir $perforcebasepath\n";
chdir $perforcebasepath || die "can't cd to $perforcebasepath";
#print "inclist before @inclist\n";
# get rid of newlines and fix slashes
@inclist =
map
{
$_ =~ s,_tmp,,g; # remove _tmp so that we check out in the proper directory
$_ =~ s,\\,/,g; # backslash to forwardslash
$_ =~ s/\n//g; # remove newlines
$_ =~ tr/[A-Z]/[a-z]/; # downcase
# $_ =~ s,.*platform/shaders/,,i;
# $_ =~ s,$perforcebasepath/,,i;
$_ =~ s,../../../game/platform/shaders/,,i; # hack. . .really want something here that works generically.
$_
} @inclist;
#print "inclist after @inclist\n";
my $prevline;
my @outlist;
foreach $_ ( sort( @inclist ) )
{
next if( defined( $prevline ) && $_ eq $prevline );
$prevline = $_;
push @outlist, $_;
}
@inclist = @outlist;
#print "\@inclist: @inclist\n";
# Get list of files on the client
# -sl Every unopened file, along with the status of
# 'same, 'diff', or 'missing' as compared to its
# revision in the depot.
my @unopenedlist = &RunCommand( "p4 diff -sl $diffpath" );
#print "\@unopenedlist: @unopenedlist\n";
my %sameunopened;
my %diffunopened;
my %missingunopened;
my $line;
foreach $line ( @unopenedlist )
{
my $same = 0;
my $diff = 0;
my $missing = 0;
if( $line =~ s/^same //i )
{
$same = 1;
}
elsif( $line =~ s/^diff //i )
{
$diff = 1;
}
elsif( $line =~ s/^missing //i )
{
$missing = 1;
}
else
{
die "checkoutincfiles.pl don't understand p4 diff -sl results: $line\n";
}
# clean up the filename
# print "before: $line\n" if $line =~ m/aftershock_vs20/i;
$line = NormalizePerforceFilename( $line );
# print "after: \"$line\"\n" if $line =~ m/aftershock_vs20/i;
# if( $line =~ m/aftershock/i )
# {
# print "unopenedlist: $line same: $same diff: $diff missing: $missing\n";
# }
# Save off the results for each line so that we can query them later.
if( $same )
{
$sameunopened{$line} = 1;
}
elsif( $diff )
{
$diffunopened{$line} = 1;
}
elsif( $missing )
{
$missingunopened{$line} = 1;
}
else
{
die;
}
}
# -sr Opened files that are the same as the revision in the
# depot.
my @openedbutsame = &RunCommand( "p4 diff -sr $diffpath" );
my %sameopened;
foreach $line ( @openedbutsame )
{
if( $line =~ m/not opened on this client/i )
{
next;
}
# clean up the filename
# print "before: $line\n" if $line =~ m/aftershock_vs20/i;
$line = NormalizePerforceFilename( $line );
# print "after: $line\n" if $line =~ m/aftershock_vs20/i;
# if( $line =~ m/aftershock/i )
# {
# print STDERR "sameopened: $line\n";
# }
$sameopened{$line} = 1;
}
my @sameunopened;
my @revert;
my @edit;
my @add;
foreach $line ( @inclist )
{
if( defined( $sameunopened{$line} ) )
{
push @sameunopened, $line;
}
elsif( defined( $sameopened{$line} ) )
{
push @revert, $line;
}
elsif( defined( $diffunopened{$line} ) )
{
push @edit, $line;
}
elsif( defined( $missingunopened{$line} ) )
{
printf STDERR "p4autocheckout.pl: $line missing\n";
}
else
{
push @add, $line;
}
}
#print "\@sameunopened = @sameunopened\n";
#print "\@revert = @revert\n";
#print "\@edit = @edit\n";
#print "\@add = @add\n";
# Get the changelist number for the named changelist if we are actually going to edit or add anything.
# We don't need it for deleting.
my $changelistarg = "";
# Get the changelist number for the Shader Auto Checkout changelist. Will create the changelist if it doesn't exist.
my $changelistnumber = `valve_p4_create_changelist.cmd . \"$changelistname\"`;
# Get rid of the newline
$changelistnumber =~ s/\n//g;
#print STDERR "changelistnumber: $changelistnumber\n";
if( $changelistnumber != 0 )
{
$changelistarg = "-c $changelistnumber"
}
#my %sameunopened;
#my %diffunopened;
#my %missingunopened;
#my %sameopened;
if( scalar @edit )
{
while( scalar @edit )
{
# Grab 10 files at a time so that we don't blow cmd.exe line limits.
my @files = splice @edit, 0, 10;
my $cmd = "p4 edit $changelistarg @files";
# print STDERR $cmd . "\n";
my @results = &RunCommand( $cmd );
# print STDERR @results;
&PrintCleanPerforceOutput( @results );
}
}
if( scalar @revert )
{
while( scalar @revert )
{
# Grab 10 files at a time so that we don't blow cmd.exe line limits.
my @files = splice @revert, 0, 10;
my $cmd = "p4 revert @files";
# print STDERR $cmd . "\n";
my @results = &RunCommand( $cmd );
&PrintCleanPerforceOutput( @results );
}
}
if( scalar @add )
{
while( scalar @add )
{
# Grab 10 files at a time so that we don't blow cmd.exe line limits.
my @files = splice @add, 0, 10;
my $cmd = "p4 add $changelistarg @files";
# print STDERR $cmd . "\n";
my @results = &RunCommand( $cmd );
# print STDERR "@results\n";
&PrintCleanPerforceOutput( @results );
}
}

View File

@ -0,0 +1,129 @@
use strict;
BEGIN {use File::Basename; push @INC, dirname($0); }
require "valve_perl_helpers.pl";
my $dynamic_compile = defined $ENV{"dynamic_shaders"} && $ENV{"dynamic_shaders"} != 0;
# ----------------------------------------------
# COMMAND-LINE ARGS
# ----------------------------------------------
my $g_x360 = 0;
my $g_ps3 = 0;
my $g_tmpfolder = "";
my $g_vcsext = ".vcs";
my $g_SrcDir = ".";
my $inputbase;
my $g_SourceDir;
while( 1 )
{
$inputbase = shift;
if( $inputbase =~ m/-source/ )
{
$g_SourceDir = shift;
}
elsif( $inputbase =~ m/-x360/ )
{
$g_x360 = 1;
$g_tmpfolder = "_360";
$g_vcsext = ".360.vcs";
}
elsif( $inputbase =~ m/-ps3/ )
{
$g_ps3 = 1;
$g_tmpfolder = "_ps3";
$g_vcsext = ".ps3.vcs";
}
else
{
last;
}
}
# ----------------------------------------------
# Load the list of shaders that we care about.
# ----------------------------------------------
my @srcfiles = &LoadShaderListFile( $inputbase );
my %incHash;
my %vcsHash;
my $shader;
foreach $shader ( @srcfiles )
{
my $shadertype = &LoadShaderListFile_GetShaderType( $shader );
my $shaderbase = &LoadShaderListFile_GetShaderBase( $shader );
my $shadersrc = &LoadShaderListFile_GetShaderSrc( $shader );
if( $shadertype eq "fxc" || $shadertype eq "vsh" )
{
# We only generate inc files for fxc and vsh files.
my $incFileName = "$shadertype" . "tmp9" . $g_tmpfolder . "/" . $shaderbase . "\.inc";
$incFileName =~ tr/A-Z/a-z/;
$incHash{$incFileName} = 1;
}
my $vcsFileName = "$shadertype/$shaderbase" . $g_vcsext;
$vcsFileName =~ tr/A-Z/a-z/;
$vcsHash{$vcsFileName} = 1;
}
# ----------------------------------------------
# Get the list of inc files to consider for reverting
# ----------------------------------------------
sub RevertIntegratedFiles
{
my $path = shift;
my $fileHashRef = shift;
my $cmd = "p4 fstat $path";
my @fstat = &RunCommand( $cmd );
my $depotFile;
my $action;
my @openedforintegrate;
my $line;
foreach $line ( @fstat )
{
if( $line =~ m,depotFile (.*)\n, )
{
$depotFile = &NormalizePerforceFilename( $1 );
}
elsif( $line =~ m,action (.*)\n, )
{
$action = $1;
}
elsif( $line =~ m,^\s*$, )
{
if( defined $action && defined $fileHashRef->{$depotFile} && $action =~ m/integrate/i )
{
push @openedforintegrate, $depotFile;
}
undef $depotFile;
undef $action;
}
}
if( scalar( @openedforintegrate ) )
{
my $cmd = "p4 revert @openedforintegrate";
# print "$cmd\n";
my @revertOutput = &RunCommand( $cmd );
&PrintCleanPerforceOutput( @revertOutput );
}
}
my $path = "vshtmp9" . $g_tmpfolder . "/... fxctmp9" . $g_tmpfolder . "/...";
&RevertIntegratedFiles( $path, \%incHash );
if( !$dynamic_compile )
{
&MakeDirHier( "../../../game/platform/shaders" );
# Might be in a different client for the vcs files, so chdir to the correct place.
chdir "../../../game/platform/shaders" || die;
my $path = "...";
&RevertIntegratedFiles( $path, \%vcsHash );
}

333
devtools/bin/psh_prep.pl Normal file
View File

@ -0,0 +1,333 @@
use String::CRC32;
BEGIN {use File::Basename; push @INC, dirname($0); }
require "valve_perl_helpers.pl";
sub BuildDefineOptions
{
local( $output );
local( $combo ) = shift;
local( $i );
for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
{
local( $val ) = ( $combo % ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 ) ) + $dynamicDefineMin[$i];
$output .= "/D$dynamicDefineNames[$i]=$val ";
$combo = $combo / ( $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1 );
}
for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
{
local( $val ) = ( $combo % ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 ) ) + $staticDefineMin[$i];
$output .= "/D$staticDefineNames[$i]=$val ";
$combo = $combo / ( $staticDefineMax[$i] - $staticDefineMin[$i] + 1 );
}
return $output;
}
sub CalcNumCombos
{
local( $i, $numCombos );
$numCombos = 1;
for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
{
$numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
}
for( $i = 0; $i < scalar( @staticDefineNames ); $i++ )
{
$numCombos *= $staticDefineMax[$i] - $staticDefineMin[$i] + 1;
}
return $numCombos;
}
sub CalcNumDynamicCombos
{
local( $i, $numCombos );
$numCombos = 1;
for( $i = 0; $i < scalar( @dynamicDefineNames ); $i++ )
{
$numCombos *= $dynamicDefineMax[$i] - $dynamicDefineMin[$i] + 1;
}
return $numCombos;
}
$g_dx9 = 1;
while( 1 )
{
$psh_filename = shift;
if( $psh_filename =~ m/-source/ )
{
$g_SourceDir = shift;
}
elsif( $psh_filename =~ m/-x360/ )
{
$g_x360 = 1;
}
else
{
last;
}
}
$psh_filename =~ s/-----.*$//;
# Get the shader binary version number from a header file.
open FILE, "<$g_SourceDir\\public\\materialsystem\\shader_vcs_version.h" || die;
while( $line = <FILE> )
{
if( $line =~ m/^\#define\s+SHADER_VCS_VERSION_NUMBER\s+(\d+)\s*$/ )
{
$shaderVersion = $1;
last;
}
}
if( !defined $shaderVersion )
{
die "couldn't get shader version from shader_vcs_version.h";
}
close FILE;
local( @staticDefineNames );
local( @staticDefineMin );
local( @staticDefineMax );
local( @dynamicDefineNames );
local( @dynamicDefineMin );
local( @dynamicDefineMax );
# Parse the combos.
open PSH, "<$psh_filename";
while( <PSH> )
{
last if( !m,^;, );
s,^;\s*,,;
if( m/\s*STATIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ )
{
local( $name, $min, $max );
$name = $1;
$min = $2;
$max = $3;
# print "\"STATIC: $name\" \"$min..$max\"\n";
if (/\[(.*)\]/)
{
$platforms=$1;
next if ( ($g_x360) && (!($platforms=~/XBOX/i)) );
next if ( (!$g_x360) && (!($platforms=~/PC/i)) );
}
push @staticDefineNames, $name;
push @staticDefineMin, $min;
push @staticDefineMax, $max;
}
elsif( m/\s*DYNAMIC\s*\:\s*\"(.*)\"\s+\"(\d+)\.\.(\d+)\"/ )
{
local( $name, $min, $max );
$name = $1;
$min = $2;
$max = $3;
# print "\"DYNAMIC: $name\" \"$min..$max\"\n";
if (/\[(.*)\]/)
{
$platforms=$1;
next if ( ($g_x360) && (!($platforms=~/XBOX/i)) );
next if ( (!$g_x360) && (!($platforms=~/PC/i)) );
}
push @dynamicDefineNames, $name;
push @dynamicDefineMin, $min;
push @dynamicDefineMax, $max;
}
}
close PSH;
$numCombos = &CalcNumCombos();
$numDynamicCombos = &CalcNumDynamicCombos();
print "$psh_filename\n";
#print "$numCombos combos\n";
#print "$numDynamicCombos dynamic combos\n";
if( $g_x360 )
{
$pshtmp = "pshtmp9_360";
}
elsif( $g_dx9 )
{
$pshtmp = "pshtmp9";
}
else
{
$pshtmp = "pshtmp8";
}
$basename = $psh_filename;
$basename =~ s/\.psh$//i;
for( $shaderCombo = 0; $shaderCombo < $numCombos; $shaderCombo++ )
{
my $tempFilename = "shader$shaderCombo.o";
unlink $tempFilename;
if( $g_x360 )
{
$cmd = "psa /D_X360=1 /Foshader$shaderCombo.o /nologo " . &BuildDefineOptions( $shaderCombo ) . "$psh_filename > NIL";
}
else
{
$cmd = "$g_SourceDir\\dx9sdk\\utilities\\psa /Foshader$shaderCombo.o /nologo " . &BuildDefineOptions( $shaderCombo ) . "$psh_filename > NIL";
}
if( !stat $pshtmp )
{
mkdir $pshtmp, 0777 || die $!;
}
# print $cmd . "\n";
system $cmd || die $!;
# Make sure a file got generated because sometimes the die above won't happen on compile errors.
my $filesize = (stat $tempFilename)[7];
if ( !$filesize )
{
die "Error compiling shader$shaderCombo.o";
}
push @outputHeader, @hdr;
}
$basename =~ s/\.fxc//gi;
push @outputHeader, "static PrecompiledShaderByteCode_t " . $basename . "_pixel_shaders[" . $numCombos . "] = \n";
push @outputHeader, "{\n";
local( $j );
for( $j = 0; $j < $numCombos; $j++ )
{
local( $thing ) = "pixelShader_" . $basename . "_" . $j;
push @outputHeader, "\t{ " . "$thing, sizeof( $thing ) },\n";
}
push @outputHeader, "};\n";
push @outputHeader, "struct $basename" . "PixelShader_t : public PrecompiledShader_t\n";
push @outputHeader, "{\n";
push @outputHeader, "\t$basename" . "PixelShader_t()\n";
push @outputHeader, "\t{\n";
push @outputHeader, "\t\tm_nFlags = 0;\n";
push @outputHeader, "\t\tm_pByteCode = " . $basename . "_pixel_shaders;\n";
push @outputHeader, "\t\tm_nShaderCount = $numCombos;\n";
#push @outputHeader, "\t\tm_nDynamicCombos = m_nShaderCount;\n";
push @outputHeader, "\t\t// NOTE!!! psh_prep.pl shaders are always static combos!\n";
push @outputHeader, "\t\tm_nDynamicCombos = 1;\n";
push @outputHeader, "\t\tm_pName = \"$basename\";\n";
if( $basename =~ /vs\d\d/ ) # hack
{
push @outputHeader, "\t\tGetShaderDLL()->InsertPrecompiledShader( PRECOMPILED_VERTEX_SHADER, this );\n";
}
else
{
push @outputHeader, "\t\tGetShaderDLL()->InsertPrecompiledShader( PRECOMPILED_PIXEL_SHADER, this );\n";
}
push @outputHeader, "\t}\n";
push @outputHeader, "\tvirtual const PrecompiledShaderByteCode_t &GetByteCode( int shaderID )\n";
push @outputHeader, "\t{\n";
push @outputHeader, "\t\treturn m_pByteCode[shaderID];\n";
push @outputHeader, "\t}\n";
push @outputHeader, "};\n";
push @outputHeader, "static $basename" . "PixelShader_t $basename" . "_PixelShaderInstance;\n";
&MakeDirHier( "shaders/psh" );
my $vcsName = "";
if( $g_x360 )
{
$vcsName = $basename . ".360.vcs";
}
else
{
$vcsName = $basename . ".vcs";
}
open COMPILEDSHADER, ">shaders/psh/$vcsName" || die;
binmode( COMPILEDSHADER );
#
# Write out the part of the header that we know. . we'll write the rest after writing the object code.
#
#print $numCombos . "\n";
# Pack arguments
my $sInt = "i";
my $uInt = "I";
if ( $g_x360 )
{
# Change arguments to "big endian long"
$sInt = "N";
$uInt = "N";
}
open PSH, "<$psh_filename";
my $crc = crc32( *PSH );
close PSH;
#print STDERR "crc for $psh_filename: $crc\n";
# version
print COMPILEDSHADER pack $sInt, 4;
# totalCombos
print COMPILEDSHADER pack $sInt, $numCombos;
# dynamic combos
print COMPILEDSHADER pack $sInt, $numDynamicCombos;
# flags
print COMPILEDSHADER pack $uInt, 0x0; # nothing here for now.
# centroid mask
print COMPILEDSHADER pack $uInt, 0;
# reference size for diffs
print COMPILEDSHADER pack $uInt, 0;
# crc32 of the source code
print COMPILEDSHADER pack $uInt, $crc;
my $beginningOfDir = tell COMPILEDSHADER;
# Write out a blank directionary. . we'll fill it in later.
for( $i = 0; $i < $numCombos; $i++ )
{
# offset from beginning of file.
print COMPILEDSHADER pack $sInt, 0;
# size
print COMPILEDSHADER pack $sInt, 0;
}
my $startByteCode = tell COMPILEDSHADER;
my @byteCodeStart;
my @byteCodeSize;
# Write out the shader object code.
for( $shaderCombo = 0; $shaderCombo < $numCombos; $shaderCombo++ )
{
my $filename = "shader$shaderCombo\.o";
my $filesize = (stat $filename)[7];
$byteCodeStart[$shaderCombo] = tell COMPILEDSHADER;
$byteCodeSize[$shaderCombo] = $filesize;
open SHADERBYTECODE, "<$filename";
binmode SHADERBYTECODE;
my $bin;
my $numread = read SHADERBYTECODE, $bin, $filesize;
# print "filename: $filename numread: $numread filesize: $filesize\n";
close SHADERBYTECODE;
unlink $filename;
print COMPILEDSHADER $bin;
}
# Seek back to the directory and write it out.
seek COMPILEDSHADER, $beginningOfDir, 0;
for( $i = 0; $i < $numCombos; $i++ )
{
# offset from beginning of file.
print COMPILEDSHADER pack $sInt, $byteCodeStart[$i];
# size
print COMPILEDSHADER pack $sInt, $byteCodeSize[$i];
}
close COMPILEDSHADER;

View File

@ -0,0 +1,36 @@
#! perl
my $fname=shift || die "format is shaderinfo blah.vcs";
open(SHADER, $fname) || die "can't open $fname";
binmode SHADER;
read(SHADER,$header,20);
($ver,$ntotal,$ndynamic,$flags,$centroidmask)=unpack("LLLLL",$header);
#print "Version $ver total combos=$ntotal, num dynamic combos=$ndynamic,\n flags=$flags, centroid mask=$centroidmask\n";
read(SHADER,$refsize,4);
$refsize=unpack("L",$refsize);
#print "Size of reference shader for diffing=$refsize\n";
seek(SHADER,$refsize,1);
$nskipped_combos=0;
for(1..$ntotal)
{
read(SHADER,$combodata,8);
($ofs,$combosize)=unpack("LL",$combodata);
if ( $ofs == 0xffffffff)
{
$nskipped_combos++;
}
else
{
}
}
#print "$nskipped_combos skipped, for an actual total of ",$ntotal-$nskipped_combos,"\n";
#print "Real to skipped ratio = ",($ntotal-$nskipped_combos)/$ntotal,"\n";
# csv output - name, real combos, virtual combos, dynamic combos
my $real_combos=$ntotal-$nskipped_combos;
print "$fname,$real_combos,$ntotal,$ndynamic\n";

View File

@ -0,0 +1,54 @@
$infilename = shift;
$outfilename1 = shift;
$outfilename2 = shift;
open INPUT, $infilename || die;
@input = <INPUT>;
close INPUT;
open MERGEDMINE, ">$outfilename1" || die;
open MERGEDTHEIRS, ">$outfilename2" || die;
for( $i = 0; $i < scalar( @input ); $i++ )
{
$line = $input[$i];
if( $line =~ m/^(.*)<<<<<<</ )
{
$first = 1;
$second = 0;
print MERGEDMINE $1;
print MERGEDTHEIRS $1;
next;
}
# Make sure that we are in a split block so that comments with ======= don't mess us up.
if( $line =~ m/^(.*)=======$/ && $first == 1 )
{
$first = 0;
$second = 1;
print MERGEDMINE $1;
next;
}
if( $line =~ m/^(.*)>>>>>>>/ )
{
$first = $second = 0;
print MERGEDTHEIRS $1;
next;
}
if( $first )
{
print MERGEDMINE $line;
}
elsif( $second )
{
print MERGEDTHEIRS $line;
}
else
{
print MERGEDMINE $line;
print MERGEDTHEIRS $line;
}
}
close MERGEDMINE;
close MERGEDTHEIRS;

View File

@ -0,0 +1,15 @@
#!/usr/bin/env perl
open( HANDLE,shift) || die;
undef $/;
binmode HANDLE;
$data=<HANDLE>;
$ctr=0;
$out.=sprintf("static unsigned char %s[] = {\n ", shift);
for($i=0;$i<length($data);$i++)
{
$out.=sprintf("0x%02x,", unpack("C", substr($data,$i,1)) );
$out.="\n " if ( ( $ctr % 20) == 19);
$ctr++;
}
$out.="0x00\n};\n";
print $out;

BIN
devtools/bin/tier0.dll Normal file

Binary file not shown.

View File

@ -0,0 +1,6 @@
foreach $_ (sort <> )
{
next if( defined( $prevline ) && $_ eq $prevline );
$prevline = $_;
print;
}

View File

@ -0,0 +1,325 @@
use String::CRC32;
BEGIN {use File::Basename; push @INC, dirname($0); }
require "valve_perl_helpers.pl";
$dynamic_compile = defined $ENV{"dynamic_shaders"} && $ENV{"dynamic_shaders"} != 0;
$depnum = 0;
$baseSourceDir = ".";
my %dep;
sub GetAsmShaderDependencies_R
{
local( $shadername ) = shift;
local( *SHADER );
open SHADER, "<$shadername";
while( <SHADER> )
{
if( m/^\s*\#\s*include\s+\"(.*)\"/ )
{
# make sure it isn't in there already.
if( !defined( $dep{$1} ) )
{
$dep{$1} = 1;
GetAsmShaderDependencies_R( $1 );
}
}
}
close SHADER;
}
sub GetAsmShaderDependencies
{
local( $shadername ) = shift;
undef %dep;
GetAsmShaderDependencies_R( $shadername );
# local( $i );
# foreach $i ( keys( %dep ) )
# {
# print "$shadername depends on $i\n";
# }
return keys( %dep );
}
sub GetShaderType
{
my $shadername = shift;
my $shadertype;
if( $shadername =~ m/\.vsh/i )
{
$shadertype = "vsh";
}
elsif( $shadername =~ m/\.psh/i )
{
$shadertype = "psh";
}
elsif( $shadername =~ m/\.fxc/i )
{
$shadertype = "fxc";
}
else
{
die;
}
return $shadertype;
}
sub GetShaderSrc
{
my $shadername = shift;
if ( $shadername =~ m/^(.*)-----/i )
{
return $1;
}
else
{
return $shadername;
}
}
sub GetShaderBase
{
my $shadername = shift;
if ( $shadername =~ m/-----(.*)$/i )
{
return $1;
}
else
{
my $shadertype = &GetShaderType( $shadername );
$shadername =~ s/\.$shadertype//i;
return $shadername;
}
}
sub DoAsmShader
{
my $argstring = shift;
my $shadername = &GetShaderSrc( $argstring );
my $shaderbase = &GetShaderBase( $argstring );
my $shadertype = &GetShaderType( $argstring );
my $incfile = "";
if( $shadertype eq "fxc" || $shadertype eq "vsh" )
{
$incfile = $shadertype . "tmp9" . $g_tmpfolder . "\\$shaderbase.inc ";
}
my $vcsfile = $shaderbase . $g_vcsext;
my $bWillCompileVcs = 1;
if( ( $shadertype eq "fxc") && $dynamic_compile )
{
$bWillCompileVcs = 0;
}
if( $shadercrcpass{$argstring} )
{
$bWillCompileVcs = 0;
}
if( $bWillCompileVcs )
{
&output_makefile_line( $incfile . "shaders\\$shadertype\\$vcsfile: $shadername ..\\..\\devtools\\bin\\updateshaders.pl ..\\..\\devtools\\bin\\" . $shadertype . "_prep.pl" . " @dep\n") ;
}
else
{
# psh files don't need a rule at this point since they don't have inc files and we aren't compiling a vcs.
if( $shadertype eq "fxc" || $shadertype eq "vsh" )
{
&output_makefile_line( $incfile . ": $shadername ..\\..\\devtools\\bin\\updateshaders.pl ..\\..\\devtools\\bin\\" . $shadertype . "_prep.pl" . " @dep\n") ;
}
}
my $x360switch = "";
my $ps3switch = "";
my $moreswitches = "";
if( !$bWillCompileVcs && $shadertype eq "fxc" )
{
$moreswitches .= "-novcs ";
}
if( $g_x360 )
{
$x360switch = "-x360";
if( $bWillCompileVcs && ( $shaderbase =~ m/_ps20$/i ) )
{
$moreswitches .= "-novcs ";
$bWillCompileVcs = 0;
}
}
if( $g_ps3 )
{
$ps3switch = "-ps3";
if( $bWillCompileVcs && ( $shaderbase =~ m/_ps20$/i ) )
{
$moreswitches .= "-novcs ";
$bWillCompileVcs = 0;
}
}
# if we are psh and we are compiling the vcs, we don't need this rule.
if( !( $shadertype eq "psh" && !$bWillCompileVcs ) )
{
&output_makefile_line( "\tperl $g_SourceDir\\devtools\\bin\\" . $shadertype . "_prep.pl $moreswitches $x360switch $ps3switch -source \"$g_SourceDir\" $argstring\n") ;
}
if( $bWillCompileVcs )
{
&output_makefile_line( "\techo $shadername>> filestocopy.txt\n") ;
my $dep;
foreach $dep( @dep )
{
&output_makefile_line( "\techo $dep>> filestocopy.txt\n") ;
}
}
&output_makefile_line( "\n") ;
}
if( scalar( @ARGV ) == 0 )
{
die "Usage updateshaders.pl shaderprojectbasename\n\tie: updateshaders.pl stdshaders_dx6\n";
}
$g_x360 = 0;
$g_ps3 = 0;
$g_tmpfolder = "_tmp";
$g_vcsext = ".vcs";
while( 1 )
{
$inputbase = shift;
if( $inputbase =~ m/-source/ )
{
$g_SourceDir = shift;
}
elsif( $inputbase =~ m/-x360/ )
{
$g_x360 = 1;
$g_tmpfolder = "_360_tmp";
$g_vcsext = ".360.vcs";
}
elsif( $inputbase =~ m/-ps3/ )
{
$g_ps3 = 1;
$g_tmpfolder = "_ps3_tmp";
$g_vcsext = ".ps3.vcs";
}
elsif( $inputbase =~ m/-execute/ )
{
$g_execute = 1;
}
elsif( $inputbase =~ m/-nv3x/ )
{
$nv3x = 1;
}
else
{
last;
}
}
my @srcfiles = &LoadShaderListFile( $inputbase );
open MAKEFILE, ">makefile\.$inputbase";
open COPYFILE, ">makefile\.$inputbase\.copy";
open INCLIST, ">inclist.txt";
open VCSLIST, ">vcslist.txt";
# make a default dependency that depends on all of the shaders.
&output_makefile_line( "default: ") ;
foreach $shader ( @srcfiles )
{
my $shadertype = &GetShaderType( $shader );
my $shaderbase = &GetShaderBase( $shader );
my $shadersrc = &GetShaderSrc( $shader );
if( $shadertype eq "fxc" || $shadertype eq "vsh" )
{
# We only generate inc files for fxc and vsh files.
my $incFileName = "$shadertype" . "tmp9" . $g_tmpfolder . "\\" . $shaderbase . "\.inc";
&output_makefile_line( " $incFileName" );
&output_inclist_line( "$incFileName\n" );
}
my $vcsfile = $shaderbase . $g_vcsext;
my $compilevcs = 1;
if( $shadertype eq "fxc" && $dynamic_compile )
{
$compilevcs = 0;
}
# Do not compile ps2.0 shaders on PS3/X360
if( ( $g_x360 || $g_ps3 ) && ( $shaderbase =~ m/_ps20$/i ) )
{
$compilevcs = 0;
}
if( $compilevcs )
{
my $vcsFileName = "..\\..\\..\\game\\platform\\shaders\\$shadertype\\$shaderbase" . $g_vcsext;
# We want to check for perforce operations even if the crc matches in the event that a file has been manually reverted and needs to be checked out again.
&output_vcslist_line( "$vcsFileName\n" );
$shadercrcpass{$shader} = &CheckCRCAgainstTarget( $shadersrc, $vcsFileName, 0 );
if( $shadercrcpass{$shader} )
{
$compilevcs = 0;
}
}
if( $compilevcs )
{
&output_makefile_line( " shaders\\$shadertype\\$vcsfile" );
# emit a list of vcs files to copy to the target since we want to build them.
&output_copyfile_line( GetShaderSrc($shader) . "-----" . GetShaderBase($shader) . "\n" );
}
}
&output_makefile_line( "\n\n") ;
# Insert all of our vertex shaders and depencencies
$lastshader = "";
foreach $shader ( @srcfiles )
{
my $currentshader = &GetShaderSrc( $shader );
if ( $lastshader ne $currentshader )
{
$lastshader = $currentshader;
@dep = &GetAsmShaderDependencies( $lastshader );
}
&DoAsmShader( $shader );
}
close VCSLIST;
close INCLIST;
close COPYFILE;
close MAKEFILE;
# nuke the copyfile if it is zero length
if( ( stat "makefile\.$inputbase\.copy" )[7] == 0 )
{
unlink "makefile\.$inputbase\.copy";
}
sub output_makefile_line
{
local ($_)=@_;
print MAKEFILE $_;
}
sub output_copyfile_line
{
local ($_)=@_;
print COPYFILE $_;
}
sub output_vcslist_line
{
local ($_)=@_;
print VCSLIST $_;
}
sub output_inclist_line
{
local ($_)=@_;
print INCLIST $_;
}

View File

@ -0,0 +1,65 @@
@echo off
:: // This will make all new env variables local to this script
setlocal
:: // Make sure we have 2 args
if .%2.==.. (
echo *** [valve_p4_create_changelist] Error calling command! No file or changelist specified for checkout! Usage: valve_p4_create_changelist.cmd fileOrPath "Description"
endlocal
exit /b 1
)
:: // Get file info
set valveTmpPathOnly="%~d1%~p1"
if "%valveTmpPathOnly%"=="" (
echo *** [valve_p4_create_changelist] Error! Can't parse file or path "%1"!
endlocal
exit /b 1
)
:: // Change directories so that the p4 set commands give use useful data
pushd %valveTmpPathOnly%
:: // Find user
for /f "tokens=2 delims== " %%A in ('p4.exe set ^| find /i "P4USER="') do set valveP4User=%%A
if "%valveP4User%"=="" goto RegularCheckout
rem //echo User="%valveP4User%"
:: // Find client
for /f "tokens=2 delims== " %%A in ('p4.exe set ^| find /i "P4CLIENT="') do set valveP4Client=%%A
if "%valveP4Client%"=="" goto RegularCheckout
rem //echo Client="%valveP4Client%"
:: // Search for existing changelist that matches command line arg
set valveP4ChangelistName=%2%
set valveP4ChangelistName=%valveP4ChangelistName:~1,-1%
for /f "tokens=2 delims= " %%A in ('p4.exe changes -u %valveP4User% -s pending -c %valveP4Client% ^| sort /r ^| find /i "'%valveP4ChangelistName%"') do set valveP4ChangelistNumber=%%A
if NOT "%valveP4ChangelistNumber%"=="" goto HaveChangelist
:: // We didn't find a matching changelist but we did figure enough out to create a new changelist
rem //echo Creating New Changelist
for /f "tokens=2 delims= " %%A in ('^( echo Change: new ^& echo Client: %valveP4Client% ^& echo User: %valveP4User% ^& echo Status: new ^& echo Description: %valveP4ChangelistName%^&echo.^) ^| p4.exe change -i') do set valveP4ChangelistNumberJustCreated=%%A
if "%valveP4ChangelistNumberJustCreated%"=="" goto RegularCheckout
:: // Now search for the changelist number even though we already have it to try to clean up after the race condition when it's hit
:: // This way, if more than one changelist is created in parallel, this will hopefully cause them to be checked out into the same changelist and the empty one deleted
for /f "tokens=2 delims= " %%A in ('p4.exe changes -u %valveP4User% -s pending -c %valveP4Client% ^| sort /r ^| find /i "'%valveP4ChangelistName%"') do set valveP4ChangelistNumber=%%A
if "%valveP4ChangelistNumber%"=="" goto RegularCheckout
if NOT "%valveP4ChangelistNumber%"=="%valveP4ChangelistNumberJustCreated%" p4.exe change -d %valveP4ChangelistNumberJustCreated% 2>&1 >nul
:: // We have a changelist number
:HaveChangelist
echo %valveP4ChangelistNumber%
goto End
:: // Can't find or create the changelist, output 0
:RegularCheckout
echo 0
goto End
:End
popd
endlocal
exit /b 0

View File

@ -0,0 +1,93 @@
@echo off
:: // This will make all new env variables local to this script
setlocal
:: // If called with the start command, we need to exit, so also make sure you pass EXIT as the third param!
:: // Also, if you modify this script, make sure that endlocal and exit are within ()'s so valveExitArg works!
:: // Type 'help set' at a command prompt if you don't understand why.
if NOT "%3"=="EXIT" set valveExitArg=/b
:: // Make sure we have 2 args
if .%2.==.. (
echo *** [valve_p4_edit_to_changelist] Error calling command! No file or changelist specified for checkout! Usage: valve_p4_edit_to_changelist.cmd file "Description" [EXIT]
endlocal
exit %valveExitArg% 1
)
:: // Get file info
set valveTmpFileName="%~n1%~x1"
set valveTmpFullFilePath="%~f1"
set valveTmpPathOnly="%~d1%~p1"
if "%valveTmpFileName%"=="" (
echo *** [valve_p4_edit_to_changelist] Error! Can't parse filename "%1"!
endlocal
exit %valveExitArg% 1
)
if "%valveTmpFullFilePath%"=="" (
echo *** [valve_p4_edit_to_changelist] Error! Can't parse filename "%1"!
endlocal
exit %valveExitArg% 1
)
if "%valveTmpPathOnly%"=="" (
echo *** [valve_p4_edit_to_changelist] Error! Can't parse filename "%1"!
endlocal
exit %valveExitArg% 1
)
:: // Change directories so that the p4 set commands give use useful data
pushd %valveTmpPathOnly%
:: // Find user
for /f "tokens=2 delims== " %%A in ('p4.exe set ^| find /i "P4USER="') do set valveP4User=%%A
if "%valveP4User%"=="" goto RegularCheckout
rem //echo User="%valveP4User%"
:: // Find client
for /f "tokens=2 delims== " %%A in ('p4.exe set ^| find /i "P4CLIENT="') do set valveP4Client=%%A
if "%valveP4Client%"=="" goto RegularCheckout
rem //echo Client="%valveP4Client%"
:: // Search for existing changelist that matches command line arg
set valveP4ChangelistName=%2%
set valveP4ChangelistName=%valveP4ChangelistName:~1,-1%
for /f "tokens=2 delims= " %%A in ('p4.exe changes -u %valveP4User% -s pending -c %valveP4Client% ^| sort /r ^| find /i "'%valveP4ChangelistName%"') do set valveP4ChangelistNumber=%%A
if NOT "%valveP4ChangelistNumber%"=="" goto HaveChangelist
:: // We didn't find a matching changelist but we did figure enough out to create a new changelist
rem //echo Creating New Changelist
for /f "tokens=2 delims= " %%A in ('^( echo Change: new ^& echo Client: %valveP4Client% ^& echo User: %valveP4User% ^& echo Status: new ^& echo Description: %valveP4ChangelistName%^&echo.^) ^| p4.exe change -i') do set valveP4ChangelistNumberJustCreated=%%A
if "%valveP4ChangelistNumberJustCreated%"=="" goto RegularCheckout
:: // Now search for the changelist number even though we already have it to try to clean up after the race condition when it's hit
:: // This way, if more than one changelist is created in parallel, this will hopefully cause them to be checked out into the same changelist and the empty one deleted
for /f "tokens=2 delims= " %%A in ('p4.exe changes -u %valveP4User% -s pending -c %valveP4Client% ^| sort /r ^| find /i "'%valveP4ChangelistName%"') do set valveP4ChangelistNumber=%%A
if "%valveP4ChangelistNumber%"=="" goto RegularCheckout
if NOT "%valveP4ChangelistNumber%"=="%valveP4ChangelistNumberJustCreated%" p4.exe change -d %valveP4ChangelistNumberJustCreated% 2>&1 >nul
:: // We have a changelist number
:HaveChangelist
set valveP4ChangelistArg=-c %valveP4ChangelistNumber%
rem //echo valveP4ChangelistArg="%valveP4ChangelistArg%"
rem //echo ChangelistNumber="%valveP4ChangelistNumber%"
rem //echo ChangelistName="%valveP4ChangelistName%"
:: // Check the file out
:RegularCheckout
if "%VALVE_WAIT_ON_P4%"=="" (
p4.exe edit %valveP4ChangelistArg% %valveTmpFullFilePath% 2>&1 | find /v /i "- currently opened for edit" | find /v /i "- also opened by" | find /v /i "- file(s) not on client" | find /v /i "- can't change from"
) ELSE (
:: // Filter out largely benign messages unless we're explicitly waiting on p4 results a la buildbot
p4.exe edit %valveP4ChangelistArg% %valveTmpFullFilePath% 2>&1 | find /v /i "- also opened by"
)
goto End
:End
popd
( endlocal
exit %valveExitArg% 0 )

View File

@ -0,0 +1,554 @@
sub BackToForwardSlash
{
my( $path ) = shift;
$path =~ s,\\,/,g;
return $path;
}
sub RemoveFileName
{
my( $in ) = shift;
$in = &BackToForwardSlash( $in );
$in =~ s,/[^/]*$,,;
return $in;
}
sub RemovePath
{
my( $in ) = shift;
$in = &BackToForwardSlash( $in );
$in =~ s,^(.*)/([^/]*)$,$2,;
return $in;
}
sub MakeDirHier
{
my( $in ) = shift;
# print "MakeDirHier( $in )\n";
$in = &BackToForwardSlash( $in );
my( @path );
while( $in =~ m,/, ) # while $in still has a slash
{
my( $end ) = &RemovePath( $in );
push @path, $end;
# print $in . "\n";
$in = &RemoveFileName( $in );
}
my( $i );
my( $numelems ) = scalar( @path );
my( $curpath );
for( $i = $numelems - 1; $i >= 0; $i-- )
{
$curpath .= "/" . $path[$i];
my( $dir ) = $in . $curpath;
if( !stat $dir )
{
# print "mkdir $dir\n";
mkdir $dir, 0777;
}
}
}
sub FileExists
{
my $filename = shift;
my @statresult = stat $filename;
my $iswritable = @statresult != 0;
return $iswritable;
}
sub MakeFileWritable
{
my $filename = shift;
if ( &FileExists( $filename ) )
{
chmod 0666, $filename || die;
}
}
sub MakeFileReadOnly
{
my $filename = shift;
chmod 0444, $filename || die;
}
# Run a command and get stdout and stderr to an array
sub RunCommand
{
my $cmd = shift;
# print STDERR "command: $cmd\n";
system "$cmd > cmdout.txt 2>&1" || die;
local( *FILE );
open FILE, "<cmdout.txt" || die;
my @output = <FILE>;
# print STDERR "command output: @output\n";
close FILE;
unlink "cmdout.txt" || die;
return @output;
}
sub PerforceEditOrAdd
{
return;
my $filename = shift;
my $changelistarg = shift;
# Is the file on the client?
my $cmd = "p4 fstat \"$filename\"";
my @p4output = &RunCommand( $cmd );
my $p4output = join "", @p4output;
if( $p4output =~ m/no such file/ )
{
# not on client. . add
my $cmd = "p4 add $changelistarg $filename";
my @p4output = &RunCommand( $cmd );
my $p4output = join "", @p4output;
if( $p4output =~ m/opened for add/ )
{
print $p4output;
return;
}
print "ERROR: $p4output";
return;
}
# The file is known to be on the client at this point.
# Is it open for edit?
if( $p4output =~ m/action edit/ )
{
# Is is open for edit, let's see if it's still different.
# check for opened files that are not different from the revision in the depot.
my $cmd = "p4 diff -sr \"$filename\"";
my @p4output = &RunCommand( $cmd );
my $outputstring = join "", @p4output;
# check for empty string
if( !( $outputstring =~ m/^\s*$/ ) )
{
my $cmd = "p4 revert \"$filename\"";
my @p4output = &RunCommand( $cmd );
my $outputstring = join "", @p4output;
print $outputstring;
return;
}
}
# check for unopened files that are different from the revision in the depot.
my $cmd = "p4 diff -se \"$filename\"";
my @p4output = &RunCommand( $cmd );
my $outputstring = join "", @p4output;
# check for empty string
if( $outputstring =~ m/^\s*$/ )
{
&MakeFileReadOnly( $filename );
return;
}
# We need to edit the file since it is known to be different here.
my $cmd = "p4 edit $changelistarg \"$filename\"";
my @p4output = &RunCommand( $cmd );
my $line;
foreach $line ( @p4output )
{
if( $line =~ m/not on client/ )
{
#print "notonclient...";
print "ERROR: @p4output\n";
return;
}
if( $line =~ m/currently opened for edit/ )
{
return;
}
if( $line =~ m/opened for edit/ )
{
print $line;
}
}
}
sub FileIsWritable
{
local( $filename ) = shift;
local( @statresult ) = stat $filename;
local( $mode, $iswritable );
$mode = oct( $statresult[2] );
$iswritable = ( $mode & 2 ) != 0;
return $iswritable;
}
sub TouchFile
{
my $filename = shift;
if( !&FileExists( $filename ) )
{
if( !open FILE, ">$filename" )
{
die;
}
close FILE;
}
my $now = time;
local( *FILE );
utime $now, $now, $filename;
}
sub FileExistsInPerforce
{
my $filename = shift;
my @output = &RunCommand( "p4 fstat $filename" );
my $line;
foreach $line (@output)
{
if( $line =~ m/no such file/ )
{
return 0;
}
}
return 1;
}
sub PerforceWriteFile
{
my $filename = shift;
my $filecontents = shift;
# my $changelistname = shift;
# Get the changelist number for the Shader Auto Checkout changelist. Will create the changelist if it doesn't exist.
# my $changelistnumber = `valve_p4_create_changelist.cmd . \"$changelistname\"`;
# Get rid of the newline
# $changelistnumber =~ s/\n//g;
# my $changelistarg = "";
# if( $changelistnumber != 0 )
# {
# $changelistarg = "-c $changelistnumber"
# }
# Make the target vcs writable if it exists
MakeFileWritable( $filename );
# Write the file.
local( *FP );
open FP, ">$filename";
print FP $filecontents;
close FP;
# Do whatever needs to happen with perforce for this file.
# &PerforceEditOrAdd( $filename, $changelistarg );
}
sub WriteFile
{
my $filename = shift;
my $filecontents = shift;
# Make the target vcs writable if it exists
MakeFileWritable( $filename );
# Write the file.
local( *FP );
open FP, ">$filename";
print FP $filecontents;
close FP;
}
sub PrintCleanPerforceOutput
{
my $line;
while( $line = shift )
{
if( $line =~ m/currently opened/i )
{
next;
}
if( $line =~ m/already opened for edit/i )
{
next;
}
if( $line =~ m/also opened/i )
{
next;
}
if( $line =~ m/add of existing file/i )
{
next;
}
print $line;
}
}
# HACK!!!! Need to pass something in to do this rather than hard coding.
sub NormalizePerforceFilename
{
my $line = shift;
# remove newlines.
$line =~ s/\n//;
# downcase.
$line =~ tr/[A-Z]/[a-z]/;
# backslash to forwardslash
$line =~ s,\\,/,g;
# for inc files HACK!
$line =~ s/^.*(fxctmp9.*)/$1/i;
$line =~ s/^.*(vshtmp9.*)/$1/i;
# for vcs files. HACK!
$line =~ s,^.*game/platform/shaders/,,i;
return $line;
}
sub MakeSureFileExists
{
local( $filename ) = shift;
local( $testexists ) = shift;
local( $testwrite ) = shift;
local( @statresult ) = stat $filename;
if( !@statresult && $testexists )
{
die "$filename doesn't exist!\n";
}
local( $mode, $iswritable );
$mode = oct( $statresult[2] );
$iswritable = ( $mode & 2 ) != 0;
if( !$iswritable && $testwrite )
{
die "$filename isn't writable!\n";
}
}
sub LoadShaderListFile_GetShaderType
{
my $shadername = shift;
my $shadertype;
if( $shadername =~ m/\.vsh/i )
{
$shadertype = "vsh";
}
elsif( $shadername =~ m/\.psh/i )
{
$shadertype = "psh";
}
elsif( $shadername =~ m/\.fxc/i )
{
$shadertype = "fxc";
}
else
{
die;
}
return $shadertype;
}
sub LoadShaderListFile_GetShaderSrc
{
my $shadername = shift;
if ( $shadername =~ m/^(.*)-----/i )
{
return $1;
}
else
{
return $shadername;
}
}
sub LoadShaderListFile_GetShaderBase
{
my $shadername = shift;
if ( $shadername =~ m/-----(.*)$/i )
{
return $1;
}
else
{
my $shadertype = &LoadShaderListFile_GetShaderType( $shadername );
$shadername =~ s/\.$shadertype//i;
return $shadername;
}
}
sub LoadShaderListFile
{
my $inputbase = shift;
my @srcfiles;
&MakeSureFileExists( "$inputbase.txt", 1, 0 );
open SHADERLISTFILE, "<$inputbase.txt" || die;
my $line;
while( $line = <SHADERLISTFILE> )
{
$line =~ s/\/\/.*$//; # remove comments "//..."
$line =~ s/^\s*//; # trim leading whitespace
$line =~ s/\s*$//; # trim trailing whitespace
next if( $line =~ m/^\s*$/ );
if( $line =~ m/\.fxc/ || $line =~ m/\.vsh/ || $line =~ m/\.psh/ )
{
my $shaderbase = &LoadShaderListFile_GetShaderBase( $line );
if( $ENV{"DIRECTX_FORCE_MODEL"} =~ m/^30$/i ) # forcing all shaders to be ver. 30
{
my $targetbase = $shaderbase;
$targetbase =~ s/_ps2x/_ps30/i;
$targetbase =~ s/_ps20b/_ps30/i;
$targetbase =~ s/_ps20/_ps30/i;
$targetbase =~ s/_vs20/_vs30/i;
$targetbase =~ s/_vsxx/_vs30/i;
push @srcfiles, ( $line . "-----" . $targetbase );
}
else
{
if( $shaderbase =~ m/_ps2x/i )
{
my $targetbase = $shaderbase;
$targetbase =~ s/_ps2x/_ps20/i;
push @srcfiles, ( $line . "-----" . $targetbase );
$targetbase = $shaderbase;
$targetbase =~ s/_ps2x/_ps20b/i;
push @srcfiles, ( $line . "-----" . $targetbase );
}
elsif( $shaderbase =~ m/_vsxx/i )
{
my $targetbase = $shaderbase;
$targetbase =~ s/_vsxx/_vs20/i;
push @srcfiles, ( $line . "-----" . $targetbase );
}
else
{
push @srcfiles, ( $line . "-----" . $shaderbase );
}
}
}
}
close SHADERLISTFILE;
return @srcfiles;
}
sub ReadInputFileWithIncludes
{
local( $filename ) = shift;
# print STDERR "ReadInputFileWithIncludes: $filename\n";
local( *INPUT );
local( $output );
# print STDERR "before open\n";
open INPUT, "<$filename" || die;
# print STDERR "after open\n";
local( $line );
while( $line = <INPUT> )
{
# print STDERR $line;
if( $line =~ m/\#include\s+\"(.*)\"/i )
{
$output.= ReadInputFileWithIncludes( $1 );
}
else
{
$output .= $line;
}
}
close INPUT;
return $output;
}
sub GetCRCFromSourceFile
{
my $filename = shift;
my $data = &ReadInputFileWithIncludes( $filename );
# print STDERR $data;
$crc = crc32( $data );
# print STDERR "GetCRCFromSourceFile: $crc\n";
return $crc;
}
sub GetCRCFromVCSFile
{
my $filename = shift;
# print STDERR "GetCRCFromVCSFile $filename\n";
local( *FP );
open FP, "<$filename" || die "GetCRCFromVCSFile: can't open file $filename\n";
binmode( FP );
# unpack arguments
my $sInt = "i";
my $uInt = "I";
if ( ( $filename =~ m/\.360\./ ) || ( $filename =~ m/\.ps3\./ ) )
{
# Change arguments to "big endian long"
$sInt = "N";
$uInt = "N";
}
my $header;
read FP, $header, 7 * 4 || die "updateshaders.pl:GetCRCFromVCSFile: can't read header for $filename\n";
my $version,$numCombos,$numDynamicCombos,$flags,$centroidMask,$refSize,$crc;
($version,$numCombos,$numDynamicCombos,$flags,$centroidMask,$refSize,$crc) = unpack "$sInt$sInt$sInt$uInt$uInt$uInt$uInt", $header;
unless( $version == 4 || $version == 5 || $version == 6 )
{
print STDERR "ERROR: GetCRCFromVCSFile: $filename is version $version\n";
return 0;
}
# print STDERR "version: $version\n";
# print STDERR "numCombos: $numCombos\n";
# print STDERR "numDynamicCombos: $numDynamicCombos\n";
# print STDERR "flags: $flags\n";
# print STDERR "centroidMask: $centroidMask\n";
# print STDERR "refSize: $refSize\n";
# print STDERR "GetCRCFromVCSFile: $crc\n";
close( FP );
return $crc;
}
sub CheckCRCAgainstTarget
{
my $srcFileName = shift;
my $vcsFileName = shift;
my $warn = shift;
# Make sure both files exist.
# print STDERR "$srcFileName doesn't exist\n" if( !( -e $srcFileName ) );
# print STDERR "$vcsFileName doesn't exist\n" if( !( -e $vcsFileName ) );
if( !( -e $srcFileName ) )
{
if( $warn )
{
print "$srcFileName missing\n";
}
return 0;
}
if( !( -e $vcsFileName ) )
{
if( $warn )
{
print "$vcsFileName missing\n";
}
return 0;
}
# print STDERR "CheckCRCAgainstTarget( $srcFileName, $vcsFileName );\n";
# print STDERR "vcsFileName: $vcsFileName\n";
# print STDERR "vcsFileName: $srcFileName\n";
my $vcsCRC = &GetCRCFromVCSFile( $vcsFileName );
my $srcCRC = &GetCRCFromSourceFile( $srcFileName );
if( $warn && ( $vcsCRC != $srcCRC ) )
{
print "$vcsFileName checksum ($vcsCRC) != $srcFileName checksum: ($srcCRC)\n";
}
# return 0; # use this to skip crc checking.
# if( $vcsCRC == $srcCRC )
# {
# print STDERR "CRC passed for $srcFileName $vcsFileName $vcsCRC\n";
# }
return $vcsCRC == $srcCRC;
}
1;

49
devtools/bin/vpc Normal file
View File

@ -0,0 +1,49 @@
#!/bin/bash
OS=`uname`
SCRIPTPATH=`dirname $0`
FORCEARG=""
case $OS in
"Darwin")
BINNAME=vpc_osx
;;
"Linux")
BINNAME=vpc_linux
;;
*)
echo "Couldn't find appropriate VPC binary, fix the script."
exit -1
;;
esac
CWD=`pwd`
cd $SCRIPTPATH/../../utils/vpc/vpc
# ask make if we need to do any work, returns 0 if we don't,
# non zero if we do.
make -q
RC=$?
if [ $RC -eq 1 ]; then
FORCEARG="/f"
elif [ $RC -eq 2 ]; then
FORCEARG="/f"
make clean
fi
make -j4
if [ $? -ne 0 ]; then
exit -1
fi
if [ $RC -ne 0 ]; then
cp -vf ../../devtools/bin/$BINNAME $CWD/$SCRIPTPATH
fi
cd $CWD
if [ $OS == "Darwin" ]; then
$SCRIPTPATH/$BINNAME $FORCEARG $@
elif [ $OS == "Linux" ]; then
$SCRIPTPATH/$BINNAME $FORCEARG $@
else
echo "Couldn't find appropriate VPC binary, fix the script."
exit -1
fi

BIN
devtools/bin/vpc.dll Normal file

Binary file not shown.

View File

@ -0,0 +1,676 @@
#!perl
use IO::File;
use File::Basename;
use File::Find;
use Cwd;
use Cwd 'abs_path';
$nprocs=`grep vendor_id /proc/cpuinfo | wc -l `;
$nprocs=~s/[\n\r]//g;
print "$nprocs processors found\n";
#find where to include master make file from
$srcdir=getcwd;
die "can't determine path to src"
unless ($srcdir=~s@/src.*$@/src@);
find( { wanted=> \&handle_vpc_file } ,"$srcdir"); # search through all directories for .vpc files
@MAINTARGETS=("all", "clean", "objs");
@TARGETS=("all", "clean", "objs", "tags");
# now, write a master makefile in each dir, and a master-master makefile in ~/src
foreach $dir ( keys %dir_written )
{
open( MAKEOUT,">$dir/Makefile" ) || die "can't write $dir/Makefile";
foreach $target ( @TARGETS )
{
print MAKEOUT ".PHONY: $target\n\n";
print MAKEOUT "$target:\n";
foreach $_ (split(/,/,$dir_written{$dir}) )
{
print MAKEOUT "\tmake -j $nprocs -f $_ $target\n" if length($_);
}
}
close MAKEOUT;
}
# now, write a master makefile in ~/src
open( MAKEOUT,">$srcdir/Makefile" ) || die "can't write master makefile to $srcdir";
foreach $target ( @MAINTARGETS )
{
print MAKEOUT ".PHONY: $target\n\n";
print MAKEOUT "$target:\n";
foreach $dir ( keys %dir_written )
{
if ($target ne "clean" )
{
print MAKEOUT "\tmake -j $nprocs -C $dir $target\n";
}
else
{
print MAKEOUT "\tmake -C $dir $target\n";
}
}
}
print MAKEOUT "\n\nmakefiles:\n\tperl $srcdir/devtools/bin/vpc2linuxmake.pl\n";
print MAKEOUT "\ntags:\n\tctags --languages=c++ -eR\n";
close MAKEOUT;
sub handle_vpc_file
{
# called for each file in the callers dir tree
my $dir=$File::Find::dir;
return if ( $dir=~/vpc_scripts/i );
if ( /_base\.vpc$/i )
{
unless ( /hk_base\.vpc$/i )
{
return;
}
}
return if (/_inc\.vpc/i);
if (/\.vpc$/)
{
(%ignore_file,@DEFINES, @CPPFILES, @CXXFILES,@CFILES, @LITERAL_LIBFILES,@LIBFILES, %define_seen,%macros,%include_seen,@INCLUDEDIRS)=undef;
undef $buildforlinux;
undef $conf_type;
undef $gccflags;
$OptimizeLevel=3;
# some defines to ignore in vpc files when generating linux include files
$define_seen{'WIN32'}=1;
$define_seen{'_WIN32'}=1;
$define_seen{'_WINDOWS'}=1;
$define_seen{'_USRDLL'}=1;
$define_seen{'DEBUG'}=1;
$define_seen{'_DEBUG'}=1;
$define_seen{'NDEBUG'}=1;
$define_seen{'_CRT_SECURE_NO_DEPRECATE'}=1;
$define_seen{'_CRT_NONSTDC_NO_DEPRECATE'}=1;
$define_seen{'fopen'}=1;
# print STDERR "parsing project $pname\n";
&ParseVPC($_);
$pname=lc($pname);
$pname=~s/\s+/_/g;
$pname=~s/[\(\)]//g;
# if anything seen, output a makefile
if ( $buildforlinux && ( @CPPFILES || @CXXFILES || @CFILES || @LIBFILES ) )
{
print STDERR "writing project $pname\n";
$projdir=getcwd;
$projdir=~s@/$@@;
$dir_written{$projdir}.=",$pname.mak";
&WriteMakefile("$projdir/$pname.mak");
&WriteCodeBlocksProj("$projdir/$pname.cbp");
}
else
{
die "no .lib or source files found in .vpc" if ( $buildforlinux );
}
}
}
sub WriteCodeBlocksProj
{
local($_)=@_;
open(CBPROJ,">$_") || die "can't write $_";
print CBPROJ <<HEADER
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="$pname" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Release">
</Target>
</Build>
HEADER
;
foreach $fl (@CPPFILES)
{
push @cppfiles2, $fl unless ( $ignore_file{$fl} > 0 );
}
foreach $fl (@CXXFILES)
{
push @cxxfiles2, $fl unless ( $ignore_file{$fl} > 0 );
}
printf CBPROJ "\t\t<Compiler>\n";
foreach $_ (@DEFINES)
{
print CBPROJ "\t\t\t<Add option=\"-DSWDS\" />\n";
print CBPROJ "\t\t\t<Add option=\"-D_LINUX\" />\n";
print CBPROJ "\t\t\t<Add option=\"-fpermissive\" />\n";
print CBPROJ "\t\t\t<Add option=\"-Dstricmp=strcasecmp\" />\n";
print CBPROJ "\t\t\t<Add option=\"-D_stricmp=strcasecmp\" />\n";
print CBPROJ "\t\t\t<Add option=\"-D_strnicmp=strncasecmp\" />\n";
print CBPROJ "\t\t\t<Add option=\"-Dstrnicmp=strncasecmp\" />\n";
print CBPROJ "\t\t\t<Add option=\"-D_snprintf=snprintf\" />\n";
print CBPROJ "\t\t\t<Add option=\"-D_vsnprintf=vsnprintf\" />\n";
print CBPROJ "\t\t\t<Add option=\"-D_alloca=alloca\" />\n";
print CBPROJ "\t\t\t<Add option=\"-Dstrcmpi=strcasecmp\" />\n";
print CBPROJ "\t\t\t<Add option=\"-D$_\" />\n";
}
foreach $_ (@INCLUDEDIRS)
{
print CBPROJ "\t\t\t<Add directory=\"$_\" />\n";
}
printf CBPROJ "\t\t</Compiler>\n";
@CPPFILES = sort(@CPPFILES);
@CXXFILES = sort(@CXXFILES);
@CFILES = sort(@CFILES);
# now, output obj dependencies
foreach $_ (@CPPFILES, @CFILES, @CXXFILES)
{
unless (( $ignore_file{$_} > 0 ) || ( length($_) < 2 ) )
{
($filename,$dir,$suffix) = fileparse($_,qr/\.[^.]*/);
print CBPROJ "\t\t<Unit filename=\"".$dir . $filename. ".cpp\" />\n";
}
}
print CBPROJ <<FOOTER
<Extensions>
<code_completion />
</Extensions>
</Project>
</CodeBlocks_project_file>
FOOTER
;
close CBPROJ;
}
sub WriteMakefile
{
local($_)=@_;
open(MAKEFILE,">$_") || die "can't write $_";
print MAKEFILE "NAME=$pname\n\n";
print MAKEFILE "SRCROOT=$srcdir\n";
print MAKEFILE "PROJDIR=$projdir\n";
print MAKEFILE "CONFTYPE=$conf_type\n";
print MAKEFILE "PROJECT_SPECIFIC_GCCFLAGS = $gccflags\n";
if ( int($OptimizeLevel) )
{
print MAKEFILE "OLEVEL=-O$OptimizeLevel\n";
}
else
{
print MAKEFILE "OLEVEL=\n";
}
if (@DEFINES)
{
print MAKEFILE "DEFINES= -D",join(" -D", @DEFINES),"\n";
}
if (@INCLUDEDIRS)
{
print MAKEFILE "INCLUDEDIRS= -I",join(" -I", @INCLUDEDIRS),"\n";
}
undef @cppfiles2;
undef @cxxfiles2;
foreach $fl (@CPPFILES)
{
if ( length($fl) )
{
print "warning file $fl does not exist\n" unless( -e $fl);
push @cppfiles2, $fl unless ( $ignore_file{$fl} > 0 );
}
}
foreach $fl (@CXXFILES)
{
push @cxxfiles2, $fl unless ( $ignore_file{$fl} > 0 );
}
if (@cppfiles2)
{
print MAKEFILE "CPPFILES= \\\n ", join(" \\\n ",@cppfiles2), "\n";
}
if (@cxxfiles2)
{
print MAKEFILE "CXXFILES= \\\n ", join(" \\\n ",@cxxfiles2), "\n";
}
if (@CFILES)
{
print MAKEFILE "CFILES= \\\n ", join(" \\\n ",@CFILES), "\n";
}
if (@LIBFILES)
{
undef @LIBNAMES;
print MAKEFILE "\nLIBFILES= \\\n";
unless( $pname=~/(tier0)|(mathlib)|(tier1)/i)
{
print MAKEFILE " $srcdir/lib/linux/tier1_486.a \\\n"
}
foreach $lib (@LIBFILES)
{
my @DLLNAMES=("tier0", "vstdlib", "steam_api");
unless ( $ignore_file{$lib} > 0 )
{
$lib=lc($lib);
my ($filename,$dir,$suffix) = fileparse($lib,qr/\.[^.]*/);
my $dll=0;
foreach $dllname (@DLLNAMES)
{
$dll=1 if ( $dllname eq $filename);
}
if ( $dll )
{
$lib=~s@^(.*)\.lib@$1_i486.so@i;
$lib=~s@/lib/.*/([^/]+)@/linux/$1@g;
}
else
{
$lib=~s/\.lib/_486.a/i;
$lib=~s@/lib/(\S+)/@/lib/linux/@g;
}
push @LIBNAMES, $lib;
}
}
foreach $lib (@LITERAL_LIBFILES)
{
unless ( $ignore_file{$lib} > 0 )
{
$lib=~s/\\/\//g;
$lib=~s@/linux/([a-zA-Z_0-9\.]+)$@/linux/$1@;
$lib=~s@^.*/linux/([a-zA-Z_0-9]+)\.so$@$1.so@;
push @LIBNAMES, $lib;
}
}
# now, sort libs for link order
foreach $lib ( sort bypriority @LIBNAMES )
{
print MAKEFILE " $lib \\\n";
}
print MAKEFILE "\n\n";
}
if ( $conf_type eq "dll" )
{
print MAKEFILE "OUTPUT_SO_FILE=$srcdir/linux/$pname","_i486.so\n\n";
}
elsif ( $conf_type eq "exe" )
{
if ( $macros{'OUTBINNAME'} eq "" )
{
die "Missing OUTBINNAME macro";
}
print MAKEFILE "OUTPUT_EXECUTABLE=$srcdir/linux/$macros{'OUTBINNAME'}\n\n";
}
print MAKEFILE "\n\n\# include base make file\ninclude $srcdir/devtools/makefile_base_linux.mak\n";
# now, output obj dependencies
foreach $_ (@CPPFILES, @CFILES)
{
unless (( $ignore_file{$_} > 0 ) || ( length($_) < 2 ) )
{
($filename) = fileparse($_,qr/\.[^.]*/);
print MAKEFILE getcwd,"/obj/$filename.o : $_\n\t\$(DO_CC)\n";
}
}
foreach $_ (@CXXFILES)
{
unless (( $ignore_file{$_} > 0 ) || ( length($_) < 2 ) )
{
($filename) = fileparse($_,qr/\.[^.]*/);
print MAKEFILE getcwd,"/obj/$filename.oxx : $_\n\t\$(DO_CC)\n";
}
}
close MAKEFILE;
}
sub bypriority
{
# sort libs for gcc linkgoodness
$priority{"mathlib"}="0005";
$priority{"tier1"}="0010";
$priority{"tier2"}="0020";
$priority{"tier3"}="0030";
my ($filenamea) = fileparse($a,qr/\.[^.]*/);
my ($filenameb) = fileparse($b,qr/\.[^.]*/);
$filenamea =~ s/_.86.*$//; # lose _i486
$filenameb =~ s/_.86.*$//;
my $pa=$priority{$filenamea} || 1000;
my $pb=$priority{$filenameb} || 1000;
return $pb cmp $pa;
}
sub ParseVPC
{
local($fname)=@_;
&startreading($fname);
while(&nextvpcline)
{
# print "$_\n";
if ( (/^\$linux/i) )
{
&skipblock(0,\&handlelinuxline);
}
if ( (/^\$configuration/i) )
{
&skipblock(0,\&handleconfigline);
}
elsif (/^\s*\$project/i)
{
&parseproject;
}
}
}
sub massageline
{
# strip leading and trailing spaces and carriage returns and comments from vpc lines
s/[\n\r]//g;
s@//.*$@@g;
s@^\s*@@g;
s@\s*$@@g;
}
sub submacros
{
# replace all macros within a line
my $mac;
foreach $mac (keys %macros)
{
s/\$$mac/$macros{$mac}/g;
}
}
sub startreading
{
# initialize recursive file reader
my( $fname)=@_;
$curfile=IO::File->new($fname) || die "can't open $fname";
}
sub nextvpcline
{
# get the next line from the file, handling line continuations, macro substitution, and $include
# return 0 if out of lines
my $ret=0;
if ( $_ = <$curfile> )
{
$ret=1;
&massageline;
while(s@\\$@ @)
{
my $old=$_;
$_=<$curfile>;
&massageline;
$_=$old.$_;
}
s@\s+@ @g;
my $old=$_;
&submacros;
# now, parse
if (/\$macro (\S+) \"(\S+)\"$/i)
{
$macros{$1}=$2;
return &nextvpcline;
}
s/\[\$WIN32\]//g;
return &nextvpcline if (/\[\$X360\]/);
if ( /^\s*[\$\#]include\s+\"(.*)\"/i)
{
# process $include
my $incfile=$1;
push @filestack, $curfile;
$incfile=~s@\\@/@g;
if ( $curfile=IO::File->new($incfile) )
{
return &nextvpcline;
}
else
{
print STDERR "can't open include file $incfile, ignoring\n";
$curfile=pop(@filestack);
return "";
}
}
}
else
{
$curfile->close;
if (@filestack)
{
$curfile=pop(@filestack);
return &nextvpcline;
}
else
{
return 0;
}
}
return $ret;
}
sub skipblock
{
# skip a named block in the key values, handling nested {} pairs
my($empty_ok, $callback)=@_;
my $lnstat=&nextvpcline;
die "parse error eof in block" if ( (! $lnstat) && ( ! $empty_ok) );
my $nest=0;
if (/^\{/)
{
$nest++;
}
else
{
die "no start block found, $_ found instead" unless($empty_ok);
}
while ($nest)
{
die "prematur eof" unless &nextvpcline;
&$callback($_) if ( $callback );
$nest++ if (/^\{/);
$nest-- if (/^\}/);
}
}
sub parseproject
{
# handle a project block, picking up files mentioned
$pname="";
if (/^\s*\$project\s*(.*)$/i)
{
$pname=$1;
$pname=~s@\"@@g;
}
local($_);
my $nest=0;
&nextvpcline || die "empty project?";
$nest++ if (/^\s*\{/);
while($nest )
{
&nextvpcline || die "premature eof in project?";
$nest++ if (/^\{/);
$nest-- if (/^\}/);
&CheckForFileLine($_);
}
}
sub CheckForFileLine
{
local($_)=@_;
if (/^\s*\-\$File\s+(.*$)/i)
{
foreach $_ (split(/ /,$1))
{
s/\"//g;
$ignore_file{&process_path($_)} = 1;
}
}
elsif (/^\s*\$File\s+(.*$)/i)
{
foreach $_ (split(/ /,$1))
{
s/\"//g;
&handlefile($_);
}
}
}
sub handlefile
{
# given a project file (.cpp, etc), figure out what to do with it
local($_)=@_;
# hardcoded exclusions for linux
return if (/dx9sdk/i);
return if (/_360/i);
return if (/xbox_console.cpp/i);
return if (/xbox_system.cpp/i);
return if (/xbox_win32stubs.cpp/i);
return if (/binkw32/i || /binkxenon/i );
if (/\.cpp$/)
{
push @CPPFILES,process_path($_);
}
if (/\.cxx$/)
{
push @CXXFILES,process_path($_);
}
elsif (/\.c$/)
{
push @CFILES,process_path($_);
}
elsif (/\.lib$/)
{
push @LIBFILES,process_path($_);
}
elsif (/\.a$/)
{
push @LITERAL_LIBFILES, process_path($_);
}
elsif (/\.so$/)
{
push @LITERAL_LIBFILES, process_path($_);
}
}
sub process_path
{
local($_)=@_;
s@\\@/@g;
if ( (! -e $_) && ( -e lc($_)) )
{
# print STDERR "$_ does not exist try lc($_)\n";
$_=lc($_);
}
my $ap=abs_path($_);
if ( (! length($ap) ) && length($_))
{
# print "abs path of $_ is empty. bad dir?\n";
}
$_=$ap;
s@i686@i486@g;
if ( (! -e $_) && ( -e lc($_)) )
{
# print STDERR "$_ does not exist try lc($_)\n";
$_=lc($_);
}
# kill ..s for prettyness
s@/[^/]+/\.\./@/@g;
if (! -e $_)
{
# print STDERR "$_ does not exist\n";
}
return $_;
}
sub handlelinuxline
{
local($_)=@_;
$buildforlinux = 1 if ( /^\s*\$buildforlinux.*1/i);
$OptimizeLevel= $1 if (/^\s*\$OptimizerLevel\s+(\d+)/i);
$buildforlinux = 1 if ( /^\s*\$buildforlinux.*1/i);
$gccflags = $1 if (/^\s*\$ProjectSpecificGCCFLags\s+\"(\S+)\"/i);
&CheckForFileLine($_); # allows linux-specific file includes and excludes
&handleconfigline($_); # allow linux-specific #defines
}
sub CheckPreprocessorDefs
{
local($_)=@_;
if (/^\s*\$PreprocessorDefinitions\s+\"(.*)\"/i)
{
foreach $_ (split(/[;,]/,$1) )
{
unless( /\$/ || $define_seen{$_} || /fopen/i)
{
push(@DEFINES,$_);
$define_seen{$_}=1;
}
}
}
}
sub handleconfigline
{
# handle a line within a $Configuration block
local($_)=@_; # the line
if (/^\s*\$AdditionalIncludeDirectories\s+\"(.*)\"/i)
{
foreach $_ (split(/[;,]/,$1) )
{
unless( /\$/ || $include_seen{$_} )
{
push(@INCLUDEDIRS,process_path($_));
$include_seen{$_}=1;
}
}
}
if (/^\s*\$ConfigurationType\s*\"(.*)\"/)
{
undef $conf_type;
$conf_type="lib" if ($1 =~ /Static Library/i);
$conf_type="dll" if ($1 =~ /Dynamic Library/i);
$conf_type="exe" if ($1 =~ /Application/i);
print STDERR " unknown conf type $1\n" if (! length($conf_type) );
}
&CheckPreprocessorDefs($_);
}

1106
devtools/bin/vsh_prep.pl Normal file

File diff suppressed because it is too large Load Diff

BIN
devtools/bin/vstdlib.dll Normal file

Binary file not shown.

44
devtools/gendbg.sh Normal file
View File

@ -0,0 +1,44 @@
#!/bin/bash
OBJCOPY=objcopy
function usage {
echo "$0 /path/to/input/file [-o /path/to/output/file ]"
echo ""
}
if [ $# == 0 ]; then
usage
exit 2
fi
if [ $(basename $1) == $1 ]; then
INFILEDIR=$PWD
else
INFILEDIR=$(cd ${1%/*} && echo $PWD)
fi
INFILE=$(basename $1)
OUTFILEDIR=$INFILEDIR
OUTFILE=$INFILE.dbg
while getopts "o:" opt; do
case $opt in
o)
OUTFILEDIR=$(cd ${OPTARG%/*} && echo $PWD)
OUTFILE=$(basename $OPTARG)
;;
esac
done
if [ "$OUTFILEDIR" != "$INFILEDIR" ]; then
INFILE=${INFILEDIR}/${INFILE}
OUTFILE=${OUTFILEDIR}/${OUTFILE}
fi
pushd "$INFILEDIR"
$OBJCOPY "$INFILE" "$OUTFILE"
$OBJCOPY --add-gnu-debuglink="$OUTFILE" "$INFILE"
popd

View File

@ -0,0 +1,869 @@
#
# Base makefile for Linux and OSX
#
# !!!!! Note to future editors !!!!!
#
# before you make changes, make sure you grok:
# 1. the difference between =, :=, +=, and ?=
# 2. how and when this base makefile gets included in the generated makefile(s)
# ( see http://www.gnu.org/software/make/manual/make.html#Flavors )
#
# Command line prefixes:
# - errors are ignored
# @ command is not printed to stdout before being executed
# + command is executed even if Make is invoked in "do not exec" mode
OS := $(shell uname)
HOSTNAME := $(shell hostname)
IDENTIFY_CURRENT_MAKEFILE_RELATIVE_FUNCTION = $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
MAKEFILE_BASE_POSIX_MAK := $(call IDENTIFY_CURRENT_MAKEFILE_RELATIVE_FUNCTION)
CROSS_COMPILE_DIR := $(realpath $(dir $(MAKEFILE_BASE_POSIX_MAK))../../cross_compile)
ifeq ($(MAKE_VERBOSE),1)
QUIET_PREFIX =
QUIET_ECHO_POSTFIX =
else
QUIET_PREFIX = @
QUIET_ECHO_POSTFIX = > /dev/null
# Use abbreviated progress messages in the schema compiler.
VALVE_SCHEMA_QUIET = 1
export VALVE_SCHEMA_QUIET
endif
BASENAME := basename
CAT := cat
CP := cp
CUT := cut
DIRNAME := dirname
ECHO := echo
ETAGS := etags
EXPR := expr
FALSE := false
FGREP := fgrep
FIND := find
GREP := grep
ICONV := iconv
MKDIR := mkdir
PWD := PWD
PWD_TOOL := pwd
RM := rm
SED := sed
SLEEP := sleep
TAIL := tail
TOUCH := touch
TR := tr
TRUE := true
UNAME := uname
WHICH := which
ECHO_LF = $(ECHO) -e
BUILD_DEBUG_ECHO = $(TRUE)
#uncomment or define ENABLE_BUILD_DEBUG=1 on the make commandline to debug build phases and dependency updates
# ENABLE_BUILD_DEBUG = 1
ifneq "$(ENABLE_BUILD_DEBUG)" ""
BUILD_DEBUG_ECHO = $(ECHO)
endif
# SPEW_UPDATED_DEPENDENCIES spews the list of dependencies whose current timestamps invalidate this rule.
# This is only done when ENABLE_BUILD_DEBUG is 1
ifeq ("$(ENABLE_BUILD_DEBUG)","1")
SPEW_DEPENDENCY_CHUNK = \
SpewDependencyChunk () \
{ \
$(BUILD_DEBUG_ECHO) " $${1}"; \
return 0; \
}
SPEW_UPDATED_DEPENDENCIES = \
$(QUIET_PREFIX) \
{ \
$(BUILD_DEBUG_ECHO) "[SPEW_UPDATED_DEPENDENCIES] rule \"$@\" triggered by files:" && \
$(BUILD_DEBUG_ECHO) " $?"; \
}
else
SPEW_UPDATED_DEPENDENCIES = $(QUIET_PREFIX) $(TRUE)
endif
-include $(SRCROOT)/devtools/steam_def.mak
# To build with clang, set the following in your environment:
# CC = clang
# CXX = clang++
ifeq ($(CFG), release)
# With gcc 4.6.3, engine.so went from 7,383,765 to 8,429,109 when building with -O3.
# There also was no speed difference running at 1280x1024. May 2012, mikesart.
# -fno-omit-frame-pointer: need this for stack traces with perf.
OptimizerLevel_CompilerSpecific = -O2 -fno-strict-aliasing -ffast-math -fno-omit-frame-pointer
else
OptimizerLevel_CompilerSpecific = -O0
#-O1 -finline-functions
endif
# CPPFLAGS == "c/c++ *preprocessor* flags" - not "cee-plus-plus flags"
ARCH_FLAGS =
BUILDING_MULTI_ARCH = 0
CPPFLAGS = $(DEFINES) $(FORCEINCLUDES) $(addprefix -I, $(abspath $(INCLUDEDIRS) ))
ifeq ($(TARGET_PLATFORM),linux64)
CPPFLAGS += -fPIC
endif
CFLAGS = $(ARCH_FLAGS) $(CPPFLAGS) $(WARN_FLAGS) -fvisibility=$(SymbolVisibility) $(OptimizerLevel) -ffast-math -pipe $(GCC_ExtraCompilerFlags) -Usprintf -Ustrncpy -UPROTECTED_THINGS_ENABLE
# In -std=gnu++11 mode we get lots of errors about "error: narrowing conversion". -fpermissive
# turns these into warnings in gcc, and -Wno-c++11-narrowing suppresses them entirely in clang 3.1+.
ifeq ($(OS),Linux)
CXXFLAGS = $(CFLAGS) -std=gnu++0x -fpermissive
else
CXXFLAGS = $(CFLAGS) -std=gnu++11 -stdlib=libc++ -Wno-c++11-narrowing -Wno-dangling-else
endif
DEFINES += -DVPROF_LEVEL=1 -DGNUC
# This causes all filesystem interfaces to default to their 64bit versions on
# 32bit systems, which means we don't break on filesystems with inodes > 32bit.
DEFINES += -D_FILE_OFFSET_BITS=64
LDFLAGS = $(CFLAGS) $(GCC_ExtraLinkerFlags) $(OptimizerLevel)
GENDEP_CXXFLAGS = -MD -MP -MF $(@:.o=.P)
MAP_FLAGS =
ifeq ($(STEAM_BRANCH),1)
WARN_FLAGS = -Wall -Wextra -Wshadow -Wno-invalid-offsetof
else
WARN_FLAGS = -Wno-write-strings -Wno-multichar
endif
WARN_FLAGS += -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-sign-compare -Wno-reorder -Wno-invalid-offsetof -Wno-float-equal -Wno-switch -fdiagnostics-show-option -Wformat -Werror=format-security -Wstrict-aliasing=2
ifeq ($(OS),Linux)
# We should always specify -Wl,--build-id, as documented at:
# http://linux.die.net/man/1/ld and http://fedoraproject.org/wiki/Releases/FeatureBuildId.http://fedoraproject.org/wiki/Releases/FeatureBuildId
LDFLAGS += -Wl,--build-id
UUID_LIB =
# Set USE_STEAM_RUNTIME to build with the Steam Runtime. Otherwise uses
# The toolchain in /valve
ifneq ($(USE_STEAM_RUNTIME),1)
# dedicated server flags
ifeq ($(TARGET_PLATFORM),linux64)
VALVE_BINDIR = /valve/bin64/
MARCH_TARGET = nocona
else
VALVE_BINDIR = /valve/bin/
MARCH_TARGET = pentium4
endif
STRIP_FLAGS = -x
LIBCPP_EXT = a
else
# linux desktop client flags
VALVE_BINDIR =
DEFINES +=
# If the steam-runtime is available, use it. We should just default to using it when
# buildbot and everyone has a bit of time to get it installed.
ifneq "$(wildcard /valve/steam-runtime/bin/)" ""
# The steam-runtime is incompatible with clang at this point, so disable it
# if clang is enabled.
ifneq ($(CXX),clang++)
VALVE_BINDIR = /valve/steam-runtime/bin/
endif
endif
GCC_VER =
ifeq ($(TARGET_PLATFORM),linux64)
MARCH_TARGET = nocona
else
MARCH_TARGET = pentium4
endif
# On dedicated servers, some plugins depend on global variable symbols in addition to functions.
# So symbols like _Z16ClearMultiDamagev should show up when you do "nm server_srv.so" in TF2.
STRIP_FLAGS = -x
LIBCPP_EXT = so
UUID_LIB = -luuid
endif
# We want to make all TLS use the global-dynamic
# model, to avoid having to use -fpic but avoid problems with dlopen()
# failing due to TLS clashes. This happens in particular when trying
# to run the game with primus. Note that -ftls-model=global-dynamic
# doesn't work due to undocumented 'features' in gcc that only allow
# the TLS model to be 'downgraded' from the default and not upgraded.
CFLAGS += -D__thread='__thread __attribute__((tls_model("global-dynamic")))'
CXXFLAGS += -D__thread='__thread __attribute__((tls_model("global-dynamic")))'
ifeq ($(CXX),clang++)
# Clang does not support -mfpmath=sse
SSE_GEN_FLAGS = -msse2
else
SSE_GEN_FLAGS = -msse2 -mfpmath=sse
endif
# Turn this on when ready to fix errors that crop up (can merge fixes from console eventually).
#WARN_FLAGS += -Werror=return-type
ifeq ($(CXX),clang++)
# The C-linkage return-type warning (no returning of references) must be disabled after the
# return-type error is enabled.
WARN_FLAGS += -Wno-return-type-c-linkage
# -g0 must be specified because -g2 makes server.so.dbg so huge that the linker sometimes
# fails due to memory exhaustion.
CFLAGS += -g0
endif
CCACHE := $(SRCROOT)/devtools/bin/linux/ccache
ifeq ($(origin GCC_VER), undefined)
GCC_VER=-4.6
endif
ifeq ($(origin AR), default)
AR = $(VALVE_BINDIR)ar crs
endif
ifeq ($(origin CC),default)
CC = $(CCACHE) $(VALVE_BINDIR)gcc$(GCC_VER)
endif
ifeq ($(origin CXX), default)
CXX = $(CCACHE) $(VALVE_BINDIR)g++$(GCC_VER)
endif
# Support ccache with clang. Add -Qunused-arguments to avoid excessive warnings due to
# a ccache quirk. Could also upgrade ccache.
# http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html
ifeq ($(CC),clang)
CC = $(CCACHE) $(VALVE_BINDIR)clang -Qunused-arguments
endif
ifeq ($(CXX),clang++)
CXX = $(CCACHE) $(VALVE_BINDIR)clang++ -Qunused-arguments
endif
LINK ?= $(CC)
ifeq ($(TARGET_PLATFORM),linux64)
# nocona = pentium4 + 64bit + MMX, SSE, SSE2, SSE3 - no SSSE3 (that's three s's - added in core2)
ARCH_FLAGS += -march=$(MARCH_TARGET) -mtune=core2
LD_SO = ld-linux-x86-64.so.2
LIBSTDCXX := $(shell $(CXX) -print-file-name=libstdc++.$(LIBCPP_EXT))
LIBSTDCXXPIC := $(shell $(CXX) -print-file-name=libstdc++.$(LIBCPP_EXT))
else
# core2 = Intel Core2 CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support.
# changed for DOTA since we are running servers on newer hardware
ifeq ($(TARGET_PLATFORM_EXT),_client)
# on non-server Linux client builds let's be a little more conservative
ARCH_FLAGS += -m32 -march=prescott -mtune=core2 $(SSE_GEN_FLAGS)
else
ARCH_FLAGS += -m32 -march=core2 -mtune=core2 $(SSE_GEN_FLAGS)
endif
LD_SO = ld-linux.so.2
LIBSTDCXX := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.$(LIBCPP_EXT))
LIBSTDCXXPIC := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.$(LIBCPP_EXT))
LDFLAGS += -m32
endif
GEN_SYM ?= $(SRCROOT)/devtools/gendbg.sh
ifeq ($(CFG),release)
STRIP ?= strip $(STRIP_FLAGS) -S
# CFLAGS += -ffunction-sections -fdata-sections
# LDFLAGS += -Wl,--gc-sections -Wl,--print-gc-sections
else
STRIP ?= true
endif
VSIGN ?= true
LINK_MAP_FLAGS = -Wl,-Map,$(@:.so=).map
SHLIBLDFLAGS = -shared $(LDFLAGS) -Wl,--no-undefined
_WRAP := -Xlinker --wrap=
PATHWRAP = $(_WRAP)fopen $(_WRAP)freopen $(_WRAP)open $(_WRAP)creat $(_WRAP)access $(_WRAP)__xstat \
$(_WRAP)stat $(_WRAP)lstat $(_WRAP)fopen64 $(_WRAP)open64 $(_WRAP)opendir $(_WRAP)__lxstat \
$(_WRAP)chmod $(_WRAP)chown $(_WRAP)lchown $(_WRAP)symlink $(_WRAP)link $(_WRAP)__lxstat64 \
$(_WRAP)mknod $(_WRAP)utimes $(_WRAP)unlink $(_WRAP)rename $(_WRAP)utime $(_WRAP)__xstat64 \
$(_WRAP)mount $(_WRAP)mkfifo $(_WRAP)mkdir $(_WRAP)rmdir $(_WRAP)scandir $(_WRAP)realpath
LIB_START_EXE = $(PATHWRAP) -static-libgcc -Wl,--start-group
LIB_END_EXE = -Wl,--end-group -lm -ldl $(LIBSTDCXX) -lpthread $(UUID_LIB)
LIB_START_SHLIB = $(PATHWRAP) -static-libgcc -Wl,--start-group
LIB_END_SHLIB = -Wl,--end-group -lm -ldl $(LIBSTDCXXPIC) -lpthread $(UUID_LIB) -l:$(LD_SO) -Wl,--version-script=$(SRCROOT)/devtools/version_script.linux.txt
endif
ifeq ($(OS),Darwin)
LDFLAGS += -stdlib=libc++
OSXVER := $(shell sw_vers -productVersion)
CCACHE := $(SRCROOT)/devtools/bin/osx32/ccache
DEVELOPER_DIR := $(shell /usr/bin/xcode-select -print-path)
XCODEVER := $(shell /usr/bin/xcode-select -version)
USE_DEV_USR_BIN := 0
ifeq (,$(findstring 10.7, $(OSXVER)))
USE_DEV_USR_BIN := 1
endif
ifeq (/Developer, $(DEVELOPER_DIR))
USE_DEV_USR_BIN := 1
endif
ifeq (1,$(USE_DEV_USR_BIN))
COMPILER_BIN_DIR := $(DEVELOPER_DIR)/usr/bin
SDK_DIR := $(DEVELOPER_DIR)/SDKs
else
COMPILER_BIN_DIR := $(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/bin
SDK_DIR := $(DEVELOPER_DIR)/Platforms/MacOSX.platform/Developer/SDKs
endif
SDKROOT ?= $(SDK_DIR)/MacOSX10.9.sdk
#test to see if you have a compiler in the right place, if you don't abort with an error
ifeq ($(wildcard $(COMPILER_BIN_DIR)/clang),)
$(error Unable to find compiler, install and configure XCode)
endif
ifeq ($(wildcard $(COMPILER_BIN_DIR)/clang++),)
$(error Unable to find compiler, install and configure XCode)
endif
ifeq ($(origin AR), default)
AR = libtool -static -o
endif
ifeq ($(origin CC), default)
CC = $(CCACHE) $(COMPILER_BIN_DIR)/clang -Qunused-arguments -Wno-c++11-narrowing -Wno-dangling-else
endif
ifeq ($(origin CXX), default)
CXX = $(CCACHE) $(COMPILER_BIN_DIR)/clang++ -Qunused-arguments -Wno-c++11-narrowing -Wno-dangling-else
endif
LINK ?= $(CXX)
ifeq ($(TARGET_PLATFORM),osx64)
ARCH_FLAGS += -arch x86_64 -m64 -march=core2
else ifeq (,$(findstring -arch x86_64,$(GCC_ExtraCompilerFlags)))
ARCH_FLAGS += -arch i386 -m32 -march=prescott -momit-leaf-frame-pointer -mtune=core2
else
# dirty hack to build a universal binary - don't specify the architecture
ARCH_FLAGS += -arch i386 -Xarch_i386 -march=prescott -Xarch_i386 -mtune=core2 -Xarch_i386 -momit-leaf-frame-pointer -Xarch_x86_64 -march=core2
endif
#FIXME: NOTE:Full path specified because the xcode 4.0 preview has a terribly broken dsymutil, so ref the 3.2 one
GEN_SYM ?= /usr/bin/dsymutil
ifeq ($(CFG),release)
STRIP ?= strip -x -S
else
STRIP ?= true
endif
VSIGN ?= true
CPPFLAGS += -I$(SDKROOT)/usr/include/malloc -ftemplate-depth=1024
CFLAGS += -isysroot $(SDKROOT) -mmacosx-version-min=10.7 -fasm-blocks -fno-color-diagnostics
WARN_FLAGS += -Wno-parentheses -Wno-constant-logical-operand -Wno-deprecated
LIB_START_EXE = -lm -ldl -lpthread
LIB_END_EXE =
LIB_START_SHLIB =
LIB_END_SHLIB =
SHLIBLDFLAGS = $(LDFLAGS) -bundle -flat_namespace -undefined suppress -Wl,-dead_strip -Wl,-no_dead_strip_inits_and_terms
ifeq (lib,$(findstring lib,$(GAMEOUTPUTFILE)))
SHLIBLDFLAGS = $(LDFLAGS) -dynamiclib -current_version 1.0 -compatibility_version 1.0 -install_name @rpath/$(basename $(notdir $(GAMEOUTPUTFILE))).dylib $(SystemLibraries) -Wl,-dead_strip -Wl,-no_dead_strip_inits_and_terms
endif
endif
#
# Profile-directed optimizations.
# Note: Last time these were tested 3/5/08, it actually slowed down the server benchmark by 5%!
#
# First, uncomment these, build, and test. It will generate .gcda and .gcno files where the .o files are.
# PROFILE_LINKER_FLAG=-fprofile-arcs
# PROFILE_COMPILER_FLAG=-fprofile-arcs
#
# Then, comment the above flags out again and rebuild with this flag uncommented:
# PROFILE_COMPILER_FLAG=-fprofile-use
#
#############################################################################
# The compiler command lne for each src code file to compile
#############################################################################
OBJ_DIR = ./obj_$(NAME)_$(TARGET_PLATFORM)$(TARGET_PLATFORM_EXT)/$(CFG)
CPP_TO_OBJ = $(CPPFILES:.cpp=.o)
CXX_TO_OBJ = $(CPP_TO_OBJ:.cxx=.o)
CC_TO_OBJ = $(CXX_TO_OBJ:.cc=.o)
MM_TO_OBJ = $(CC_TO_OBJ:.mm=.o)
C_TO_OBJ = $(MM_TO_OBJ:.c=.o)
OBJS = $(addprefix $(OBJ_DIR)/, $(notdir $(C_TO_OBJ)))
export OBJ_DIR
ifeq ($(MAKE_VERBOSE),1)
QUIET_PREFIX =
QUIET_ECHO_POSTFIX =
else
QUIET_PREFIX = @
QUIET_ECHO_POSTFIX = > /dev/null
endif
ifeq ($(MAKE_CC_VERBOSE),1)
CC += -v
endif
ifeq ($(CONFTYPE),lib)
LIB_File = $(OUTPUTFILE)
endif
ifeq ($(CONFTYPE),dll)
SO_File = $(OUTPUTFILE)
endif
ifeq ($(CONFTYPE),exe)
EXE_File = $(OUTPUTFILE)
endif
# we generate dependencies as a side-effect of compilation now
GEN_DEP_FILE=
PRE_COMPILE_FILE =
POST_COMPILE_FILE =
ifeq ($(BUILDING_MULTI_ARCH),1)
SINGLE_ARCH_CXXFLAGS=$(subst -arch x86_64,,$(CXXFLAGS))
COMPILE_FILE = \
$(QUIET_PREFIX) \
echo "---- $(lastword $(subst /, ,$<)) as MULTIARCH----";\
mkdir -p $(OBJ_DIR) && \
$(CXX) $(SINGLE_ARCH_CXXFLAGS) $(GENDEP_CXXFLAGS) -o $@ -c $< && \
$(CXX) $(CXXFLAGS) -o $@ -c $<
else
COMPILE_FILE = \
$(QUIET_PREFIX) \
echo "---- $(lastword $(subst /, ,$<)) ----";\
mkdir -p $(OBJ_DIR) && \
$(CXX) $(CXXFLAGS) $(GENDEP_CXXFLAGS) -o $@ -c $<
endif
ifneq "$(origin VALVE_NO_AUTO_P4)" "undefined"
P4_EDIT_START = chmod -R +w
P4_EDIT_END = || true
P4_REVERT_START = true
P4_REVERT_END =
else
ifndef P4_EDIT_CHANGELIST
# You can use an environment variable to specify what changelist to check the Linux Binaries out into. Normally the default
# setting is best, but here is an alternate example:
# export P4_EDIT_CHANGELIST_CMD="echo 1424335"
# ?= means that if P4_EDIT_CHANGELIST_CMD is already set it won't be changed.
P4_EDIT_CHANGELIST_CMD ?= p4 changes -c `p4 client -o | grep ^Client | cut -f 2` -s pending | fgrep 'POSIX Auto Checkout' | cut -d' ' -f 2 | tail -n 1
P4_EDIT_CHANGELIST := $(shell $(P4_EDIT_CHANGELIST_CMD))
endif
ifeq ($(P4_EDIT_CHANGELIST),)
# If we haven't found a changelist to check out to then create one. The name must match the one from a few
# lines above or else a new changelist will be created each time.
# Warning: the behavior of 'echo' is not consistent. In bash you need the "-e" option in order for \n to be
# interpreted as a line-feed, but in dash you do not, and if "-e" is passed along then it is printed, which
# confuses p4. So, if you run this command from the bash shell don't forget to add "-e" to the echo command.
P4_EDIT_CHANGELIST = $(shell echo "Change: new\nDescription: POSIX Auto Checkout" | p4 change -i | cut -f 2 -d ' ')
endif
P4_EDIT_START := for f in
P4_EDIT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | p4 -x - edit -c $(P4_EDIT_CHANGELIST); else p4 edit -c $(P4_EDIT_CHANGELIST) $$f; fi; fi; done $(QUIET_ECHO_POSTFIX)
P4_REVERT_START := for f in
P4_REVERT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | p4 -x - revert; else p4 revert $$f; fi; fi; done $(QUIET_ECHO_POSTFIX)
endif
ifeq ($(CONFTYPE),dll)
all: $(OTHER_DEPENDENCIES) $(OBJS) $(GAMEOUTPUTFILE)
@echo $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX)
else
all: $(OTHER_DEPENDENCIES) $(OBJS) $(OUTPUTFILE)
@echo $(OUTPUTFILE) $(QUIET_ECHO_POSTFIX)
endif
.PHONY: clean cleantargets cleanandremove rebuild relink RemoveOutputFile SingleFile
rebuild :
$(MAKE) -f $(firstword $(MAKEFILE_LIST)) cleanandremove
$(MAKE) -f $(firstword $(MAKEFILE_LIST))
# Use the relink target to force to relink the project.
relink: RemoveOutputFile all
RemoveOutputFile:
rm -f $(OUTPUTFILE)
# This rule is so you can say "make SingleFile SingleFilename=/home/myname/valve_main/src/engine/language.cpp" and have it only build that file.
# It basically just translates the full filename to create a dependency on the appropriate .o file so it'll build that.
SingleFile : RemoveSingleFile $(OBJ_DIR)/$(basename $(notdir $(SingleFilename))).o
@echo ""
RemoveSingleFile:
$(QUIET_PREFIX) rm -f $(OBJ_DIR)/$(basename $(notdir $(SingleFilename))).o
clean:
ifneq "$(OBJ_DIR)" ""
$(QUIET_PREFIX) echo "rm -rf $(OBJ_DIR)"
$(QUIET_PREFIX) rm -rf $(OBJ_DIR)
endif
ifneq "$(OUTPUTFILE)" ""
$(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \
echo "p4 revert $(OUTPUTFILE)"; \
$(P4_REVERT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END); \
fi;
endif
ifneq "$(OTHER_DEPENDENCIES)" ""
$(QUIET_PREFIX) echo "rm -f $(OTHER_DEPENDENCIES)"
ifneq "$(GAMEOUTPUTFILE)" ""
endif
$(QUIET_PREFIX) rm -f $(OTHER_DEPENDENCIES)
endif
ifneq "$(GAMEOUTPUTFILE)" ""
$(QUIET_PREFIX) echo "p4 revert $(GAMEOUTPUTFILE)"
$(QUIET_PREFIX) $(P4_REVERT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END)
endif
# Do the above cleaning, except with p4 edit and rm. Reason being ar crs adds and replaces obj files to the
# archive. However if you've renamed or deleted a source file, $(AR) won't remove it. This can leave
# us with archive files that have extra unused symbols, and also potentially cause compilation errors
# when you rename a file and have many duplicate symbols.
cleanandremove:
ifneq "$(OBJ_DIR)" ""
$(QUIET_PREFIX) echo "rm -rf $(OBJ_DIR)"
$(QUIET_PREFIX) -rm -rf $(OBJ_DIR)
endif
ifneq "$(OUTPUTFILE)" ""
$(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \
echo "p4 edit and rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT)"; \
$(P4_EDIT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); \
fi;
$(QUIET_PREFIX) -rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT);
endif
ifneq "$(OTHER_DEPENDENCIES)" ""
$(QUIET_PREFIX) echo "rm -f $(OTHER_DEPENDENCIES)"
$(QUIET_PREFIX) -rm -f $(OTHER_DEPENDENCIES)
endif
ifneq "$(GAMEOUTPUTFILE)" ""
$(QUIET_PREFIX) echo "p4 edit and rm -f $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT)"
$(QUIET_PREFIX) $(P4_EDIT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END)
$(QUIET_PREFIX) -rm -f $(GAMEOUTPUTFILE)
endif
# This just deletes the final targets so it'll do a relink next time we build.
cleantargets:
$(QUIET_PREFIX) rm -f $(OUTPUTFILE) $(GAMEOUTPUTFILE)
$(LIB_File): $(OTHER_DEPENDENCIES) $(OBJS)
$(QUIET_PREFIX) -$(P4_EDIT_START) $(LIB_File) $(P4_EDIT_END);
$(QUIET_PREFIX) $(AR) $(LIB_File) $(OBJS) $(LIBFILES);
SO_GameOutputFile = $(GAMEOUTPUTFILE)
$(SO_GameOutputFile): $(SO_File)
$(QUIET_PREFIX) \
$(P4_EDIT_START) $(GAMEOUTPUTFILE) $(P4_EDIT_END) && \
echo "----" $(QUIET_ECHO_POSTFIX);\
echo "---- COPYING TO $@ [$(CFG)] ----";\
echo "----" $(QUIET_ECHO_POSTFIX);
$(QUIET_PREFIX) -$(P4_EDIT_START) $(GAMEOUTPUTFILE) $(P4_EDIT_END);
$(QUIET_PREFIX) -mkdir -p `dirname $(GAMEOUTPUTFILE)` > /dev/null;
$(QUIET_PREFIX) cp -v $(OUTPUTFILE) $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX);
$(QUIET_PREFIX) -$(P4_EDIT_START) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END);
$(QUIET_PREFIX) $(GEN_SYM) $(GAMEOUTPUTFILE);
$(QUIET_PREFIX) -$(STRIP) $(GAMEOUTPUTFILE);
$(QUIET_PREFIX) $(VSIGN) -signvalve $(GAMEOUTPUTFILE);
$(QUIET_PREFIX) if [ "$(IMPORTLIBRARY)" != "" ]; then\
echo "----" $(QUIET_ECHO_POSTFIX);\
echo "---- COPYING TO IMPORT LIBRARY $(IMPORTLIBRARY) ----";\
echo "----" $(QUIET_ECHO_POSTFIX);\
$(P4_EDIT_START) $(IMPORTLIBRARY) $(P4_EDIT_END) && \
mkdir -p `dirname $(IMPORTLIBRARY)` > /dev/null && \
cp -v $(OUTPUTFILE) $(IMPORTLIBRARY); \
fi;
$(SO_File): $(OTHER_DEPENDENCIES) $(OBJS) $(LIBFILENAMES)
$(QUIET_PREFIX) \
echo "----" $(QUIET_ECHO_POSTFIX);\
echo "---- LINKING $@ [$(CFG)] ----";\
echo "----" $(QUIET_ECHO_POSTFIX);\
\
$(LINK) $(LINK_MAP_FLAGS) $(SHLIBLDFLAGS) $(PROFILE_LINKER_FLAG) -o $(OUTPUTFILE) $(LIB_START_SHLIB) $(OBJS) $(LIBFILES) $(SystemLibraries) $(LIB_END_SHLIB);
$(VSIGN) -signvalve $(OUTPUTFILE);
$(EXE_File) : $(OTHER_DEPENDENCIES) $(OBJS) $(LIBFILENAMES)
$(QUIET_PREFIX) \
echo "----" $(QUIET_ECHO_POSTFIX);\
echo "---- LINKING EXE $@ [$(CFG)] ----";\
echo "----" $(QUIET_ECHO_POSTFIX);\
\
$(P4_EDIT_START) $(OUTPUTFILE) $(P4_EDIT_END);\
$(LINK) $(LINK_MAP_FLAGS) $(LDFLAGS) $(PROFILE_LINKER_FLAG) -o $(OUTPUTFILE) $(LIB_START_EXE) $(OBJS) $(LIBFILES) $(SystemLibraries) $(LIB_END_EXE);
$(QUIET_PREFIX) -$(P4_EDIT_START) $(OUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END);
$(QUIET_PREFIX) $(GEN_SYM) $(OUTPUTFILE);
$(QUIET_PREFIX) -$(STRIP) $(OUTPUTFILE);
$(QUIET_PREFIX) $(VSIGN) -signvalve $(OUTPUTFILE);
tags:
etags -a -C -o $(SRCROOT)/TAGS *.cpp *.cxx *.h *.hxx
P4EXE ?= p4
# DETECT_STRING_CHANGE_BETWEEN_BUILDS is a macro that lets you update the timestamp on a file whenever a string changes between invokations of make
# This lets us know that our compile flags are consistent with the last time we ran and avoid overbuilding
#
# Parameters: $(1) = a unique name as a basis for intermediate variables and file names, the exact name will not be used if you want to give it a name used for $(2).
# $(2) = extra escaped deref or call that you would invoke to fully evaluate the string in $(1)
# A file specified with $(call DETECT_STRING_CHANGE_BETWEEN_BUILDS_TIMESTAMP_FILE,$(1)) will have it's timestamp updated whenever the cached settings change
# Make string substitions on the value so it can be represented cleanly in an "$(ECHO) > file" operation
DETECT_STRING_CHANGE_BETWEEN_BUILDS_STRING_FILTER = $(strip $(subst $$,_dollar,$(subst \\,_bs,$(subst =,_eq,$(subst ',_sq,$(subst ",_dq,$(1)))))))
DETECT_STRING_CHANGE_BETWEEN_BUILDS_TIMESTAMP_FILE = $(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated
define DETECT_STRING_CHANGE_BETWEEN_BUILDS
ifeq "$$(DISABLE_DETECT_STRING_CHANGE_BETWEEN_BUILDS)" ""
include $$(wildcard $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_previous)
unexport $(1)_FILTERED_PREV
$(1)_FILTERED_CURRENT := $$(call DETECT_STRING_CHANGE_BETWEEN_BUILDS_STRING_FILTER,$(2))
unexport $(1)_FILTERED_CURRENT
ifeq "1" "0"
# Invalidate any cached settings whenever the base makefile changes in any way. This is mostly paranoia and we should be able to rely on the second rule by itself
$$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_eval:: $(MAKEFILE_BASE_POSIX_MAK) ; \
$$(QUIET_PREFIX) \
{ \
$$(BUILD_DEBUG_ECHO) detect string change between builds $(1) eval base start && \
if [ -e "$$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated" ]; then \
{ \
$$(BUILD_DEBUG_ECHO) "Discarding $(1) cached value due to changes in \"$$^\""; \
}; \
fi; \
$$(RM) -f $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated; \
$$(RM) -f $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_previous; \
$$(RM) -f $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_eval; \
}
endif
ifneq ("$$($(1)_FILTERED_CURRENT)","$$($(1)_FILTERED_PREV)")
$(1)_WRITE_CHUNK_FUNC = \
WriteStringChunkToPrevFile () \
{ \
$$(ECHO) -n "$$$${1}" >> $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_previous && \
return 0; \
}
#value changed, write out the new value, touch the updated and eval file
$$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_eval:: $(MAKEFILE_BASE_POSIX_MAK) $(COMPILE_DEPENDANT_MAKEFILES)
$$(QUIET_PREFIX) $$(BUILD_DEBUG_ECHO) detect string change between builds $(1) eval incremental start
$$(SPEW_UPDATED_DEPENDENCIES)
$$(QUIET_PREFIX) \
{ \
{ $$(MKDIR) -p $$(OBJ_DIR)/_detect_string_change_between_builds $$(QUIET_ECHO_POSTFIX) || $(TRUE); } && \
$$(BUILD_DEBUG_ECHO) "$(1) changed since last build" && \
$$(TOUCH) $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated && \
$$(ECHO) -n "$(1)_FILTERED_PREV = " > $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_previous; \
}
$$(QUIET_PREFIX) $$(call CHUNK_OUT_STRING_FOR_SHELL_LIMITS,$$($(1)_WRITE_CHUNK_FUNC),WriteStringChunkToPrevFile, ,$$($(1)_FILTERED_CURRENT))
$$(QUIET_PREFIX) $$(TOUCH) $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_eval
else
#value is the same, just touch the eval file
$$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_eval:: $(MAKEFILE_BASE_POSIX_MAK) $(COMPILE_DEPENDANT_MAKEFILES)
$$(QUIET_PREFIX) $$(BUILD_DEBUG_ECHO) detect string change between builds $(1) eval incremental start
$$(SPEW_UPDATED_DEPENDENCIES)
$$(QUIET_PREFIX) \
{ \
{ $$(MKDIR) -p $$(OBJ_DIR)/_detect_string_change_between_builds $$(QUIET_ECHO_POSTFIX) || $(TRUE); } && \
$$(BUILD_DEBUG_ECHO) $(1) unchanged since last build && \
$$(TOUCH) $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_eval; \
}
endif
$$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated: $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_eval ; \
$$(QUIET_PREFIX) \
{ \
if [ ! -e "$$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated" ]; then \
{ \
$$(TOUCH) $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated; \
}; \
fi; \
$$(BUILD_DEBUG_ECHO) detect string change between builds $(1) has evaluated; \
}
else
# if $(DISABLE_DETECT_STRING_CHANGE_BETWEEN_BUILDS) is defined to not do anything, always update the strings when any relevant makefile changes
$$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated: $(MAKEFILE_BASE_POSIX_MAK) $(COMPILE_DEPENDANT_MAKEFILES) ; \
$$(QUIET_PREFIX) \
{
$$(BUILD_DEBUG_ECHO) detect string change between builds $(1) updated disabled start && \
$$(TOUCH) $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated; \
}
endif
endef
unexport DETECT_STRING_CHANGE_BETWEEN_BUILDS
# RUN_RECIPE_ACTION_ONCE ensures you run a recipe action exactly one time among many parallel threads
# and none of the recipes trying to run it return from the function until the action has completed
#
# Parameters: $(1) = unique "already run" sentinel file, $(2) = unique mutex directory, $(3) = action to run
# The existence of the sentinel is used to note that the action has already run and should not run again. The contents of the file are a shell script to replciate the exit status of the action. You are responsible for ensuring this file is deleted before the action will run again
# The existence of the mutex directory causes parallel recipes to spin until it is removed (which automatically happens at the end of the function). You are responsible for ensuring this directory is deleted before any locks can be acquired
# "_prebuild_always::" is a good place to remove both files.
# You are also responsible for ensuring the base directories for both items exist prior to calling RUN_RECIPE_ACTION_ONCE
#
# The sentinel file is used because shell scripts cannot promote environment variables to the parent make process, so the filesystem is used to create a boolean flag out of the sentinel file
# The mutex directory is used because directory creation is atomic and will return an error if the directory cannot be created (already exists)
RUN_RECIPE_ACTION_ONCE = \
( \
until [ -e $(1) ]; do \
{ \
$(MKDIR) -p $(2) > /dev/null 2>&1 && \
{ \
! [ -e $(1) ] && \
{ \
{ $(3); } && \
$(ECHO) "exit 0" > $(1) || \
$(ECHO) "exit 1" > $(1); \
}; \
$(RM) -fr $(2); \
} \
|| \
{ \
$(SLEEP) 1; \
}; \
}; \
done; \
$(SHELL) $(1); \
)
#
# Standard directory creation targets to ensure we can just touch files we need knowing that their directory exists
#
# Ensure $(OBJ_DIR) exists
$(OBJ_DIR)/_create_dir:
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) $(OBJ_DIR)/_create_dir start
$(QUIET_PREFIX) $(MKDIR) -p $(OBJ_DIR) $(QUIET_ECHO_POSTFIX)
$(QUIET_PREFIX) $(TOUCH) $(OBJ_DIR)/_create_dir
PREBUILD_EVENT_ACTION ?= { $(TRUE); }
PREBUILD_EVENT_WRAPPED = \
{ \
{ \
$(BUILD_DEBUG_ECHO) "Pre-Build Event For \"$(NAME)\"" && \
$(call PREBUILD_EVENT_ACTION); \
} \
|| \
{ \
$(ECHO) "Error executing Pre-Build Event for \"$(NAME)\""; \
$(FALSE); \
}; \
}
RUN_PREBUILD_EVENT_ONCE = $(call RUN_RECIPE_ACTION_ONCE,"$(OBJ_DIR)/_ran_prebuild_event","$(OBJ_DIR)/_lock_prebuild_event",$(call PREBUILD_EVENT_WRAPPED))
_prebuild_always::
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _prebuild_always delete prebuild event start
$(QUIET_PREFIX) $(RM) -fr $(OBJ_DIR)/_ran_prebuild_event
$(QUIET_PREFIX) $(RM) -fr $(OBJ_DIR)/_lock_prebuild_event
# Analogous to MSVC Pre-Link Event
PRELINK_EVENT_ACTION ?= { $(TRUE); }
$(OBJ_DIR)/_prelink_event: $(LINK_STEP_DEPENDENCIES) | _prebuild_steps _predepgen_steps _precompile_steps
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _prelink_event start
$(SPEW_UPDATED_DEPENDENCIES)
$(QUIET_PREFIX) \
{ \
{ \
$(call RUN_PREBUILD_EVENT_ONCE) && \
$(BUILD_DEBUG_ECHO) "Pre-Link Event For \"$(NAME)\"" && \
$(call PRELINK_EVENT_ACTION) && \
$(TOUCH) $(OBJ_DIR)/_prelink_event && \
$(RM) -f $(OBJ_DIR)/_prelink_event_failed; \
} \
|| \
{ \
$(ECHO) "Error executing Pre-Link Event for \"$(NAME)\""; \
$(RM) -f $(OBJ_DIR)/_prelink_event; \
$(TOUCH) $(OBJ_DIR)/_prelink_event_failed; \
$(FALSE); \
}; \
}
# Analogous to MSVC Post-Build Event
POSTBUILD_EVENT_ACTION ?= { $(TRUE); }
$(OBJ_DIR)/_postbuild_event: $(ALL_CUSTOM_BUILD_TOOL_OUTPUTS) $(LINK_STEP) $(wildcard $(OBJ_DIR)/_postbuild_event_failed) | _prebuild_steps
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _postbuild_event start
$(SPEW_UPDATED_DEPENDENCIES)
$(QUIET_PREFIX) \
{ \
{ \
$(call RUN_PREBUILD_EVENT_ONCE) && \
$(BUILD_DEBUG_ECHO) "Post-Build Event For \"$(NAME)\"" && \
$(call POSTBUILD_EVENT_ACTION) && \
$(TOUCH) $(OBJ_DIR)/_postbuild_event && \
$(RM) -f $(OBJ_DIR)/_postbuild_event_failed; \
} \
|| \
{ \
$(ECHO) "Error executing Post-Build Event for \"$(NAME)\""; \
$(RM) -f $(OBJ_DIR)/_postbuild_event; \
$(TOUCH) $(OBJ_DIR)/_postbuild_event_failed; \
$(FALSE); \
}; \
}
# Everything that should run before anything starts generating intermediate files
_prebuild_steps: _prebuild_always $(OBJ_DIR)/_create_dir
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _prebuild_steps completed
# Everything that needs to run before depgen. Running after custom build tools because they can generate cpp's we depend on
_predepgen_steps: _prebuild_steps $(ALL_CUSTOM_BUILD_TOOL_OUTPUTS)
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _predepgen_steps completed
# Everything that needs to finish before compiling cpps.
_precompile_steps: _predepgen_steps
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _precompile_steps completed
# Everything that needs to finish before linking
_prelink_steps: $(OBJ_DIR)/_prelink_event
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _prelink_steps completed
# Everything to do after linking
_postbuild_steps: $(OBJ_DIR)/_postbuild_event
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _postbuild_steps completed

2517
devtools/memlog/memlog.cpp Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,237 @@
package Carp;
our $VERSION = '1.0701';
# this file is an utra-lightweight stub. The first time a function is
# called, Carp::Heavy is loaded, and the real short/longmessmess_jmp
# subs are installed
our $MaxEvalLen = 0;
our $Verbose = 0;
our $CarpLevel = 0;
our $MaxArgLen = 64; # How much of each argument to print. 0 = all.
our $MaxArgNums = 8; # How many arguments to print. 0 = all.
require Exporter;
our @ISA = ('Exporter');
our @EXPORT = qw(confess croak carp);
our @EXPORT_OK = qw(cluck verbose longmess shortmess);
our @EXPORT_FAIL = qw(verbose); # hook to enable verbose mode
# if the caller specifies verbose usage ("perl -MCarp=verbose script.pl")
# then the following method will be called by the Exporter which knows
# to do this thanks to @EXPORT_FAIL, above. $_[1] will contain the word
# 'verbose'.
sub export_fail { shift; $Verbose = shift if $_[0] eq 'verbose'; @_ }
# fixed hooks for stashes to point to
sub longmess { goto &longmess_jmp }
sub shortmess { goto &shortmess_jmp }
# these two are replaced when Carp::Heavy is loaded
sub longmess_jmp {
local($@, $!);
eval { require Carp::Heavy };
return $@ if $@;
goto &longmess_real;
}
sub shortmess_jmp {
local($@, $!);
eval { require Carp::Heavy };
return $@ if $@;
goto &shortmess_real;
}
sub croak { die shortmess @_ }
sub confess { die longmess @_ }
sub carp { warn shortmess @_ }
sub cluck { warn longmess @_ }
1;
__END__
=head1 NAME
carp - warn of errors (from perspective of caller)
cluck - warn of errors with stack backtrace
(not exported by default)
croak - die of errors (from perspective of caller)
confess - die of errors with stack backtrace
=head1 SYNOPSIS
use Carp;
croak "We're outta here!";
use Carp qw(cluck);
cluck "This is how we got here!";
=head1 DESCRIPTION
The Carp routines are useful in your own modules because
they act like die() or warn(), but with a message which is more
likely to be useful to a user of your module. In the case of
cluck, confess, and longmess that context is a summary of every
call in the call-stack. For a shorter message you can use C<carp>
or C<croak> which report the error as being from where your module
was called. There is no guarantee that that is where the error
was, but it is a good educated guess.
You can also alter the way the output and logic of C<Carp> works, by
changing some global variables in the C<Carp> namespace. See the
section on C<GLOBAL VARIABLES> below.
Here is a more complete description of how c<carp> and c<croak> work.
What they do is search the call-stack for a function call stack where
they have not been told that there shouldn't be an error. If every
call is marked safe, they give up and give a full stack backtrace
instead. In other words they presume that the first likely looking
potential suspect is guilty. Their rules for telling whether
a call shouldn't generate errors work as follows:
=over 4
=item 1.
Any call from a package to itself is safe.
=item 2.
Packages claim that there won't be errors on calls to or from
packages explicitly marked as safe by inclusion in C<@CARP_NOT>, or
(if that array is empty) C<@ISA>. The ability to override what
@ISA says is new in 5.8.
=item 3.
The trust in item 2 is transitive. If A trusts B, and B
trusts C, then A trusts C. So if you do not override C<@ISA>
with C<@CARP_NOT>, then this trust relationship is identical to,
"inherits from".
=item 4.
Any call from an internal Perl module is safe. (Nothing keeps
user modules from marking themselves as internal to Perl, but
this practice is discouraged.)
=item 5.
Any call to Perl's warning system (eg Carp itself) is safe.
(This rule is what keeps it from reporting the error at the
point where you call C<carp> or C<croak>.)
=item 6.
C<$Carp::CarpLevel> can be set to skip a fixed number of additional
call levels. Using this is not recommended because it is very
difficult to get it to behave correctly.
=back
=head2 Forcing a Stack Trace
As a debugging aid, you can force Carp to treat a croak as a confess
and a carp as a cluck across I<all> modules. In other words, force a
detailed stack trace to be given. This can be very helpful when trying
to understand why, or from where, a warning or error is being generated.
This feature is enabled by 'importing' the non-existent symbol
'verbose'. You would typically enable it by saying
perl -MCarp=verbose script.pl
or by including the string C<MCarp=verbose> in the PERL5OPT
environment variable.
Alternately, you can set the global variable C<$Carp::Verbose> to true.
See the C<GLOBAL VARIABLES> section below.
=head1 GLOBAL VARIABLES
=head2 $Carp::MaxEvalLen
This variable determines how many characters of a string-eval are to
be shown in the output. Use a value of C<0> to show all text.
Defaults to C<0>.
=head2 $Carp::MaxArgLen
This variable determines how many characters of each argument to a
function to print. Use a value of C<0> to show the full length of the
argument.
Defaults to C<64>.
=head2 $Carp::MaxArgNums
This variable determines how many arguments to each function to show.
Use a value of C<0> to show all arguments to a function call.
Defaults to C<8>.
=head2 $Carp::Verbose
This variable makes C<carp> and C<cluck> generate stack backtraces
just like C<cluck> and C<confess>. This is how C<use Carp 'verbose'>
is implemented internally.
Defaults to C<0>.
=head2 %Carp::Internal
This says what packages are internal to Perl. C<Carp> will never
report an error as being from a line in a package that is internal to
Perl. For example:
$Carp::Internal{ __PACKAGE__ }++;
# time passes...
sub foo { ... or confess("whatever") };
would give a full stack backtrace starting from the first caller
outside of __PACKAGE__. (Unless that package was also internal to
Perl.)
=head2 %Carp::CarpInternal
This says which packages are internal to Perl's warning system. For
generating a full stack backtrace this is the same as being internal
to Perl, the stack backtrace will not start inside packages that are
listed in C<%Carp::CarpInternal>. But it is slightly different for
the summary message generated by C<carp> or C<croak>. There errors
will not be reported on any lines that are calling packages in
C<%Carp::CarpInternal>.
For example C<Carp> itself is listed in C<%Carp::CarpInternal>.
Therefore the full stack backtrace from C<confess> will not start
inside of C<Carp>, and the short message from calling C<croak> is
not placed on the line where C<croak> was called.
=head2 $Carp::CarpLevel
This variable determines how many additional call frames are to be
skipped that would not otherwise be when reporting where an error
occurred on a call to one of C<Carp>'s functions. It is fairly easy
to count these call frames on calls that generate a full stack
backtrace. However it is much harder to do this accounting for calls
that generate a short message. Usually people skip too many call
frames. If they are lucky they skip enough that C<Carp> goes all of
the way through the call stack, realizes that something is wrong, and
then generates a full stack backtrace. If they are unlucky then the
error is reported from somewhere misleading very high in the call
stack.
Therefore it is best to avoid C<$Carp::CarpLevel>. Instead use
C<@CARP_NOT>, C<%Carp::Internal> and %Carp::CarpInternal>.
Defaults to C<0>.
=head1 BUGS
The Carp routines don't handle exception objects currently.
If called with a first argument that is a reference, they simply
call die() or warn(), as appropriate.

View File

@ -0,0 +1,441 @@
package Exporter;
require 5.006;
# Be lean.
#use strict;
#no strict 'refs';
our $Debug = 0;
our $ExportLevel = 0;
our $Verbose ||= 0;
our $VERSION = '5.60';
our (%Cache);
# Carp does this now for us, so we can finally live w/o Carp
#$Carp::Internal{Exporter} = 1;
sub as_heavy {
require Exporter::Heavy;
# Unfortunately, this does not work if the caller is aliased as *name = \&foo
# Thus the need to create a lot of identical subroutines
my $c = (caller(1))[3];
$c =~ s/.*:://;
\&{"Exporter::Heavy::heavy_$c"};
}
sub export {
goto &{as_heavy()};
}
sub import {
my $pkg = shift;
my $callpkg = caller($ExportLevel);
if ($pkg eq "Exporter" and @_ and $_[0] eq "import") {
*{$callpkg."::import"} = \&import;
return;
}
# We *need* to treat @{"$pkg\::EXPORT_FAIL"} since Carp uses it :-(
my($exports, $fail) = (\@{"$pkg\::EXPORT"}, \@{"$pkg\::EXPORT_FAIL"});
return export $pkg, $callpkg, @_
if $Verbose or $Debug or @$fail > 1;
my $export_cache = ($Cache{$pkg} ||= {});
my $args = @_ or @_ = @$exports;
local $_;
if ($args and not %$export_cache) {
s/^&//, $export_cache->{$_} = 1
foreach (@$exports, @{"$pkg\::EXPORT_OK"});
}
my $heavy;
# Try very hard not to use {} and hence have to enter scope on the foreach
# We bomb out of the loop with last as soon as heavy is set.
if ($args or $fail) {
($heavy = (/\W/ or $args and not exists $export_cache->{$_}
or @$fail and $_ eq $fail->[0])) and last
foreach (@_);
} else {
($heavy = /\W/) and last
foreach (@_);
}
return export $pkg, $callpkg, ($args ? @_ : ()) if $heavy;
local $SIG{__WARN__} =
sub {require Carp; &Carp::carp};
# shortcut for the common case of no type character
*{"$callpkg\::$_"} = \&{"$pkg\::$_"} foreach @_;
}
# Default methods
sub export_fail {
my $self = shift;
@_;
}
# Unfortunately, caller(1)[3] "does not work" if the caller is aliased as
# *name = \&foo. Thus the need to create a lot of identical subroutines
# Otherwise we could have aliased them to export().
sub export_to_level {
goto &{as_heavy()};
}
sub export_tags {
goto &{as_heavy()};
}
sub export_ok_tags {
goto &{as_heavy()};
}
sub require_version {
goto &{as_heavy()};
}
1;
__END__
=head1 NAME
Exporter - Implements default import method for modules
=head1 SYNOPSIS
In module YourModule.pm:
package YourModule;
require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = qw(munge frobnicate); # symbols to export on request
or
package YourModule;
use Exporter 'import'; # gives you Exporter's import() method directly
@EXPORT_OK = qw(munge frobnicate); # symbols to export on request
In other files which wish to use YourModule:
use ModuleName qw(frobnicate); # import listed symbols
frobnicate ($left, $right) # calls YourModule::frobnicate
=head1 DESCRIPTION
The Exporter module implements an C<import> method which allows a module
to export functions and variables to its users' namespaces. Many modules
use Exporter rather than implementing their own C<import> method because
Exporter provides a highly flexible interface, with an implementation optimised
for the common case.
Perl automatically calls the C<import> method when processing a
C<use> statement for a module. Modules and C<use> are documented
in L<perlfunc> and L<perlmod>. Understanding the concept of
modules and how the C<use> statement operates is important to
understanding the Exporter.
=head2 How to Export
The arrays C<@EXPORT> and C<@EXPORT_OK> in a module hold lists of
symbols that are going to be exported into the users name space by
default, or which they can request to be exported, respectively. The
symbols can represent functions, scalars, arrays, hashes, or typeglobs.
The symbols must be given by full name with the exception that the
ampersand in front of a function is optional, e.g.
@EXPORT = qw(afunc $scalar @array); # afunc is a function
@EXPORT_OK = qw(&bfunc %hash *typeglob); # explicit prefix on &bfunc
If you are only exporting function names it is recommended to omit the
ampersand, as the implementation is faster this way.
=head2 Selecting What To Export
Do B<not> export method names!
Do B<not> export anything else by default without a good reason!
Exports pollute the namespace of the module user. If you must export
try to use @EXPORT_OK in preference to @EXPORT and avoid short or
common symbol names to reduce the risk of name clashes.
Generally anything not exported is still accessible from outside the
module using the ModuleName::item_name (or $blessed_ref-E<gt>method)
syntax. By convention you can use a leading underscore on names to
informally indicate that they are 'internal' and not for public use.
(It is actually possible to get private functions by saying:
my $subref = sub { ... };
$subref->(@args); # Call it as a function
$obj->$subref(@args); # Use it as a method
However if you use them for methods it is up to you to figure out
how to make inheritance work.)
As a general rule, if the module is trying to be object oriented
then export nothing. If it's just a collection of functions then
@EXPORT_OK anything but use @EXPORT with caution. For function and
method names use barewords in preference to names prefixed with
ampersands for the export lists.
Other module design guidelines can be found in L<perlmod>.
=head2 How to Import
In other files which wish to use your module there are three basic ways for
them to load your module and import its symbols:
=over 4
=item C<use ModuleName;>
This imports all the symbols from ModuleName's @EXPORT into the namespace
of the C<use> statement.
=item C<use ModuleName ();>
This causes perl to load your module but does not import any symbols.
=item C<use ModuleName qw(...);>
This imports only the symbols listed by the caller into their namespace.
All listed symbols must be in your @EXPORT or @EXPORT_OK, else an error
occurs. The advanced export features of Exporter are accessed like this,
but with list entries that are syntactically distinct from symbol names.
=back
Unless you want to use its advanced features, this is probably all you
need to know to use Exporter.
=head1 Advanced features
=head2 Specialised Import Lists
If any of the entries in an import list begins with !, : or / then
the list is treated as a series of specifications which either add to
or delete from the list of names to import. They are processed left to
right. Specifications are in the form:
[!]name This name only
[!]:DEFAULT All names in @EXPORT
[!]:tag All names in $EXPORT_TAGS{tag} anonymous list
[!]/pattern/ All names in @EXPORT and @EXPORT_OK which match
A leading ! indicates that matching names should be deleted from the
list of names to import. If the first specification is a deletion it
is treated as though preceded by :DEFAULT. If you just want to import
extra names in addition to the default set you will still need to
include :DEFAULT explicitly.
e.g., Module.pm defines:
@EXPORT = qw(A1 A2 A3 A4 A5);
@EXPORT_OK = qw(B1 B2 B3 B4 B5);
%EXPORT_TAGS = (T1 => [qw(A1 A2 B1 B2)], T2 => [qw(A1 A2 B3 B4)]);
Note that you cannot use tags in @EXPORT or @EXPORT_OK.
Names in EXPORT_TAGS must also appear in @EXPORT or @EXPORT_OK.
An application using Module can say something like:
use Module qw(:DEFAULT :T2 !B3 A3);
Other examples include:
use Socket qw(!/^[AP]F_/ !SOMAXCONN !SOL_SOCKET);
use POSIX qw(:errno_h :termios_h !TCSADRAIN !/^EXIT/);
Remember that most patterns (using //) will need to be anchored
with a leading ^, e.g., C</^EXIT/> rather than C</EXIT/>.
You can say C<BEGIN { $Exporter::Verbose=1 }> to see how the
specifications are being processed and what is actually being imported
into modules.
=head2 Exporting without using Exporter's import method
Exporter has a special method, 'export_to_level' which is used in situations
where you can't directly call Exporter's import method. The export_to_level
method looks like:
MyPackage->export_to_level($where_to_export, $package, @what_to_export);
where $where_to_export is an integer telling how far up the calling stack
to export your symbols, and @what_to_export is an array telling what
symbols *to* export (usually this is @_). The $package argument is
currently unused.
For example, suppose that you have a module, A, which already has an
import function:
package A;
@ISA = qw(Exporter);
@EXPORT_OK = qw ($b);
sub import
{
$A::b = 1; # not a very useful import method
}
and you want to Export symbol $A::b back to the module that called
package A. Since Exporter relies on the import method to work, via
inheritance, as it stands Exporter::import() will never get called.
Instead, say the following:
package A;
@ISA = qw(Exporter);
@EXPORT_OK = qw ($b);
sub import
{
$A::b = 1;
A->export_to_level(1, @_);
}
This will export the symbols one level 'above' the current package - ie: to
the program or module that used package A.
Note: Be careful not to modify C<@_> at all before you call export_to_level
- or people using your package will get very unexplained results!
=head2 Exporting without inheriting from Exporter
By including Exporter in your @ISA you inherit an Exporter's import() method
but you also inherit several other helper methods which you probably don't
want. To avoid this you can do
package YourModule;
use Exporter qw( import );
which will export Exporter's own import() method into YourModule.
Everything will work as before but you won't need to include Exporter in
@YourModule::ISA.
=head2 Module Version Checking
The Exporter module will convert an attempt to import a number from a
module into a call to $module_name-E<gt>require_version($value). This can
be used to validate that the version of the module being used is
greater than or equal to the required version.
The Exporter module supplies a default require_version method which
checks the value of $VERSION in the exporting module.
Since the default require_version method treats the $VERSION number as
a simple numeric value it will regard version 1.10 as lower than
1.9. For this reason it is strongly recommended that you use numbers
with at least two decimal places, e.g., 1.09.
=head2 Managing Unknown Symbols
In some situations you may want to prevent certain symbols from being
exported. Typically this applies to extensions which have functions
or constants that may not exist on some systems.
The names of any symbols that cannot be exported should be listed
in the C<@EXPORT_FAIL> array.
If a module attempts to import any of these symbols the Exporter
will give the module an opportunity to handle the situation before
generating an error. The Exporter will call an export_fail method
with a list of the failed symbols:
@failed_symbols = $module_name->export_fail(@failed_symbols);
If the export_fail method returns an empty list then no error is
recorded and all the requested symbols are exported. If the returned
list is not empty then an error is generated for each symbol and the
export fails. The Exporter provides a default export_fail method which
simply returns the list unchanged.
Uses for the export_fail method include giving better error messages
for some symbols and performing lazy architectural checks (put more
symbols into @EXPORT_FAIL by default and then take them out if someone
actually tries to use them and an expensive check shows that they are
usable on that platform).
=head2 Tag Handling Utility Functions
Since the symbols listed within %EXPORT_TAGS must also appear in either
@EXPORT or @EXPORT_OK, two utility functions are provided which allow
you to easily add tagged sets of symbols to @EXPORT or @EXPORT_OK:
%EXPORT_TAGS = (foo => [qw(aa bb cc)], bar => [qw(aa cc dd)]);
Exporter::export_tags('foo'); # add aa, bb and cc to @EXPORT
Exporter::export_ok_tags('bar'); # add aa, cc and dd to @EXPORT_OK
Any names which are not tags are added to @EXPORT or @EXPORT_OK
unchanged but will trigger a warning (with C<-w>) to avoid misspelt tags
names being silently added to @EXPORT or @EXPORT_OK. Future versions
may make this a fatal error.
=head2 Generating combined tags
If several symbol categories exist in %EXPORT_TAGS, it's usually
useful to create the utility ":all" to simplify "use" statements.
The simplest way to do this is:
%EXPORT_TAGS = (foo => [qw(aa bb cc)], bar => [qw(aa cc dd)]);
# add all the other ":class" tags to the ":all" class,
# deleting duplicates
{
my %seen;
push @{$EXPORT_TAGS{all}},
grep {!$seen{$_}++} @{$EXPORT_TAGS{$_}} foreach keys %EXPORT_TAGS;
}
CGI.pm creates an ":all" tag which contains some (but not really
all) of its categories. That could be done with one small
change:
# add some of the other ":class" tags to the ":all" class,
# deleting duplicates
{
my %seen;
push @{$EXPORT_TAGS{all}},
grep {!$seen{$_}++} @{$EXPORT_TAGS{$_}}
foreach qw/html2 html3 netscape form cgi internal/;
}
Note that the tag names in %EXPORT_TAGS don't have the leading ':'.
=head2 C<AUTOLOAD>ed Constants
Many modules make use of C<AUTOLOAD>ing for constant subroutines to
avoid having to compile and waste memory on rarely used values (see
L<perlsub> for details on constant subroutines). Calls to such
constant subroutines are not optimized away at compile time because
they can't be checked at compile time for constancy.
Even if a prototype is available at compile time, the body of the
subroutine is not (it hasn't been C<AUTOLOAD>ed yet). perl needs to
examine both the C<()> prototype and the body of a subroutine at
compile time to detect that it can safely replace calls to that
subroutine with the constant value.
A workaround for this is to call the constants once in a C<BEGIN> block:
package My ;
use Socket ;
foo( SO_LINGER ); ## SO_LINGER NOT optimized away; called at runtime
BEGIN { SO_LINGER }
foo( SO_LINGER ); ## SO_LINGER optimized away at compile time.
This forces the C<AUTOLOAD> for C<SO_LINGER> to take place before
SO_LINGER is encountered later in C<My> package.
If you are writing a package that C<AUTOLOAD>s, consider forcing
an C<AUTOLOAD> for any constants explicitly imported by other packages
or which are usually used when your package is C<use>d.
=cut

View File

@ -0,0 +1,244 @@
package Fcntl;
=head1 NAME
Fcntl - load the C Fcntl.h defines
=head1 SYNOPSIS
use Fcntl;
use Fcntl qw(:DEFAULT :flock);
=head1 DESCRIPTION
This module is just a translation of the C F<fcntl.h> file.
Unlike the old mechanism of requiring a translated F<fcntl.ph>
file, this uses the B<h2xs> program (see the Perl source distribution)
and your native C compiler. This means that it has a
far more likely chance of getting the numbers right.
=head1 NOTE
Only C<#define> symbols get translated; you must still correctly
pack up your own arguments to pass as args for locking functions, etc.
=head1 EXPORTED SYMBOLS
By default your system's F_* and O_* constants (eg, F_DUPFD and
O_CREAT) and the FD_CLOEXEC constant are exported into your namespace.
You can request that the flock() constants (LOCK_SH, LOCK_EX, LOCK_NB
and LOCK_UN) be provided by using the tag C<:flock>. See L<Exporter>.
You can request that the old constants (FAPPEND, FASYNC, FCREAT,
FDEFER, FEXCL, FNDELAY, FNONBLOCK, FSYNC, FTRUNC) be provided for
compatibility reasons by using the tag C<:Fcompat>. For new
applications the newer versions of these constants are suggested
(O_APPEND, O_ASYNC, O_CREAT, O_DEFER, O_EXCL, O_NDELAY, O_NONBLOCK,
O_SYNC, O_TRUNC).
For ease of use also the SEEK_* constants (for seek() and sysseek(),
e.g. SEEK_END) and the S_I* constants (for chmod() and stat()) are
available for import. They can be imported either separately or using
the tags C<:seek> and C<:mode>.
Please refer to your native fcntl(2), open(2), fseek(3), lseek(2)
(equal to Perl's seek() and sysseek(), respectively), and chmod(2)
documentation to see what constants are implemented in your system.
See L<perlopentut> to learn about the uses of the O_* constants
with sysopen().
See L<perlfunc/seek> and L<perlfunc/sysseek> about the SEEK_* constants.
See L<perlfunc/stat> about the S_I* constants.
=cut
use strict;
our($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS, $AUTOLOAD);
require Exporter;
use XSLoader ();
@ISA = qw(Exporter);
BEGIN {
$VERSION = "1.06";
}
# Items to export into callers namespace by default
# (move infrequently used names to @EXPORT_OK below)
@EXPORT =
qw(
FD_CLOEXEC
F_ALLOCSP
F_ALLOCSP64
F_COMPAT
F_DUP2FD
F_DUPFD
F_EXLCK
F_FREESP
F_FREESP64
F_FSYNC
F_FSYNC64
F_GETFD
F_GETFL
F_GETLK
F_GETLK64
F_GETOWN
F_NODNY
F_POSIX
F_RDACC
F_RDDNY
F_RDLCK
F_RWACC
F_RWDNY
F_SETFD
F_SETFL
F_SETLK
F_SETLK64
F_SETLKW
F_SETLKW64
F_SETOWN
F_SHARE
F_SHLCK
F_UNLCK
F_UNSHARE
F_WRACC
F_WRDNY
F_WRLCK
O_ACCMODE
O_ALIAS
O_APPEND
O_ASYNC
O_BINARY
O_CREAT
O_DEFER
O_DIRECT
O_DIRECTORY
O_DSYNC
O_EXCL
O_EXLOCK
O_LARGEFILE
O_NDELAY
O_NOCTTY
O_NOFOLLOW
O_NOINHERIT
O_NONBLOCK
O_RANDOM
O_RAW
O_RDONLY
O_RDWR
O_RSRC
O_RSYNC
O_SEQUENTIAL
O_SHLOCK
O_SYNC
O_TEMPORARY
O_TEXT
O_TRUNC
O_WRONLY
);
# Other items we are prepared to export if requested
@EXPORT_OK = qw(
DN_ACCESS
DN_ATTRIB
DN_CREATE
DN_DELETE
DN_MODIFY
DN_MULTISHOT
DN_RENAME
FAPPEND
FASYNC
FCREAT
FDEFER
FDSYNC
FEXCL
FLARGEFILE
FNDELAY
FNONBLOCK
FRSYNC
FSYNC
FTRUNC
F_GETLEASE
F_GETSIG
F_NOTIFY
F_SETLEASE
F_SETSIG
LOCK_EX
LOCK_MAND
LOCK_NB
LOCK_READ
LOCK_RW
LOCK_SH
LOCK_UN
LOCK_WRITE
O_IGNORE_CTTY
O_NOATIME
O_NOLINK
O_NOTRANS
SEEK_CUR
SEEK_END
SEEK_SET
S_IFSOCK S_IFBLK S_IFCHR S_IFIFO S_IFWHT S_ENFMT
S_IREAD S_IWRITE S_IEXEC
S_IRGRP S_IWGRP S_IXGRP S_IRWXG
S_IROTH S_IWOTH S_IXOTH S_IRWXO
S_IRUSR S_IWUSR S_IXUSR S_IRWXU
S_ISUID S_ISGID S_ISVTX S_ISTXT
_S_IFMT S_IFREG S_IFDIR S_IFLNK
&S_ISREG &S_ISDIR &S_ISLNK &S_ISSOCK &S_ISBLK &S_ISCHR &S_ISFIFO
&S_ISWHT &S_ISENFMT &S_IFMT &S_IMODE
);
# Named groups of exports
%EXPORT_TAGS = (
'flock' => [qw(LOCK_SH LOCK_EX LOCK_NB LOCK_UN)],
'Fcompat' => [qw(FAPPEND FASYNC FCREAT FDEFER FDSYNC FEXCL FLARGEFILE
FNDELAY FNONBLOCK FRSYNC FSYNC FTRUNC)],
'seek' => [qw(SEEK_SET SEEK_CUR SEEK_END)],
'mode' => [qw(S_ISUID S_ISGID S_ISVTX S_ISTXT
_S_IFMT S_IFREG S_IFDIR S_IFLNK
S_IFSOCK S_IFBLK S_IFCHR S_IFIFO S_IFWHT S_ENFMT
S_IRUSR S_IWUSR S_IXUSR S_IRWXU
S_IRGRP S_IWGRP S_IXGRP S_IRWXG
S_IROTH S_IWOTH S_IXOTH S_IRWXO
S_IREAD S_IWRITE S_IEXEC
S_ISREG S_ISDIR S_ISLNK S_ISSOCK
S_ISBLK S_ISCHR S_ISFIFO
S_ISWHT S_ISENFMT
S_IFMT S_IMODE
)],
);
# Force the constants to become inlined
BEGIN {
XSLoader::load 'Fcntl', $VERSION;
}
sub S_IFMT { @_ ? ( $_[0] & _S_IFMT() ) : _S_IFMT() }
sub S_IMODE { $_[0] & 07777 }
sub S_ISREG { ( $_[0] & _S_IFMT() ) == S_IFREG() }
sub S_ISDIR { ( $_[0] & _S_IFMT() ) == S_IFDIR() }
sub S_ISLNK { ( $_[0] & _S_IFMT() ) == S_IFLNK() }
sub S_ISSOCK { ( $_[0] & _S_IFMT() ) == S_IFSOCK() }
sub S_ISBLK { ( $_[0] & _S_IFMT() ) == S_IFBLK() }
sub S_ISCHR { ( $_[0] & _S_IFMT() ) == S_IFCHR() }
sub S_ISFIFO { ( $_[0] & _S_IFMT() ) == S_IFIFO() }
sub S_ISWHT { ( $_[0] & _S_IFMT() ) == S_IFWHT() }
sub S_ISENFMT { ( $_[0] & _S_IFMT() ) == S_IFENFMT() }
sub AUTOLOAD {
(my $constname = $AUTOLOAD) =~ s/.*:://;
die "&Fcntl::constant not defined" if $constname eq 'constant';
my ($error, $val) = constant($constname);
if ($error) {
my (undef,$file,$line) = caller;
die "$error at $file line $line.\n";
}
no strict 'refs';
*$AUTOLOAD = sub { $val };
goto &$AUTOLOAD;
}
1;

View File

@ -0,0 +1,350 @@
# Generated from XSLoader.pm.PL (resolved %Config::Config value)
package XSLoader;
$VERSION = "0.08";
#use strict;
# enable debug/trace messages from DynaLoader perl code
# $dl_debug = $ENV{PERL_DL_DEBUG} || 0 unless defined $dl_debug;
my $dl_dlext = 'dll';
package DynaLoader;
# No prizes for guessing why we don't say 'bootstrap DynaLoader;' here.
# NOTE: All dl_*.xs (including dl_none.xs) define a dl_error() XSUB
boot_DynaLoader('DynaLoader') if defined(&boot_DynaLoader) &&
!defined(&dl_error);
package XSLoader;
sub load {
package DynaLoader;
die q{XSLoader::load('Your::Module', $Your::Module::VERSION)} unless @_;
my($module) = $_[0];
# work with static linking too
my $b = "$module\::bootstrap";
goto &$b if defined &$b;
goto retry unless $module and defined &dl_load_file;
my @modparts = split(/::/,$module);
my $modfname = $modparts[-1];
my $modpname = join('/',@modparts);
my $modlibname = (caller())[1];
my $c = @modparts;
$modlibname =~ s,[\\/][^\\/]+$,, while $c--; # Q&D basename
my $file = "$modlibname/auto/$modpname/$modfname.$dl_dlext";
# print STDERR "XSLoader::load for $module ($file)\n" if $dl_debug;
my $bs = $file;
$bs =~ s/(\.\w+)?(;\d*)?$/\.bs/; # look for .bs 'beside' the library
goto retry if not -f $file or -s $bs;
my $bootname = "boot_$module";
$bootname =~ s/\W/_/g;
@DynaLoader::dl_require_symbols = ($bootname);
my $boot_symbol_ref;
# Many dynamic extension loading problems will appear to come from
# this section of code: XYZ failed at line 123 of DynaLoader.pm.
# Often these errors are actually occurring in the initialisation
# C code of the extension XS file. Perl reports the error as being
# in this perl code simply because this was the last perl code
# it executed.
my $libref = dl_load_file($file, 0) or do {
require Carp;
Carp::croak("Can't load '$file' for module $module: " . dl_error());
};
push(@DynaLoader::dl_librefs,$libref); # record loaded object
my @unresolved = dl_undef_symbols();
if (@unresolved) {
require Carp;
Carp::carp("Undefined symbols present after loading $file: @unresolved\n");
}
$boot_symbol_ref = dl_find_symbol($libref, $bootname) or do {
require Carp;
Carp::croak("Can't find '$bootname' symbol in $file\n");
};
push(@DynaLoader::dl_modules, $module); # record loaded module
boot:
my $xs = dl_install_xsub("${module}::bootstrap", $boot_symbol_ref, $file);
# See comment block above
push(@DynaLoader::dl_shared_objects, $file); # record files loaded
return &$xs(@_);
retry:
my $bootstrap_inherit = DynaLoader->can('bootstrap_inherit') ||
XSLoader->can('bootstrap_inherit');
goto &$bootstrap_inherit;
}
# Versions of DynaLoader prior to 5.6.0 don't have this function.
sub bootstrap_inherit {
package DynaLoader;
my $module = $_[0];
local *DynaLoader::isa = *{"$module\::ISA"};
local @DynaLoader::isa = (@DynaLoader::isa, 'DynaLoader');
# Cannot goto due to delocalization. Will report errors on a wrong line?
require DynaLoader;
DynaLoader::bootstrap(@_);
}
1;
__END__
=head1 NAME
XSLoader - Dynamically load C libraries into Perl code
=head1 VERSION
Version 0.08
=head1 SYNOPSIS
package YourPackage;
use XSLoader;
XSLoader::load 'YourPackage', $YourPackage::VERSION;
=head1 DESCRIPTION
This module defines a standard I<simplified> interface to the dynamic
linking mechanisms available on many platforms. Its primary purpose is
to implement cheap automatic dynamic loading of Perl modules.
For a more complicated interface, see L<DynaLoader>. Many (most)
features of C<DynaLoader> are not implemented in C<XSLoader>, like for
example the C<dl_load_flags>, not honored by C<XSLoader>.
=head2 Migration from C<DynaLoader>
A typical module using L<DynaLoader|DynaLoader> starts like this:
package YourPackage;
require DynaLoader;
our @ISA = qw( OnePackage OtherPackage DynaLoader );
our $VERSION = '0.01';
bootstrap YourPackage $VERSION;
Change this to
package YourPackage;
use XSLoader;
our @ISA = qw( OnePackage OtherPackage );
our $VERSION = '0.01';
XSLoader::load 'YourPackage', $VERSION;
In other words: replace C<require DynaLoader> by C<use XSLoader>, remove
C<DynaLoader> from C<@ISA>, change C<bootstrap> by C<XSLoader::load>. Do not
forget to quote the name of your package on the C<XSLoader::load> line,
and add comma (C<,>) before the arguments (C<$VERSION> above).
Of course, if C<@ISA> contained only C<DynaLoader>, there is no need to have
the C<@ISA> assignment at all; moreover, if instead of C<our> one uses the
more backward-compatible
use vars qw($VERSION @ISA);
one can remove this reference to C<@ISA> together with the C<@ISA> assignment.
If no C<$VERSION> was specified on the C<bootstrap> line, the last line becomes
XSLoader::load 'YourPackage';
=head2 Backward compatible boilerplate
If you want to have your cake and eat it too, you need a more complicated
boilerplate.
package YourPackage;
use vars qw($VERSION @ISA);
@ISA = qw( OnePackage OtherPackage );
$VERSION = '0.01';
eval {
require XSLoader;
XSLoader::load('YourPackage', $VERSION);
1;
} or do {
require DynaLoader;
push @ISA, 'DynaLoader';
bootstrap YourPackage $VERSION;
};
The parentheses about C<XSLoader::load()> arguments are needed since we replaced
C<use XSLoader> by C<require>, so the compiler does not know that a function
C<XSLoader::load()> is present.
This boilerplate uses the low-overhead C<XSLoader> if present; if used with
an antic Perl which has no C<XSLoader>, it falls back to using C<DynaLoader>.
=head1 Order of initialization: early load()
I<Skip this section if the XSUB functions are supposed to be called from other
modules only; read it only if you call your XSUBs from the code in your module,
or have a C<BOOT:> section in your XS file (see L<perlxs/"The BOOT: Keyword">).
What is described here is equally applicable to the L<DynaLoader|DynaLoader>
interface.>
A sufficiently complicated module using XS would have both Perl code (defined
in F<YourPackage.pm>) and XS code (defined in F<YourPackage.xs>). If this
Perl code makes calls into this XS code, and/or this XS code makes calls to
the Perl code, one should be careful with the order of initialization.
The call to C<XSLoader::load()> (or C<bootstrap()>) has three side effects:
=over
=item *
if C<$VERSION> was specified, a sanity check is done to ensure that the
versions of the F<.pm> and the (compiled) F<.xs> parts are compatible;
=item *
the XSUBs are made accessible from Perl;
=item *
if a C<BOOT:> section was present in the F<.xs> file, the code there is called.
=back
Consequently, if the code in the F<.pm> file makes calls to these XSUBs, it is
convenient to have XSUBs installed before the Perl code is defined; for
example, this makes prototypes for XSUBs visible to this Perl code.
Alternatively, if the C<BOOT:> section makes calls to Perl functions (or
uses Perl variables) defined in the F<.pm> file, they must be defined prior to
the call to C<XSLoader::load()> (or C<bootstrap()>).
The first situation being much more frequent, it makes sense to rewrite the
boilerplate as
package YourPackage;
use XSLoader;
use vars qw($VERSION @ISA);
BEGIN {
@ISA = qw( OnePackage OtherPackage );
$VERSION = '0.01';
# Put Perl code used in the BOOT: section here
XSLoader::load 'YourPackage', $VERSION;
}
# Put Perl code making calls into XSUBs here
=head2 The most hairy case
If the interdependence of your C<BOOT:> section and Perl code is
more complicated than this (e.g., the C<BOOT:> section makes calls to Perl
functions which make calls to XSUBs with prototypes), get rid of the C<BOOT:>
section altogether. Replace it with a function C<onBOOT()>, and call it like
this:
package YourPackage;
use XSLoader;
use vars qw($VERSION @ISA);
BEGIN {
@ISA = qw( OnePackage OtherPackage );
$VERSION = '0.01';
XSLoader::load 'YourPackage', $VERSION;
}
# Put Perl code used in onBOOT() function here; calls to XSUBs are
# prototype-checked.
onBOOT;
# Put Perl initialization code assuming that XS is initialized here
=head1 DIAGNOSTICS
=over
=item C<Can't find '%s' symbol in %s>
B<(F)> The bootstrap symbol could not be found in the extension module.
=item C<Can't load '%s' for module %s: %s>
B<(F)> The loading or initialisation of the extension module failed.
The detailed error follows.
=item C<Undefined symbols present after loading %s: %s>
B<(W)> As the message says, some symbols stay undefined although the
extension module was correctly loaded and initialised. The list of undefined
symbols follows.
=item C<XSLoader::load('Your::Module', $Your::Module::VERSION)>
B<(F)> You tried to invoke C<load()> without any argument. You must supply
a module name, and optionally its version.
=back
=head1 LIMITATIONS
To reduce the overhead as much as possible, only one possible location
is checked to find the extension DLL (this location is where C<make install>
would put the DLL). If not found, the search for the DLL is transparently
delegated to C<DynaLoader>, which looks for the DLL along the C<@INC> list.
In particular, this is applicable to the structure of C<@INC> used for testing
not-yet-installed extensions. This means that running uninstalled extensions
may have much more overhead than running the same extensions after
C<make install>.
=head1 BUGS
Please report any bugs or feature requests via the perlbug(1) utility.
=head1 SEE ALSO
L<DynaLoader>
=head1 AUTHORS
Ilya Zakharevich originally extracted C<XSLoader> from C<DynaLoader>.
CPAN version is currently maintained by SE<eacute>bastien Aperghis-Tramoni
E<lt>sebastien@aperghis.netE<gt>.
Previous maintainer was Michael G Schwern <schwern@pobox.com>.
=head1 COPYRIGHT
This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,88 @@
package bytes;
our $VERSION = '1.02';
$bytes::hint_bits = 0x00000008;
sub import {
$^H |= $bytes::hint_bits;
}
sub unimport {
$^H &= ~$bytes::hint_bits;
}
sub AUTOLOAD {
require "bytes_heavy.pl";
goto &$AUTOLOAD if defined &$AUTOLOAD;
require Carp;
Carp::croak("Undefined subroutine $AUTOLOAD called");
}
sub length ($);
sub chr ($);
sub ord ($);
sub substr ($$;$$);
sub index ($$;$);
sub rindex ($$;$);
1;
__END__
=head1 NAME
bytes - Perl pragma to force byte semantics rather than character semantics
=head1 SYNOPSIS
use bytes;
... chr(...); # or bytes::chr
... index(...); # or bytes::index
... length(...); # or bytes::length
... ord(...); # or bytes::ord
... rindex(...); # or bytes::rindex
... substr(...); # or bytes::substr
no bytes;
=head1 DESCRIPTION
The C<use bytes> pragma disables character semantics for the rest of the
lexical scope in which it appears. C<no bytes> can be used to reverse
the effect of C<use bytes> within the current lexical scope.
Perl normally assumes character semantics in the presence of character
data (i.e. data that has come from a source that has been marked as
being of a particular character encoding). When C<use bytes> is in
effect, the encoding is temporarily ignored, and each string is treated
as a series of bytes.
As an example, when Perl sees C<$x = chr(400)>, it encodes the character
in UTF-8 and stores it in $x. Then it is marked as character data, so,
for instance, C<length $x> returns C<1>. However, in the scope of the
C<bytes> pragma, $x is treated as a series of bytes - the bytes that make
up the UTF8 encoding - and C<length $x> returns C<2>:
$x = chr(400);
print "Length is ", length $x, "\n"; # "Length is 1"
printf "Contents are %vd\n", $x; # "Contents are 400"
{
use bytes; # or "require bytes; bytes::length()"
print "Length is ", length $x, "\n"; # "Length is 2"
printf "Contents are %vd\n", $x; # "Contents are 198.144"
}
chr(), ord(), substr(), index() and rindex() behave similarly.
For more on the implications and differences between character
semantics and byte semantics, see L<perluniintro> and L<perlunicode>.
=head1 LIMITATIONS
bytes::substr() does not work as an lvalue().
=head1 SEE ALSO
L<perluniintro>, L<perlunicode>, L<utf8>
=cut

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,136 @@
package strict;
$strict::VERSION = "1.03";
my %bitmask = (
refs => 0x00000002,
subs => 0x00000200,
vars => 0x00000400
);
sub bits {
my $bits = 0;
my @wrong;
foreach my $s (@_) {
push @wrong, $s unless exists $bitmask{$s};
$bits |= $bitmask{$s} || 0;
}
if (@wrong) {
require Carp;
Carp::croak("Unknown 'strict' tag(s) '@wrong'");
}
$bits;
}
my $default_bits = bits(qw(refs subs vars));
sub import {
shift;
$^H |= @_ ? bits(@_) : $default_bits;
}
sub unimport {
shift;
$^H &= ~ (@_ ? bits(@_) : $default_bits);
}
1;
__END__
=head1 NAME
strict - Perl pragma to restrict unsafe constructs
=head1 SYNOPSIS
use strict;
use strict "vars";
use strict "refs";
use strict "subs";
use strict;
no strict "vars";
=head1 DESCRIPTION
If no import list is supplied, all possible restrictions are assumed.
(This is the safest mode to operate in, but is sometimes too strict for
casual programming.) Currently, there are three possible things to be
strict about: "subs", "vars", and "refs".
=over 6
=item C<strict refs>
This generates a runtime error if you
use symbolic references (see L<perlref>).
use strict 'refs';
$ref = \$foo;
print $$ref; # ok
$ref = "foo";
print $$ref; # runtime error; normally ok
$file = "STDOUT";
print $file "Hi!"; # error; note: no comma after $file
There is one exception to this rule:
$bar = \&{'foo'};
&$bar;
is allowed so that C<goto &$AUTOLOAD> would not break under stricture.
=item C<strict vars>
This generates a compile-time error if you access a variable that wasn't
declared via C<our> or C<use vars>,
localized via C<my()>, or wasn't fully qualified. Because this is to avoid
variable suicide problems and subtle dynamic scoping issues, a merely
local() variable isn't good enough. See L<perlfunc/my> and
L<perlfunc/local>.
use strict 'vars';
$X::foo = 1; # ok, fully qualified
my $foo = 10; # ok, my() var
local $foo = 9; # blows up
package Cinna;
our $bar; # Declares $bar in current package
$bar = 'HgS'; # ok, global declared via pragma
The local() generated a compile-time error because you just touched a global
name without fully qualifying it.
Because of their special use by sort(), the variables $a and $b are
exempted from this check.
=item C<strict subs>
This disables the poetry optimization, generating a compile-time error if
you try to use a bareword identifier that's not a subroutine, unless it
is a simple identifier (no colons) and that it appears in curly braces or
on the left hand side of the C<< => >> symbol.
use strict 'subs';
$SIG{PIPE} = Plumber; # blows up
$SIG{PIPE} = "Plumber"; # just fine: quoted string is always ok
$SIG{PIPE} = \&Plumber; # preferred form
=back
See L<perlmodlib/Pragmatic Modules>.
=head1 HISTORY
C<strict 'subs'>, with Perl 5.6.1, erroneously permitted to use an unquoted
compound identifier (e.g. C<Foo::Bar>) as a hash key (before C<< => >> or
inside curlies), but without forcing it always to a literal string.
Starting with Perl 5.8.1 strict is strict about its restrictions:
if unknown restrictions are used, the strict pragma will abort with
Unknown 'strict' tag(s) '...'
=cut

View File

@ -0,0 +1,497 @@
# -*- buffer-read-only: t -*-
# !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
# This file was created by warnings.pl
# Any changes made here will be lost.
#
package warnings;
our $VERSION = '1.05';
=head1 NAME
warnings - Perl pragma to control optional warnings
=head1 SYNOPSIS
use warnings;
no warnings;
use warnings "all";
no warnings "all";
use warnings::register;
if (warnings::enabled()) {
warnings::warn("some warning");
}
if (warnings::enabled("void")) {
warnings::warn("void", "some warning");
}
if (warnings::enabled($object)) {
warnings::warn($object, "some warning");
}
warnings::warnif("some warning");
warnings::warnif("void", "some warning");
warnings::warnif($object, "some warning");
=head1 DESCRIPTION
The C<warnings> pragma is a replacement for the command line flag C<-w>,
but the pragma is limited to the enclosing block, while the flag is global.
See L<perllexwarn> for more information.
If no import list is supplied, all possible warnings are either enabled
or disabled.
A number of functions are provided to assist module authors.
=over 4
=item use warnings::register
Creates a new warnings category with the same name as the package where
the call to the pragma is used.
=item warnings::enabled()
Use the warnings category with the same name as the current package.
Return TRUE if that warnings category is enabled in the calling module.
Otherwise returns FALSE.
=item warnings::enabled($category)
Return TRUE if the warnings category, C<$category>, is enabled in the
calling module.
Otherwise returns FALSE.
=item warnings::enabled($object)
Use the name of the class for the object reference, C<$object>, as the
warnings category.
Return TRUE if that warnings category is enabled in the first scope
where the object is used.
Otherwise returns FALSE.
=item warnings::warn($message)
Print C<$message> to STDERR.
Use the warnings category with the same name as the current package.
If that warnings category has been set to "FATAL" in the calling module
then die. Otherwise return.
=item warnings::warn($category, $message)
Print C<$message> to STDERR.
If the warnings category, C<$category>, has been set to "FATAL" in the
calling module then die. Otherwise return.
=item warnings::warn($object, $message)
Print C<$message> to STDERR.
Use the name of the class for the object reference, C<$object>, as the
warnings category.
If that warnings category has been set to "FATAL" in the scope where C<$object>
is first used then die. Otherwise return.
=item warnings::warnif($message)
Equivalent to:
if (warnings::enabled())
{ warnings::warn($message) }
=item warnings::warnif($category, $message)
Equivalent to:
if (warnings::enabled($category))
{ warnings::warn($category, $message) }
=item warnings::warnif($object, $message)
Equivalent to:
if (warnings::enabled($object))
{ warnings::warn($object, $message) }
=back
See L<perlmodlib/Pragmatic Modules> and L<perllexwarn>.
=cut
use Carp ();
our %Offsets = (
# Warnings Categories added in Perl 5.008
'all' => 0,
'closure' => 2,
'deprecated' => 4,
'exiting' => 6,
'glob' => 8,
'io' => 10,
'closed' => 12,
'exec' => 14,
'layer' => 16,
'newline' => 18,
'pipe' => 20,
'unopened' => 22,
'misc' => 24,
'numeric' => 26,
'once' => 28,
'overflow' => 30,
'pack' => 32,
'portable' => 34,
'recursion' => 36,
'redefine' => 38,
'regexp' => 40,
'severe' => 42,
'debugging' => 44,
'inplace' => 46,
'internal' => 48,
'malloc' => 50,
'signal' => 52,
'substr' => 54,
'syntax' => 56,
'ambiguous' => 58,
'bareword' => 60,
'digit' => 62,
'parenthesis' => 64,
'precedence' => 66,
'printf' => 68,
'prototype' => 70,
'qw' => 72,
'reserved' => 74,
'semicolon' => 76,
'taint' => 78,
'threads' => 80,
'uninitialized' => 82,
'unpack' => 84,
'untie' => 86,
'utf8' => 88,
'void' => 90,
'y2k' => 92,
);
our %Bits = (
'all' => "\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x15", # [0..46]
'ambiguous' => "\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00", # [29]
'bareword' => "\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00", # [30]
'closed' => "\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [6]
'closure' => "\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [1]
'debugging' => "\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00", # [22]
'deprecated' => "\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [2]
'digit' => "\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00", # [31]
'exec' => "\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [7]
'exiting' => "\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [3]
'glob' => "\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [4]
'inplace' => "\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00", # [23]
'internal' => "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00", # [24]
'io' => "\x00\x54\x55\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [5..11]
'layer' => "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [8]
'malloc' => "\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00", # [25]
'misc' => "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00", # [12]
'newline' => "\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [9]
'numeric' => "\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00", # [13]
'once' => "\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00", # [14]
'overflow' => "\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00", # [15]
'pack' => "\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00", # [16]
'parenthesis' => "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00", # [32]
'pipe' => "\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [10]
'portable' => "\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00", # [17]
'precedence' => "\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00", # [33]
'printf' => "\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00", # [34]
'prototype' => "\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00", # [35]
'qw' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00", # [36]
'recursion' => "\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00", # [18]
'redefine' => "\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00", # [19]
'regexp' => "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00", # [20]
'reserved' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00", # [37]
'semicolon' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00", # [38]
'severe' => "\x00\x00\x00\x00\x00\x54\x05\x00\x00\x00\x00\x00", # [21..25]
'signal' => "\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00", # [26]
'substr' => "\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00", # [27]
'syntax' => "\x00\x00\x00\x00\x00\x00\x00\x55\x55\x15\x00\x00", # [28..38]
'taint' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00", # [39]
'threads' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00", # [40]
'uninitialized' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00", # [41]
'unopened' => "\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [11]
'unpack' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00", # [42]
'untie' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00", # [43]
'utf8' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", # [44]
'void' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04", # [45]
'y2k' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10", # [46]
);
our %DeadBits = (
'all' => "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\x2a", # [0..46]
'ambiguous' => "\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00", # [29]
'bareword' => "\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00", # [30]
'closed' => "\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [6]
'closure' => "\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [1]
'debugging' => "\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00", # [22]
'deprecated' => "\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [2]
'digit' => "\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00", # [31]
'exec' => "\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [7]
'exiting' => "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [3]
'glob' => "\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [4]
'inplace' => "\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00", # [23]
'internal' => "\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00", # [24]
'io' => "\x00\xa8\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [5..11]
'layer' => "\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [8]
'malloc' => "\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00", # [25]
'misc' => "\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00", # [12]
'newline' => "\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [9]
'numeric' => "\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00", # [13]
'once' => "\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00", # [14]
'overflow' => "\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00", # [15]
'pack' => "\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00", # [16]
'parenthesis' => "\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00", # [32]
'pipe' => "\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [10]
'portable' => "\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00", # [17]
'precedence' => "\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00", # [33]
'printf' => "\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00", # [34]
'prototype' => "\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00", # [35]
'qw' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00", # [36]
'recursion' => "\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00", # [18]
'redefine' => "\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00", # [19]
'regexp' => "\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00", # [20]
'reserved' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00", # [37]
'semicolon' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00", # [38]
'severe' => "\x00\x00\x00\x00\x00\xa8\x0a\x00\x00\x00\x00\x00", # [21..25]
'signal' => "\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00", # [26]
'substr' => "\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00", # [27]
'syntax' => "\x00\x00\x00\x00\x00\x00\x00\xaa\xaa\x2a\x00\x00", # [28..38]
'taint' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00", # [39]
'threads' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00", # [40]
'uninitialized' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00", # [41]
'unopened' => "\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [11]
'unpack' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00", # [42]
'untie' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00", # [43]
'utf8' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02", # [44]
'void' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08", # [45]
'y2k' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20", # [46]
);
$NONE = "\0\0\0\0\0\0\0\0\0\0\0\0";
$LAST_BIT = 94 ;
$BYTES = 12 ;
$All = "" ; vec($All, $Offsets{'all'}, 2) = 3 ;
sub Croaker
{
require Carp::Heavy; # this initializes %CarpInternal
delete $Carp::CarpInternal{'warnings'};
Carp::croak(@_);
}
sub bits
{
# called from B::Deparse.pm
push @_, 'all' unless @_;
my $mask;
my $catmask ;
my $fatal = 0 ;
my $no_fatal = 0 ;
foreach my $word ( @_ ) {
if ($word eq 'FATAL') {
$fatal = 1;
$no_fatal = 0;
}
elsif ($word eq 'NONFATAL') {
$fatal = 0;
$no_fatal = 1;
}
elsif ($catmask = $Bits{$word}) {
$mask |= $catmask ;
$mask |= $DeadBits{$word} if $fatal ;
$mask &= ~($DeadBits{$word}|$All) if $no_fatal ;
}
else
{ Croaker("Unknown warnings category '$word'")}
}
return $mask ;
}
sub import
{
shift;
my $catmask ;
my $fatal = 0 ;
my $no_fatal = 0 ;
my $mask = ${^WARNING_BITS} ;
if (vec($mask, $Offsets{'all'}, 1)) {
$mask |= $Bits{'all'} ;
$mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1);
}
push @_, 'all' unless @_;
foreach my $word ( @_ ) {
if ($word eq 'FATAL') {
$fatal = 1;
$no_fatal = 0;
}
elsif ($word eq 'NONFATAL') {
$fatal = 0;
$no_fatal = 1;
}
elsif ($catmask = $Bits{$word}) {
$mask |= $catmask ;
$mask |= $DeadBits{$word} if $fatal ;
$mask &= ~($DeadBits{$word}|$All) if $no_fatal ;
}
else
{ Croaker("Unknown warnings category '$word'")}
}
${^WARNING_BITS} = $mask ;
}
sub unimport
{
shift;
my $catmask ;
my $mask = ${^WARNING_BITS} ;
if (vec($mask, $Offsets{'all'}, 1)) {
$mask |= $Bits{'all'} ;
$mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1);
}
push @_, 'all' unless @_;
foreach my $word ( @_ ) {
if ($word eq 'FATAL') {
next;
}
elsif ($catmask = $Bits{$word}) {
$mask &= ~($catmask | $DeadBits{$word} | $All);
}
else
{ Croaker("Unknown warnings category '$word'")}
}
${^WARNING_BITS} = $mask ;
}
my %builtin_type; @builtin_type{qw(SCALAR ARRAY HASH CODE REF GLOB LVALUE Regexp)} = ();
sub __chk
{
my $category ;
my $offset ;
my $isobj = 0 ;
if (@_) {
# check the category supplied.
$category = shift ;
if (my $type = ref $category) {
Croaker("not an object")
if exists $builtin_type{$type};
$category = $type;
$isobj = 1 ;
}
$offset = $Offsets{$category};
Croaker("Unknown warnings category '$category'")
unless defined $offset;
}
else {
$category = (caller(1))[0] ;
$offset = $Offsets{$category};
Croaker("package '$category' not registered for warnings")
unless defined $offset ;
}
my $this_pkg = (caller(1))[0] ;
my $i = 2 ;
my $pkg ;
if ($isobj) {
while (do { { package DB; $pkg = (caller($i++))[0] } } ) {
last unless @DB::args && $DB::args[0] =~ /^$category=/ ;
}
$i -= 2 ;
}
else {
for ($i = 2 ; $pkg = (caller($i))[0] ; ++ $i) {
last if $pkg ne $this_pkg ;
}
$i = 2
if !$pkg || $pkg eq $this_pkg ;
}
my $callers_bitmask = (caller($i))[9] ;
return ($callers_bitmask, $offset, $i) ;
}
sub enabled
{
Croaker("Usage: warnings::enabled([category])")
unless @_ == 1 || @_ == 0 ;
my ($callers_bitmask, $offset, $i) = __chk(@_) ;
return 0 unless defined $callers_bitmask ;
return vec($callers_bitmask, $offset, 1) ||
vec($callers_bitmask, $Offsets{'all'}, 1) ;
}
sub warn
{
Croaker("Usage: warnings::warn([category,] 'message')")
unless @_ == 2 || @_ == 1 ;
my $message = pop ;
my ($callers_bitmask, $offset, $i) = __chk(@_) ;
Carp::croak($message)
if vec($callers_bitmask, $offset+1, 1) ||
vec($callers_bitmask, $Offsets{'all'}+1, 1) ;
Carp::carp($message) ;
}
sub warnif
{
Croaker("Usage: warnings::warnif([category,] 'message')")
unless @_ == 2 || @_ == 1 ;
my $message = pop ;
my ($callers_bitmask, $offset, $i) = __chk(@_) ;
return
unless defined $callers_bitmask &&
(vec($callers_bitmask, $offset, 1) ||
vec($callers_bitmask, $Offsets{'all'}, 1)) ;
Carp::croak($message)
if vec($callers_bitmask, $offset+1, 1) ||
vec($callers_bitmask, $Offsets{'all'}+1, 1) ;
Carp::carp($message) ;
}
1;
# ex: set ro:

View File

@ -0,0 +1,51 @@
package warnings::register;
our $VERSION = '1.01';
=pod
=head1 NAME
warnings::register - warnings import function
=head1 SYNOPSIS
use warnings::register;
=head1 DESCRIPTION
Creates a warnings category with the same name as the current package.
See L<warnings> and L<perllexwarn> for more information on this module's
usage.
=cut
require warnings;
sub mkMask
{
my ($bit) = @_;
my $mask = "";
vec($mask, $bit, 1) = 1;
return $mask;
}
sub import
{
shift;
my $package = (caller(0))[0];
if (! defined $warnings::Bits{$package}) {
$warnings::Bits{$package} = mkMask($warnings::LAST_BIT);
vec($warnings::Bits{'all'}, $warnings::LAST_BIT, 1) = 1;
$warnings::Offsets{$package} = $warnings::LAST_BIT ++;
foreach my $k (keys %warnings::Bits) {
vec($warnings::Bits{$k}, $warnings::LAST_BIT, 1) = 0;
}
$warnings::DeadBits{$package} = mkMask($warnings::LAST_BIT);
vec($warnings::DeadBits{'all'}, $warnings::LAST_BIT++, 1) = 1;
}
}
1;

View File

@ -0,0 +1 @@
# empty sitecustomize.pl file

View File

@ -0,0 +1,14 @@
{
global: *;
local:
extern "C++" {
*std::*;
__cxxabi*;
__gcc*;
__gxx*;
__gnu_cxx*;
__cxa*;
operator*;
__dynamic_cast
};
};