diff options
Diffstat (limited to 'tmake/bin')
-rwxr-xr-x | tmake/bin/progen | 249 | ||||
-rw-r--r-- | tmake/bin/progen.bat | 266 | ||||
-rwxr-xr-x | tmake/bin/tmake | 1099 | ||||
-rw-r--r-- | tmake/bin/tmake.bat | 1093 |
4 files changed, 2707 insertions, 0 deletions
diff --git a/tmake/bin/progen b/tmake/bin/progen new file mode 100755 index 0000000..8237fd5 --- /dev/null +++ b/tmake/bin/progen @@ -0,0 +1,249 @@ +#!/usr/bin/perl +############################################################################ +# $Id$ +# +# Generates a tmake project file. +# +# Copyright (C) 1996-1998 by Troll Tech AS. All rights reserved. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose and without fee is hereby granted, provided +# that this copyright notice appears in all copies. +# No representations are made about the suitability of this software for any +# purpose. It is provided "as is" without express or implied warranty. +# +############################################################################ + +# Default project settings +$project{"TEMPLATE"} = "app"; +$project{"CONFIG"} = "qt warn_on release"; + +@project_extra = (); + +while ( @ARGV ) { # parse command line args + $_ = shift @ARGV; + if ( s/^-// ) { + if ( /^o(.*)/ ) { + $outfile = ($1 eq "") ? shift @ARGV : $1; + ($outfile eq "-") && ($outfile = ""); + } elsif ( /^n(.*)/ ) { + $project{"TARGET"} = ($1 eq "") ? shift @ARGV : $1; + } elsif ( /^t(.*)/ ) { + $project{"TEMPLATE"} = ($1 eq "") ? shift @ARGV : $1; + $project{"TEMPLATE"} =~ s/\.t$//i; + } elsif ( /lower/ ) { + $tolower = 1; + } else { + &progen_usage; + } + } elsif ( /^\s*(?:[\w\-]+:)?\w+\s*[\+\-\*\/]?=/ ) { # project override + push( @project_extra, $_ ); + } else { + push (@files, $_ ); + } +} + +$outfile eq "" || open(STDOUT,">" . $outfile) || + &progen_error("Can't create \"$outfile\""); + +if ( ! @files ) { + @files = &find_files(".",".*",1); +} + +if ( $tolower ) { + foreach $f ( @files ) { + $f =~ tr/A-Z/a-z/; + } +} + +@hdr = sort grep(/\.(h|hh|hpp|hxx)$/i,@files); +@src = sort grep(/\.(c|cpp|cc|cxx)$/i && ! /moc_/i,@files); + +# Remove source files that are included by other source files +foreach $f ( @src ) { + $srcdict{$f} = 1; +} +foreach $f ( @src ) { + if ( open(F,"< $f") ) { + while ( <F> ) { + if ( /^\s*#\s*include\s+\"([^\"]*)\"/ ) { + $srcdict{$1} = 0; + } + } + } +} +foreach $f( @src ) { + $srcdict{$f} && (push(@src2,$f)); +} +@src = @src2; + +$project{"HEADERS"} = join(" ",sort @hdr); +$project{"SOURCES"} = join(" ",sort @src); + +foreach $p ( @project_extra ) { + if ( $p =~ /^\s*((?:[\w\-]+:)?\w+)\s*([\+\-\*\/])?=\s*(.*)/ ) { + if ( $project{$1} ne "" ) { + Project($p); + } + } +} + +$project{"HEADERS"} =~ s/\s+/ \\\n\t\t /g; +$project{"SOURCES"} =~ s/\s+/ \\\n\t\t /g; + +print "TEMPLATE\t= " . $project{"TEMPLATE"} . "\n"; +print "CONFIG\t\t= " . $project{"CONFIG"} . "\n"; +print "HEADERS\t\t= " . $project{"HEADERS"} . "\n"; +print "SOURCES\t\t= " . $project{"SOURCES"} . "\n"; +if ( $project{"TARGET"} ne "" ) { + print "TARGET\t\t= " . $project{"TARGET"} . "\n"; +} + +foreach ( @project_extra ) { + if ( /^\s*((?:[\w\-]+:)?\w+)\s*([\+\-\*\/])?=\s*(.*)/ ) { + if ( $project{$1} eq "" ) { + $t = $1; + if ( length($t) < 8 ) { + $t .= "\t\t"; + } elsif ( length($t) < 16 ) { + $t .= "\t"; + } else { + $t .= " "; + } + print "$t$2= $3\n"; + } + } +} + +exit 0; + + +# +# progen_usage() +# +# Prints a message about program usage and exits +# + +sub progen_usage { + print STDERR "Usage:\n progen [options] [files]\n"; + print STDERR "Options:\n"; + print STDERR " -lower Lower-case letters filenames (useful for non-Unix)\n"; + print STDERR " -n name Specify a project name (= TARGET)\n"; + print STDERR " -o file Write output to \"file\"\n"; + print STDERR " -t file Specify a template file other than qtapp\n"; + exit 1; +} + + +# +# progen_error(msg) +# +# Prints the message and exits +# + +sub progen_error { + my($msg) = @_; + print STDERR "progen error: " . $msg . "\n"; + exit 1; +} + + +# +# Finds files. +# +# Examples: +# find_files("/usr","\.cpp$",1) - finds .cpp files in /usr and below +# find_files("/tmp","^#",0) - finds #* files in /tmp +# + +sub find_files { + my($dir,$match,$descend) = @_; + my($file,$p,@files); + local(*D); + $dir =~ s=\\=/=g; + ($dir eq "") && ($dir = "."); + if ( opendir(D,$dir) ) { + if ( $dir eq "." ) { + $dir = ""; + } else { + ($dir =~ /\/$/) || ($dir .= "/"); + } + foreach $file ( readdir(D) ) { + next if ( $file =~ /^\.\.?$/ ); + $p = $dir . $file; + ($file =~ /$match/i) && (push @files, $p); + if ( $descend && -d $p && ! -l $p ) { + push @files, &find_files($p,$match,$descend); + } + } + closedir(D); + } + return @files; +} + + +# +# strip_project_val(tag) +# +# Strips white space from project value strings. +# + +sub strip_project_val { + my($v) = @_; + $v =~ s/^\s+//; # trim white space + $v =~ s/\s+$//; + return $v; +} + + +# +# Project(strings) +# +# This is a powerful function for setting or reading project variables. +# Returns the resulting project variables (joined with space between). +# +# This is a slightly modified version of the Project function in tmake. + +sub Project { + my @settings = @_; + my($r,$t,$s,$v,$p,$c); + $r = ""; + foreach ( @settings ) { + $v = $_; + if ( $v =~ s/^\s*((?:[\w\-]+:)?\w+)\s*(\+=|\*=|\-=|\/=|=)\s*// ) { + $t = $1; + $s = $2; + $v = strip_project_val($v); + $p = $project{$t}; + if ( $s eq "=" ) { # set variable + $p = $v; + } elsif ( $s eq "+=" ) { # append + if ( $p eq "" ) { + $p = $v; + } else { + $p .= " " . $v; + } + } elsif ( $s eq "*=" ) { # append if not contained + if ( !($p =~ /(?:^|\s)\Q$v\E(?:\s|$)/) ) { + if ( $p eq "" ) { + $p = $v; + } else { + $p .= " " . $v; + } + } + } elsif ( $s eq "-=" ) { # subtract + $p =~ s/$v//g; + } elsif ( $s eq "/=" ) { # sed + $cmd = '$p =~ ' . $v; + eval $cmd; + } + $project{$t} = strip_project_val($p); + } else { + $p = strip_project_val($project{$v}); + } + if ( $p ne "" ) { + $r = ($r eq "") ? $p : ($r . " " . $p); + } + } + return $r; +} diff --git a/tmake/bin/progen.bat b/tmake/bin/progen.bat new file mode 100644 index 0000000..54475ee --- /dev/null +++ b/tmake/bin/progen.bat @@ -0,0 +1,266 @@ +@rem = '--*-PERL-*--'; +@rem = ' +@echo off +rem setlocal +set ARGS= +:loop +if .%1==. goto endloop +set ARGS=%ARGS% %1 +shift +goto loop +:endloop +rem ***** This assumes PERL is in the PATH ***** +perl.exe -S progen.bat %ARGS% +goto endofperl +@rem '; +#!/usr/bin/perl +############################################################################ +# $Id$ +# +# Generates a tmake project file. +# +# Copyright (C) 1996-1998 by Troll Tech AS. All rights reserved. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose and without fee is hereby granted, provided +# that this copyright notice appears in all copies. +# No representations are made about the suitability of this software for any +# purpose. It is provided "as is" without express or implied warranty. +# +############################################################################ + +# Default project settings +$project{"TEMPLATE"} = "app"; +$project{"CONFIG"} = "qt warn_on release"; + +@project_extra = (); + +while ( @ARGV ) { # parse command line args + $_ = shift @ARGV; + if ( s/^-// ) { + if ( /^o(.*)/ ) { + $outfile = ($1 eq "") ? shift @ARGV : $1; + ($outfile eq "-") && ($outfile = ""); + } elsif ( /^n(.*)/ ) { + $project{"TARGET"} = ($1 eq "") ? shift @ARGV : $1; + } elsif ( /^t(.*)/ ) { + $project{"TEMPLATE"} = ($1 eq "") ? shift @ARGV : $1; + $project{"TEMPLATE"} =~ s/\.t$//i; + } elsif ( /lower/ ) { + $tolower = 1; + } else { + &progen_usage; + } + } elsif ( /^\s*(?:[\w\-]+:)?\w+\s*[\+\-\*\/]?=/ ) { # project override + push( @project_extra, $_ ); + } else { + push (@files, $_ ); + } +} + +$outfile eq "" || open(STDOUT,">" . $outfile) || + &progen_error("Can't create \"$outfile\""); + +if ( ! @files ) { + @files = &find_files(".",".*",1); +} + +if ( $tolower ) { + foreach $f ( @files ) { + $f =~ tr/A-Z/a-z/; + } +} + +@hdr = sort grep(/\.(h|hh|hpp|hxx)$/i,@files); +@src = sort grep(/\.(c|cpp|cc|cxx)$/i && ! /moc_/i,@files); + +# Remove source files that are included by other source files +foreach $f ( @src ) { + $srcdict{$f} = 1; +} +foreach $f ( @src ) { + if ( open(F,"< $f") ) { + while ( <F> ) { + if ( /^\s*#\s*include\s+\"([^\"]*)\"/ ) { + $srcdict{$1} = 0; + } + } + } +} +foreach $f( @src ) { + $srcdict{$f} && (push(@src2,$f)); +} +@src = @src2; + +$project{"HEADERS"} = join(" ",sort @hdr); +$project{"SOURCES"} = join(" ",sort @src); + +foreach $p ( @project_extra ) { + if ( $p =~ /^\s*((?:[\w\-]+:)?\w+)\s*([\+\-\*\/])?=\s*(.*)/ ) { + if ( $project{$1} ne "" ) { + Project($p); + } + } +} + +$project{"HEADERS"} =~ s/\s+/ \\\n\t\t /g; +$project{"SOURCES"} =~ s/\s+/ \\\n\t\t /g; + +print "TEMPLATE\t= " . $project{"TEMPLATE"} . "\n"; +print "CONFIG\t\t= " . $project{"CONFIG"} . "\n"; +print "HEADERS\t\t= " . $project{"HEADERS"} . "\n"; +print "SOURCES\t\t= " . $project{"SOURCES"} . "\n"; +if ( $project{"TARGET"} ne "" ) { + print "TARGET\t\t= " . $project{"TARGET"} . "\n"; +} + +foreach ( @project_extra ) { + if ( /^\s*((?:[\w\-]+:)?\w+)\s*([\+\-\*\/])?=\s*(.*)/ ) { + if ( $project{$1} eq "" ) { + $t = $1; + if ( length($t) < 8 ) { + $t .= "\t\t"; + } elsif ( length($t) < 16 ) { + $t .= "\t"; + } else { + $t .= " "; + } + print "$t$2= $3\n"; + } + } +} + +exit 0; + + +# +# progen_usage() +# +# Prints a message about program usage and exits +# + +sub progen_usage { + print STDERR "Usage:\n progen [options] [files]\n"; + print STDERR "Options:\n"; + print STDERR " -lower Lower-case letters filenames (useful for non-Unix)\n"; + print STDERR " -n name Specify a project name (= TARGET)\n"; + print STDERR " -o file Write output to \"file\"\n"; + print STDERR " -t file Specify a template file other than qtapp\n"; + exit 1; +} + + +# +# progen_error(msg) +# +# Prints the message and exits +# + +sub progen_error { + my($msg) = @_; + print STDERR "progen error: " . $msg . "\n"; + exit 1; +} + + +# +# Finds files. +# +# Examples: +# find_files("/usr","\.cpp$",1) - finds .cpp files in /usr and below +# find_files("/tmp","^#",0) - finds #* files in /tmp +# + +sub find_files { + my($dir,$match,$descend) = @_; + my($file,$p,@files); + local(*D); + $dir =~ s=\\=/=g; + ($dir eq "") && ($dir = "."); + if ( opendir(D,$dir) ) { + if ( $dir eq "." ) { + $dir = ""; + } else { + ($dir =~ /\/$/) || ($dir .= "/"); + } + foreach $file ( readdir(D) ) { + next if ( $file =~ /^\.\.?$/ ); + $p = $dir . $file; + ($file =~ /$match/i) && (push @files, $p); + if ( $descend && -d $p && ! -l $p ) { + push @files, &find_files($p,$match,$descend); + } + } + closedir(D); + } + return @files; +} + + +# +# strip_project_val(tag) +# +# Strips white space from project value strings. +# + +sub strip_project_val { + my($v) = @_; + $v =~ s/^\s+//; # trim white space + $v =~ s/\s+$//; + return $v; +} + + +# +# Project(strings) +# +# This is a powerful function for setting or reading project variables. +# Returns the resulting project variables (joined with space between). +# +# This is a slightly modified version of the Project function in tmake. + +sub Project { + my @settings = @_; + my($r,$t,$s,$v,$p,$c); + $r = ""; + foreach ( @settings ) { + $v = $_; + if ( $v =~ s/^\s*((?:[\w\-]+:)?\w+)\s*(\+=|\*=|\-=|\/=|=)\s*// ) { + $t = $1; + $s = $2; + $v = strip_project_val($v); + $p = $project{$t}; + if ( $s eq "=" ) { # set variable + $p = $v; + } elsif ( $s eq "+=" ) { # append + if ( $p eq "" ) { + $p = $v; + } else { + $p .= " " . $v; + } + } elsif ( $s eq "*=" ) { # append if not contained + if ( !($p =~ /(?:^|\s)\Q$v\E(?:\s|$)/) ) { + if ( $p eq "" ) { + $p = $v; + } else { + $p .= " " . $v; + } + } + } elsif ( $s eq "-=" ) { # subtract + $p =~ s/$v//g; + } elsif ( $s eq "/=" ) { # sed + $cmd = '$p =~ ' . $v; + eval $cmd; + } + $project{$t} = strip_project_val($p); + } else { + $p = strip_project_val($project{$v}); + } + if ( $p ne "" ) { + $r = ($r eq "") ? $p : ($r . " " . $p); + } + } + return $r; +} +__END__ +:endofperl diff --git a/tmake/bin/tmake b/tmake/bin/tmake new file mode 100755 index 0000000..2d7e6a7 --- /dev/null +++ b/tmake/bin/tmake @@ -0,0 +1,1099 @@ +#!/usr/bin/perl +############################################################################ +# $Id$ +# +# Creates a Makefile from a template and a project file. +# +# Copyright (C) 1996-1998 by Troll Tech AS. All rights reserved. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose and without fee is hereby granted, provided +# that this copyright notice appears in all copies. +# No representations are made about the suitability of this software for any +# purpose. It is provided "as is" without express or implied warranty. +# +# +# Some important, global variables in tmake: +# cpp_ext C++ extension added to moc output (.cpp) +# obj_ext Object file extension (.o on Unix, .obj otherwise) +# moc_aware Will scan for files containing Qt signals/slots +# moc_pre Moc prefix for generated moc file: x.h -> moc_x.cpp +# moc_ext Moc extension for generated moc file: x.cpp -> x.moc +# moc_cmd The moc command in your makefile, $(MOC) +# linebreak Line break character (\) +# dir_sep Directory separator (/ on Unix, \ on Windows) +# is_unix Autodetected. If not Unix, assume Windows (Win32). +# +# If you need to customize any of these settings, do it before +# calling StdInit() in the template file. +# +############################################################################ + +if ($] < 5.0) { + &tmake_error("This program requires perl version 5 or newer"); +} + +$cpp_ext = "cpp"; +$obj_ext = "o"; +$moc_aware = 0; +$moc_pre = "moc_"; +$moc_ext = "moc"; +$moc_cmd = '$(MOC)'; +$linebreak = "\\"; +$dir_sep = "/"; +$is_unix = 1; +$really_unix = &check_unix(); +$guess_os = 1; +$depend_path = ""; +$nodepend = 0; +$output_count = 0; + +$template_name = ""; +$project_name = ""; +$outfile = ""; +@project_extra = (); +@project_files = (); +@eval_expr = (); +$eval_done = 0; + +while ( @ARGV ) { # parse command line args + $_ = shift @ARGV; + if ( s/^-// ) { + if ( /^e(.*)/ ) { + push( @eval_expr, ($1 eq "") ? shift @ARGV : $1); + } elsif ( /^t(.*)/ ) { + $template_name = ($1 eq "") ? shift @ARGV : $1; + } elsif ( /^o(.*)/ ) { + $outfile = ($1 eq "") ? shift @ARGV : $1; + ($outfile eq "-") && ($outfile = ""); + } elsif ( /^p(.*)/ ) { + push( @project_files, ($1 eq "") ? shift @ARGV : $1); + } elsif ( /^unix$/ ) { + $guess_os = 0; + $is_unix = 1; + } elsif ( /^win32$/ ) { + $guess_os = 0; + $is_unix = 0; + } elsif ( /^nodepend$/ ) { + $nodepend = 1; # don't generate dependencies + } elsif ( /^v$/ ) { + $verbose = 1; + } else { + &tmake_usage(); + } + } elsif ( /^\s*(?:[\w\-]+:)?\w+\s*[\+\-\*\/]?=/ ) { # project override + push( @project_extra, $_ ); + } else { + $project_name && + &tmake_error("You can only specify one project file"); + $project_name = $_; + } +} + +($project_name ne "") || &tmake_usage(); + +if ( $guess_os && ! check_unix() ) { # probably non-Unix, + $is_unix = 0; + &tmake_verb("Win32 detected"); +} +if ( ! $is_unix ) { + $obj_ext = "obj"; + $dir_sep = "\\"; +} +$outfile eq "" || open(STDOUT,">" . fix_path($outfile)) || + &tmake_error("Can't create \"$outfile\""); + +%project = (); +&ScanProject( &find_template("tmake.conf") ); +&tmake_verb("Reading the project file $project_name"); +if ( ! ($project_name =~ /\.pro$/i) && -f fix_path($project_name . ".pro") ) { + $project_name .= ".pro"; +} +$project{"PROJECT"} = $project_name; +$project{"PROJECT"} =~ s/\.pro$//i; +$project{"TARGET"} = $project{"PROJECT"}; + +unshift(@project_files,$project_name); +foreach ( @project_files ) { + if ( ! ($_ =~ /\.pro$/i) && -f fix_path($_ . ".pro") ) { + $_ .= ".pro"; + } + if ( !&ScanProject($_) ) { + &tmake_error("Can't open project file \"$_\""); + } +} +&Project( @project_extra ); + +if ( $template_name eq "" ) { + $template_name = $project{"TEMPLATE"} ? + $project{"TEMPLATE"} : "default.t"; +} + +foreach ( @eval_expr ) { + $text = ""; + eval( $_ ); + die $@ if $@; + print $text . "\n" if ($text ne ""); + $eval_done = 1; +} +if ( $eval_done ) { + &tmake_verb("Done!"); + exit 0; +} + +$template_name = &find_template($template_name); +&IncludeTemplate($template_name); +&tmake_verb("Done!"); +exit 0; # finished! + + + +############################################################################## +# Subroutines from here +############################################################################## + +# +# tmake_usage() +# +# Prints a message about program usage and exits +# + +sub tmake_usage { + print STDERR "Usage:\n tmake [options] project-file\n"; + print STDERR "Options:\n"; + print STDERR " -e expr Evaluate expression, ignore template file\n"; + print STDERR " -nodepend Don't generate dependency information\n"; + print STDERR " -o file Write output to file\n"; + print STDERR " -p project Load additional project file\n"; + print STDERR " -t file Specify a template file\n"; + print STDERR " -unix Create output for Unix (auto detects)\n"; + print STDERR " -v Verbose/debug mode\n"; + print STDERR " -win32 Create output for Win32 (auto detects)\n"; + exit 1; +} + + +# +# tmake_error(msg) +# +# Prints the message and exits +# + +sub tmake_error { + my($msg) = @_; + print STDERR "tmake error: " . $msg . "\n"; + exit 1; +} + + +# +# tmake_verb() +# +# Prints a verbose message +# + +sub tmake_verb { + my($msg) = @_; + $verbose && print STDERR "tmake: " . $msg . "\n"; +} + + +# +# check_unix() +# +# Returns 1 if this is a Unix, 0 otherwise. +# + +sub check_unix { + my($r); + $r = 0; + if ( -f "/bin/uname" || -f "/usr/bin/uname" ) { + $r = 1; + (-f "\\bin\\uname") && ($r = 0); + } + return $r; +} + + +# +# find_template(filename) +# +# Looks for the template file. +# 1. search the current directory +# 2. search the directories in TMAKEPATH +# 3. search in $HOME/.tmake +# + +sub find_template { + my($filename) = @_; + my($tb,$d,$p,@dirs); + if ( !defined($template_base) || ($template_base eq "") ) { + $tb = ""; + } else { + $tb = $template_base . ";"; + } + $d = ";" . $tb . $ENV{"TMAKEPATH"} . ";" . $ENV{"HOME"} . "/.tmake/"; + @dirs = &split_path( $d ); + $filename .= ".t" unless ($filename =~ /\.\w+$/); + for $d ( @dirs ) { + $p = $d . $filename; + if ( -f fix_path($p) ) { + if ( $filename eq "tmake.conf" ) { + $tmake_platform = $d; + $tmake_platform =~ s-.*[/\\]([^/\\]*)[/\\]-$1-; + &tmake_verb("Detected platform $tmake_platform"); + } + return $p; + } + return ($d . $filename) if ( -f fix_path($d . $filename) ); + } + &tmake_error("Template file " . $filename . " not found"); +} + + +############################################################################## +# User functions +############################################################################## + +# +# StdInit() +# +# Standard initialization +# + +sub StdInit { + my($p); + return if $stdinit_done; + $stdinit_done = 1; + if ( defined($project{"OBJECTS_DIR"}) ) { + $project{"OBJECTS_DIR"} = FixPath($project{"OBJECTS_DIR"}); + } + if ( defined($project{"MOC_DIR"}) ) { + $project{"MOC_DIR"} = FixPath($project{"MOC_DIR"}); + } + $project{"OBJECTS"} = &Objects($project{"SOURCES"}); + if ( $moc_aware ) { + $project{"_HDRMOC"} = &list_moc($project{"HEADERS"},$moc_pre,$cpp_ext); + $project{"_SRCMOC"} = &list_moc($project{"SOURCES"},"",$moc_ext); + $project{"OBJMOC"} = &Objects($project{"_HDRMOC"}); + $p = $project{"_HDRMOC"} . " " . $project{"_SRCMOC"}; + $p =~ s/(^\s+|\s+$)//g; + $project{"SRCMOC"} = $p; + } + &AddIncludePath(""); +} + + +sub FixPath { + my($p) = @_; + if ( !defined($p) || ($p eq "") || ($p eq ".") ) { + $p = ""; + } else { + $p .= $dir_sep; + $p =~ s-[\\/]+-${dir_sep}-g; + } + return $p; +} + + +# +# Config(name) +# +# Returns true if the project variable CONFIG contains the +# configuration name. +# + +sub Config { + my($name) = @_; + return $project{"CONFIG"} =~ /\b\Q$name\E\b/; +} + + +# +# DisableOutput() +# +# Disables tmake output. Must be restored by calling a corresponding +# EnableOutput(). +# + +sub DisableOutput { + $output_count++; +} + + +# +# EnableOutput() +# +# Enables tmake output again after DisableOutput() has been called. +# + +sub EnableOutput { + $output_count--; +} + + +# +# Now() - sets $text +# +# Sets $text to the current date and time. +# + +sub Now { + my($sec,$min,$hour,$mday,$mon,$year); + ($sec,$min,$hour,$mday,$mon,$year) = localtime(time()); + $text = sprintf("%02d:%02d, %4d/%02d/%02d", + $hour, $min, 1900+$year, 1+$mon, $mday); +} + + +# +# expand_project_val(tag) +# +# Internal function for Project(). +# Expands a project value string. +# + +sub expand_project_val { + my($v) = @_; + my($c); + return "" if !defined($v); + $v =~ s/^\s+//; # trim white space + $v =~ s/\s+$//; + $c = 0; + while ( $c < 100 ) { # expand $$ + if ( $v =~ s/(\$\$\w+)/\035/ ) { + $_ = $1; + s/\$\$//g; + if ( !defined($project{$_}) ) { + $v =~ s/\035//g; + } else { + $v =~ s/\035/$project{$_}/g; + } + $c++; + } else { + $c = 100; + } + } + return $v; +} + + +# +# Project(strings) +# +# This is a powerful function for setting or reading project variables. +# Returns the resulting project variables (joined with space between). +# +# Get a project variable: +# $s = Project("TEMPLATE"); -> $s = "TEMPLATE" +# +# Set a project variable: +# Project("TEMPLATE = lib"); -> TEMPLATE = lib +# Project("CONFIG =";) -> CONFIG empty +# +# Append to a project variable: +# Project("CONFIG = qt"); -> CONFIG = qt +# Project("CONFIG += debug"); -> CONFIG = qt debug +# +# Append to a project variable if it does not contain the value already: +# Project("CONFIG = qt release"); -> CONFIG = qt release +# Project("CONFIG *= qt"); -> CONFIG = qt release +# Project("CONFIG *= opengl"); -> CONFIG = qt release opengl +# +# Subtract from a project variable: +# Project("THINGS = abc xyz"); -> THINGS = abc xyz +# Project("THINGS -= abc"); -> THINGS = xyz +# +# Search/replace on a project variable: +# Project("CONFIG = tq opengl"); -> CONFIG = tq opengl +# Project("CONFIG /= s/tq/qt/"); -> CONFIG = qt opengl +# +# The operations can be performed on several project variables at a time. +# +# Project("TEMPLATE = app", "CONFIG *= opengl", "THINGS += klm"); +# + +sub Project { + my @settings = @_; + my($r,$if_tag,$t,$s,$v,$p,$c); + $r = ""; + foreach ( @settings ) { + $v = $_; + if ( $v =~ s/^\s*((?:[^:]*?:)?)(\w+)\s*(\+=|\*=|\-=|\/=|=)\s*// ) { + $if_tag = $1; + if ( $if_tag ne "" ) { + chop $if_tag; + if ( $if_tag eq "unix" ) { + return "" if !$is_unix; + } elsif ( $if_tag eq "win32" ) { + return "" if $is_unix; + } elsif ( ($if_tag ne $tmake_platform) && !Config($if_tag) ) { + return ""; + } + } + $t = $2; + $s = $3; + $v = expand_project_val($v); + $p = $project{$t}; + if ( $s eq "=" ) { # set variable + $p = $v; + } elsif ( $s eq "+=" ) { # append + if ( $p eq "" ) { + $p = $v; + } else { + $p .= " " . $v; + } + } elsif ( $s eq "*=" ) { # append if not contained + if ( !($p =~ /(?:^|\s)\Q$v\E(?:\s|$)/) ) { + if ( $p eq "" ) { + $p = $v; + } else { + $p .= " " . $v; + } + } + } elsif ( $s eq "-=" ) { # subtract + $p =~ s/$v//g; + } elsif ( $s eq "/=" ) { # sed + $cmd = '$p =~ ' . $v; + eval $cmd; + } + $project{$t} = expand_project_val($p); + } else { + $p = expand_project_val($project{$v}); + } + if ( $p ne "" ) { + $r = ($r eq "") ? $p : ($r . " " . $p); + } + } + return $r; +} + + +# +# Substitute(string) +# +# This function substitutes project variables in a text. +# +# Example: +# Substitute('The project name is "$$PROJECT"') +# + +sub Substitute { + my($subst) = @_; + $text = expand_project_val($subst); + return $text; +} + + +# +# ScanProject(file) +# +# Scans a project file. Inserts project variables into the global +# associative project array. +# + +sub ScanProject { + my($file) = @_; + my($tag,$var,@v,$more,$line); + + $tag = ""; + $line = 0; + open(TMP,fix_path($file)) || return 0; + + while ( <TMP> ) { + $line++; + s/\#.*//; # strip comment + s/^\s+//; # strip white space + s/\s+$//; + if ( /^\s*((?:(?:[^:]*?:)?)\w+\s*(\+|\-|\*|\/)?=)/ ) { + $tag = $1; # tag also contains the ".=" + s/^.*?=\s*//; + } + if ( $tag ne "" ) { + $more = ( $_ =~ s/\s*\\\s*$// ); # more if \ at end of line + push( @v, split( /\s+/, $_ ) ); + if ( ! $more ) { + $var = join(" ",@v); + Project( $tag . $var ); + $tag = ""; + @v = (); + } + } elsif ( $_ ne "" ) { + tmake_error("$file:$line: Syntax error"); + } + } + close(TMP); + return 1; +} + + +# +# IncludeTemplate(template_name) +# +# Includes and processes a template file. +# +# Below, we read the template file and executes any perl code found. +# Perl code comes after "#$". The variable $text contains the text +# to replace the perl code that was executed. +# Template comments begin with "#!". +# + +sub IncludeTemplate { + my($t_name) = @_; + my($cmd,$cmd_block,$cmd_end,$is_cmd_block,$saveline,$spaceonly); + local($text); + local(*T); + + $t_name = &find_template($t_name); + if ( $tmake_template_dict{$t_name} ) { + &tmake_error("Cyclic template inclusion for $t_name"); + } else { + $tmake_template_dict{$t_name} = 1; + } + $template_base = $t_name; + $template_base =~ s-(.*[/\\]).*-$1-; + &tmake_verb("Reading the template $t_name"); + open(T,fix_path($t_name)) || + &tmake_error("Can't open template file \"$t_name\""); + + while ( <T> ) { + if ( /\#\!/ ) { # tmake comment + s/\s*\#\!.*//; + next if /^$/; + } + if ( /\#\$(\{)?\s*(.*)\n/ ) { # code + $cmd = $2; + $is_cmd_block = defined($1) && ($1 eq "{"); + s/\#\$.*\n//; + if ( $is_cmd_block ) { # code block #${ ... + $saveline = $_; + $cmd_block = $cmd; + $cmd_end = 0; + while ( <T> ) { + $cmd = $_; + $cmd =~ s/\s*\#\!.*//; # tmake comment + if ( $cmd =~ /^\s*\#\$\}/ ) { + $_ = ""; + $cmd_end = 1; + last; + } + $cmd =~ s/^\s*\#(\$)?\s*//; + $cmd_block .= $cmd; + } + $cmd_end || &tmake_error('#$} expected but not found'); + $cmd = $cmd_block; + $_ = $saveline; + } + $spaceonly = /^\s*$/; + $saveline = $_; + &tmake_verb("Evaluate: $cmd"); + $text = ""; + eval $cmd; + die $@ if $@; + next if $spaceonly && ($text =~ /^\s*$/); + print $saveline . $text . "\n" if $output_count <= 0; + } else { # something else + print if $output_count <= 0; + } + } + close( T ); +} + + +# +# Expand(tag) - appends to $text +# +# Expands a list of $project{} variables with a space character between them. +# + +sub Expand { + my @tags = @_; + my($t); + $t = Project(@tags); + if ( $text eq "" ) { + $text = $t; + } elsif ( $t ne "" ) { + $text .= " " . $t; + } + return $text; +} + + +# +# ExpandGlue(tag,prepend,glue,append) - appends to $text +# +# Expands a $project{} tag, splits on whitespace +# and joins with $glue. $prepend is put at the start +# of the string and $append is put at the end of the +# string. The resulting string becomes "" if the project +# tag is empty or not defined. +# +# Example: +# +# The project file defines: +# SOURCES = a b c +# +# ExpandGlue("SOURCES","<","-",">") +# +# The result: +# $text = "<a-b-c>" +# + +sub ExpandGlue { + my($tag,$prepend,$glue,$append) = @_; + my($t,$v); + $v = Project($tag); + if ( $v eq "" ) { + $t = ""; + } else { + $t = $prepend . join($glue,split(/\s+/,$v)) . $append; + } + if ( $text eq "" ) { + $text = $t; + } elsif ( $t ne "" ) { + $text .= " " . $t; + } + return $text; +} + + +# +# ExpandList(tag) - sets $text. +# +# Suitable for expanding HEADERS = ... etc. in a Makefile +# + +sub ExpandList { + my($tag) = @_; + return ExpandGlue($tag,""," ${linebreak}\n\t\t",""); +} + + +# +# TmakeSelf() +# +# Generates makefile rule to regenerate the makefile using tmake. +# + +sub TmakeSelf { + my $a = "tmake $project_name"; + if ( $nodepend ) { + $a .= " -nodepend"; + } + if ( $outfile ) { + $text = "tmake: $outfile\n\n$outfile: $project_name\n\t"; + $a .= " -o $outfile"; + } else { + $text = "tmake:\n\t"; + } + $text .= $a +} + + +# +# Objects(files) +# +# Replaces any extension with .o ($obj_ext). +# + +sub Objects { + local($_) = @_; + my(@a); + @a = split(/\s+/,$_); + foreach ( @a ) { + s-\.\w+$-.${obj_ext}-; + if ( defined($project{"OBJECTS_DIR"}) ) { + s-^.*[\\/]--; + $_ = $project{"OBJECTS_DIR"} . $_; + } + } + return join(" ",@a); +} + + +# +# list_moc(files,prefix,extension) +# +# Scans all files and selects all files that contain Q_OBJECT. +# Insert a prefix before the filename and replaces the filename extention. +# + +sub list_moc { + my($files,$pre,$ext) = @_; + my(@v,@m,@lines,$contents,$n,$f,$t); + @v = split(/\s+/,$files); + undef $/; + foreach $f ( @v ) { + if ( open(TMP,fix_path($f)) ) { + $contents = <TMP>; + close(TMP); + $n = 0; + @lines = split(/\n/,$contents); + grep( /tmake\s+ignore\s+Q_OBJECT/ && $n--, @lines ); + $contents =~ s-/\*.*?\*/--gs; # strip C/C++ comments + $contents =~ s-//.*\n--g; + @lines = split(/\n/,$contents); + grep( /(^|\W)Q_OBJECT(\W|$)/ && $n++, @lines ); + if ( $n > 0 ) { + $t = $f; + $t =~ s-^(.*[/\\])?([^/\\]*?)\.(\w+)$-$1${pre}$2.${ext}-; + if ( defined($project{"MOC_DIR"}) ) { + $t =~ s-^.*[\\/]--; + $t = $project{"MOC_DIR"} . $t; + } + $moc_output{$f} = $t; + $moc_input{$t} = $f; + push(@m,$t); + } + $contents = ""; + } + } + $/ = "\n"; + return join(" ",@m); +} + + +# +# BuildObj(objects,sources) +# +# Builds the object files. +# + +sub BuildObj { + my($obj,$src) = @_; + my(@objv,$srcv,$i,$s,$o,$d,$c,$comp,$cimp); + @objv = split(/\s+/,$obj); + @srcv = split(/\s+/,$src); + for $i ( 0..$#objv ) { + $s = $srcv[$i]; + $o = $objv[$i]; + next if $s eq ""; + $text .= $o . ": " . $s; + if ( defined($moc_output{$s}) && ($moc_output{$s} ne "") ) { + $text .= " ${linebreak}\n\t\t" . $moc_output{$s}; + } + $d = &make_depend($s); + $text .= " ${linebreak}\n\t\t" . $d if $d ne ""; + if ( ($s =~ /\.c$/) ) { + $comp = "TMAKE_RUN_CC"; + $cimp = "TMAKE_RUN_CC_IMP"; + } else { + $comp = "TMAKE_RUN_CXX"; + $cimp = "TMAKE_RUN_CXX_IMP"; + } + if ( defined($project{"OBJECTS_DIR"}) || + !defined($project{$cimp}) ) { + $c = $project{$comp}; + $c =~ s/\$src/$s/; + $c =~ s/\$obj/$o/; + $text .= "\n\t$c"; + } + $text .= "\n\n"; + } + chop $text; +} + + +# +# BuildMocObj(objects,sources) +# +# Builds the moc object files. +# + +sub BuildMocObj { + my($obj,$src) = @_; + my(@objv,$srcv,$i,$s,$o,$hdr,$d); + @objv = split(/\s+/,$obj); + @srcv = split(/\s+/,$src); + for $i ( 0..$#objv ) { + $s = $srcv[$i]; + $o = $objv[$i]; + $hdr = $moc_input{$srcv[$i]}; + $text .= $o . ": " . $s . " ${linebreak}\n\t\t" . $hdr; + $d = &make_depend($hdr); + $text .= " ${linebreak}\n\t\t" . $d if $d ne ""; + if ( defined($project{"OBJECTS_DIR"}) || defined($project{"MOC_DIR"})|| + !defined($project{"TMAKE_RUN_CXX_IMP"}) ) { + $c = $project{"TMAKE_RUN_CXX"}; + $c =~ s/\$src/$s/; + $c =~ s/\$obj/$o/; + $text .= "\n\t$c"; + } + $text .= "\n\n"; + } + chop $text; +} + + +# +# BuildMocSrc(files) +# +# Builds the moc source files from headers and sources. +# + +sub BuildMocSrc { + my($f) = @_; + my(@v,$m,$o); + @v = split(/\s+/,$f); + foreach $m ( @v ) { + $o = $moc_output{$m}; + if ( defined($o) && ($o ne "") ) { + $text .= "$o: $m\n\t$moc_cmd $m -o $o\n\n"; + } + } + chop $text; +} + + +# +# AddIncludePath(path) +# +# Adds path to the current include path, $project{"INCLUDEPATH"}. +# + +sub AddIncludePath { + my($path) = @_; + my($p); + if ( $project{"INCPATH"} && + ($project{"INCPATH"} =~ /(?:^|\s)\Q$path\E(?:\s|$)/) ) { + return; + } + $project{"INCLUDEPATH"} = "" if !defined($project{"INCLUDEPATH"}); + $p = $project{"INCLUDEPATH"}; + $p = ($p && $path) ? ($p . ";" . $path) : ($p . $path); + $project{"INCLUDEPATH"} = $p; + $p = join(" ",&split_path($p)); + $p =~ s=[\\/](\s|$)= =g; + $project{"INCPATH"} = $p; +} + + +# +# FindHighestLibVersion(dir,name) +# +# Returns the newest library version. Scans all the files in the specifies +# directory and returns the highest version number. +# +# Used on Windows only. +# +# Example: +# FindHighestLibVersion("c:\qt\lib","qt") returns "200" if +# the c:\qt\lib directory contains qt141.lib and qt200.lib. +# + +sub FindHighestLibVersion { + my($dir,$name) = @_; + my(@files,$f,$v,$highest); + $highest = ""; + @files = find_files($dir,"${name}.*\.lib"); + for $f ( @files ) { + if ( $f =~ /(\d+)\.lib/ ) { + $v = $1; + if ( $highest eq "" || $v > $highest ) { + $highest = $v; + } + } + } + return $highest; +} + + +# +# Finds files. +# +# Examples: +# find_files("/usr","\.cpp$",1) - finds .cpp files in /usr and below +# find_files("/tmp","^#",0) - finds #* files in /tmp +# + +sub find_files { + my($dir,$match,$descend) = @_; + my($file,$p,@files); + local(*D); + $dir =~ s=\\=/=g; + ($dir eq "") && ($dir = "."); + if ( opendir(D,fix_path($dir)) ) { + if ( $dir eq "." ) { + $dir = ""; + } else { + ($dir =~ /\/$/) || ($dir .= "/"); + } + foreach $file ( readdir(D) ) { + next if ( $file =~ /^\.\.?$/ ); + $p = $dir . $file; + if ( $is_unix ) { + ($file =~ /$match/) && (push @files, $p); + } else { + ($file =~ /$match/i) && (push @files, $p); + } + if ( $descend && -d $p && ! -l $p ) { + push @files, &find_files($p,$match,$descend); + } + } + closedir(D); + } + return @files; +} + + +# +# make_depend(file) +# +# Returns a list of included files. +# Uses the global $depend_path variable. +# + +sub make_depend { + my($file) = @_; + my($i,$count); + if ( $nodepend ) { + return ""; + } + if ( ! $depend_path_fixed ) { + $depend_path_fixed = 1; + if ( defined($project{"DEPENDPATH"}) ) { + $depend_path = $project{"DEPENDPATH"}; + } else { + $depend_path = ""; + } + $count = 0; + while ( $count < 100 ) { + if ( $depend_path =~ s/(\$[\{\(]?\w+[\}\)]?)/035/ ) { + $_ = $1; + s/[\$\{\}\(\)]//g; + $depend_path =~ s/035/$ENV{$_}/g; + } else { + $count = 100; + } + } + @dep_path = &split_path($depend_path); + } + @cur_dep_path = @dep_path; + if ( $file =~ /(.*[\/\\])/ ) { + $dep_curdir = $1; + splice( @cur_dep_path, 0, 0, $dep_curdir ); + } else { + $dep_curdir = ""; + } + $dep_file = $file; + &canonical_dep($file); + %dep_dict = (); + $i = &build_dep($file); + chop $i; + $i =~ s=/=$dir_sep=g unless $is_unix; + $i =~ s=([a-zA-Z]):/=//$1/=g if (defined($gnuwin32) && $gnuwin32); + return join(" ${linebreak}\n\t\t",split(/ /,$i) ); +} + +# +# build_dep() - Internal for make_depend() +# + +sub build_dep { + my($file) = @_; + my(@i,$a,$n); + $a = ""; + return $a if !(defined $depend_dict{$file}); + @i = split(/ /,$depend_dict{$file}); + for $n ( @i ) { + if ( !defined($dep_dict{$n}) && defined($full_path{$n}) ) { + $dep_dict{$n} = 1; + $a .= $full_path{$n} . " " . &build_dep($n); + } + } + return $a; +} + +# +# canonical_dep(file) - Internal for make_depend() +# +# Reads the file and all included files recursively. +# %depend_dict associates a file name to a list of included files. +# + +sub canonical_dep { + my($file) = @_; + my(@inc,$i); + @inc = &scan_dep($file); + if ( @inc ) { + $depend_dict{$file} = join(" ",@inc); + for $i ( @inc ) { + &canonical_dep($i) if !defined($depend_dict{$i}); + } + } +} + +# +# scan_dep(file) - Internal for make_depend() +# +# Returns an array of included files. +# + +sub scan_dep { + my($file) = @_; + my($dir,$path,$found,@allincs,@includes,%incs); + $path = ($file eq $dep_file) ? $file : $dep_curdir . $file; + @includes = (); + return @includes if $file =~ /\.$moc_ext$/; # avoid .moc files + if ( ! (-f fix_path($path)) ) { + $found = 0; + for $dir ( @cur_dep_path ) { + $path = $dir . $file; + last if ( $found = (-f fix_path($path)) ); + } + return @includes if ! $found; + } + undef $/; + if ( open(TMP,fix_path($path)) ) { + $full_path{$file} = $path; + $_ = <TMP>; + s-/\*.*?\*/--gs; # strip C/C++ comments + s-//.*\n-\n-g; + @allincs = split(/\n/,$_); + @allincs = grep(/^\s*#\s*include/,@allincs); + foreach ( @allincs ) { # all #include lines + next if !(/^\s*#\s*include\s+[<"]([^>"]*)[>"]/) || defined($incs{$1}); + push(@includes,$1); + $incs{$1} = "1"; + } + close(TMP); + } + $/ = "\n"; + return @includes; +} + + +# +# split_path(path) +# +# Splits a path containing : (Unix) or ; (MSDOS, NT etc.) separators. +# Returns an array. +# + +sub split_path { + my($p) = @_; + return "" if !defined($p); + $p =~ s=:=;=g if $is_unix; + $p =~ s=[/\\]+=/=g; + $p =~ s=([^/:]);=$1/;=g; + $p =~ s=([^:;/])$=$1/=; + $p =~ s=/=$dir_sep=g unless $is_unix; + return split(/;/,$p); +} + + +# +# fix_path(path) +# +# Converts all '\' to '/' if this really seems to be a Unix box. +# + +sub fix_path { + my($p) = @_; + if ( $really_unix ) { + $p =~ s-\\-/-g; + } else { + $p =~ s-/-\\-g; + } + return $p; +} diff --git a/tmake/bin/tmake.bat b/tmake/bin/tmake.bat new file mode 100644 index 0000000..6fbd6b2 --- /dev/null +++ b/tmake/bin/tmake.bat @@ -0,0 +1,1093 @@ +@rem = '--*-PERL-*--'; +@rem = ' +@echo off +rem setlocal +set ARGS= +:loop +if .%1==. goto endloop +set ARGS=%ARGS% %1 +shift +goto loop +:endloop +rem ***** This assumes PERL is in the PATH ***** +perl.exe -S tmake.bat %ARGS% +goto endofperl +@rem '; +#!/usr/bin/perl +############################################################################ +# $Id$ +# +# Creates a Makefile from a template and a project file. +# +# Copyright (C) 1996-1998 by Troll Tech AS. All rights reserved. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose and without fee is hereby granted, provided +# that this copyright notice appears in all copies. +# No representations are made about the suitability of this software for any +# purpose. It is provided "as is" without express or implied warranty. +# +# +# Some important, global variables in tmake: +# cpp_ext C++ extension added to moc output (.cpp) +# obj_ext Object file extension (.o on Unix, .obj otherwise) +# moc_aware Will scan for files containing Qt signals/slots +# moc_pre Moc prefix for generated moc file: x.h -> moc_x.cpp +# moc_ext Moc extension for generated moc file: x.cpp -> x.moc +# moc_cmd The moc command in your makefile, $(MOC) +# linebreak Line break character (\) +# dir_sep Directory separator (/ on Unix, \ on Windows) +# is_unix Autodetected. If not Unix, assume Windows (Win32). +# +# If you need to customize any of these settings, do it before +# calling StdInit() in the template file. +# +############################################################################ + +if ($] < 5.0) { + &tmake_error("This program requires perl version 5 or newer"); +} + +$cpp_ext = "cpp"; +$obj_ext = "o"; +$moc_aware = 0; +$moc_pre = "moc_"; +$moc_ext = "moc"; +$moc_cmd = '$(MOC)'; +$linebreak = "\\"; +$dir_sep = "/"; +$is_unix = 1; +$really_unix = &check_unix(); +$guess_os = 1; +$depend_path = ""; +$nodepend = 0; +$output_count = 0; + +$template_name = ""; +$project_name = ""; +$outfile = ""; +@project_extra = (); +@project_files = (); +@eval_expr = (); +$eval_done = 0; + +while ( @ARGV ) { # parse command line args + $_ = shift @ARGV; + if ( s/^-// ) { + if ( /^e(.*)/ ) { + push( @eval_expr, ($1 eq "") ? shift @ARGV : $1); + } elsif ( /^t(.*)/ ) { + $template_name = ($1 eq "") ? shift @ARGV : $1; + } elsif ( /^o(.*)/ ) { + $outfile = ($1 eq "") ? shift @ARGV : $1; + ($outfile eq "-") && ($outfile = ""); + } elsif ( /^p(.*)/ ) { + push( @project_files, ($1 eq "") ? shift @ARGV : $1); + } elsif ( /^unix$/ ) { + $guess_os = 0; + $is_unix = 1; + } elsif ( /^win32$/ ) { + $guess_os = 0; + $is_unix = 0; + } elsif ( /^nodepend$/ ) { + $nodepend = 1; # don't generate dependencies + } elsif ( /^v$/ ) { + $verbose = 1; + } else { + &tmake_usage(); + } + } elsif ( /^\s*(?:[\w\-]+:)?\w+\s*[\+\-\*\/]?=/ ) { # project override + push( @project_extra, $_ ); + } else { + $project_name && + &tmake_error("You can only specify one project file"); + $project_name = $_; + } +} + +($project_name ne "") || &tmake_usage(); + +if ( $guess_os && ! check_unix() ) { # probably non-Unix, + $is_unix = 0; + &tmake_verb("Win32 detected"); +} +if ( ! $is_unix ) { + $obj_ext = "obj"; + $dir_sep = "\\"; +} +$outfile eq "" || open(STDOUT,">" . fix_path($outfile)) || + &tmake_error("Can't create \"$outfile\""); + +%project = (); +&ScanProject( &find_template("tmake.conf") ); +&tmake_verb("Reading the project file $project_name"); +if ( ! ($project_name =~ /\.pro$/i) && -f fix_path($project_name . ".pro") ) { + $project_name .= ".pro"; +} +$project{"PROJECT"} = $project_name; +$project{"PROJECT"} =~ s/\.pro$//i; +$project{"TARGET"} = $project{"PROJECT"}; + +unshift(@project_files,$project_name); +foreach ( @project_files ) { + if ( ! ($_ =~ /\.pro$/i) && -f fix_path($_ . ".pro") ) { + $_ .= ".pro"; + } + if ( !&ScanProject($_) ) { + &tmake_error("Can't open project file \"$_\""); + } +} +&Project( @project_extra ); + +if ( $template_name eq "" ) { + $template_name = $project{"TEMPLATE"} ? + $project{"TEMPLATE"} : "default.t"; +} + +foreach ( @eval_expr ) { + $text = ""; + eval( $_ ); + die $@ if $@; + print $text . "\n" if ($text ne ""); + $eval_done = 1; +} +if ( $eval_done ) { + &tmake_verb("Done!"); + exit 0; +} + +$template_name = &find_template($template_name); +&IncludeTemplate($template_name); +&tmake_verb("Done!"); +exit 0; # finished! + + + +############################################################################## +# Subroutines from here +############################################################################## + +# +# tmake_usage() +# +# Prints a message about program usage and exits +# + +sub tmake_usage { + print STDERR "Usage:\n tmake [options] project-file\n"; + print STDERR "Options:\n"; + print STDERR " -e expr Evaluate expression, ignore template file\n"; + print STDERR " -nodepend Don't generate dependency information\n"; + print STDERR " -o file Write output to file\n"; + print STDERR " -p project Load additional project file\n"; + print STDERR " -t file Specify a template file\n"; + print STDERR " -unix Create output for Unix (auto detects)\n"; + print STDERR " -v Verbose/debug mode\n"; + print STDERR " -win32 Create output for Win32 (auto detects)\n"; + exit 1; +} + + +# +# tmake_error(msg) +# +# Prints the message and exits +# + +sub tmake_error { + my($msg) = @_; + print STDERR "tmake error: " . $msg . "\n"; + exit 1; +} + + +# +# tmake_verb() +# +# Prints a verbose message +# + +sub tmake_verb { + my($msg) = @_; + $verbose && print STDERR "tmake: " . $msg . "\n"; +} + + +# +# check_unix() +# +# Returns 1 if this is a Unix, 0 otherwise. +# + +sub check_unix { + my($r); + $r = 0; + if ( -f "/bin/uname" ) { + $r = 1; + (-f "\\bin\\uname") && ($r = 0); + } + return $r; +} + + +# +# find_template(filename) +# +# Looks for the template file. +# 1. search the current directory +# 2. search the directories in TMAKEPATH +# 3. search in $HOME/.tmake +# + +sub find_template { + my($filename) = @_; + my($tb,$d,$p,@dirs); + $tb = ($template_base eq "") ? "" : $template_base . ";"; + $d = ";" . $tb . $ENV{"TMAKEPATH"} . ";" . $ENV{"HOME"} . "/.tmake/"; + @dirs = &split_path( $d ); + $filename .= ".t" unless ($filename =~ /\.\w+$/); + for $d ( @dirs ) { + $p = $d . $filename; + if ( -f fix_path($p) ) { + if ( $filename eq "tmake.conf" ) { + $tmake_platform = $d; + $tmake_platform =~ s-.*[/\\]([^/\\]*)[/\\]-$1-; + &tmake_verb("Detected platform $tmake_platform"); + } + return $p; + } + return ($d . $filename) if ( -f fix_path($d . $filename) ); + } + &tmake_error("Template file " . $filename . " not found"); +} + + +############################################################################## +# User functions +############################################################################## + +# +# StdInit() +# +# Standard initialization +# + +sub StdInit { + my($p); + return if $stdinit_done; + $stdinit_done = 1; + if ( defined($project{"OBJECTS_DIR"}) ) { + $project{"OBJECTS_DIR"} = FixPath($project{"OBJECTS_DIR"}); + } + if ( defined($project{"MOC_DIR"}) ) { + $project{"MOC_DIR"} = FixPath($project{"MOC_DIR"}); + } + $project{"OBJECTS"} = &Objects($project{"SOURCES"}); + if ( $moc_aware ) { + $project{"_HDRMOC"} = &list_moc($project{"HEADERS"},$moc_pre,$cpp_ext); + $project{"_SRCMOC"} = &list_moc($project{"SOURCES"},"",$moc_ext); + $project{"OBJMOC"} = &Objects($project{"_HDRMOC"}); + $p = $project{"_HDRMOC"} . " " . $project{"_SRCMOC"}; + $p =~ s/(^\s+|\s+$)//g; + $project{"SRCMOC"} = $p; + } + &AddIncludePath(""); +} + + +sub FixPath { + my($p) = @_; + if ( $p eq "." ) { $p = ""; } + elsif ( length($p) > 0 ) { + $p .= $dir_sep; + $p =~ s-[\\/]+-${dir_sep}-g; + } + return $p; +} + + +# +# Config(name) +# +# Returns true if the project variable CONFIG contains the +# configuration name. +# + +sub Config { + my($name) = @_; + return $project{"CONFIG"} =~ /\b$name\b/; +} + + +# +# DisableOutput() +# +# Disables tmake output. Must be restored by calling a corresponding +# EnableOutput(). +# + +sub DisableOutput { + $output_count++; +} + + +# +# EnableOutput() +# +# Enables tmake output again after DisableOutput() has been called. +# + +sub EnableOutput { + $output_count--; +} + + +# +# Now() - sets $text +# +# Sets $text to the current date and time. +# + +sub Now { + my($sec,$min,$hour,$mday,$mon,$year); + ($sec,$min,$hour,$mday,$mon,$year) = localtime(time()); + $text = sprintf("%02d:%02d, %4d/%02d/%02d", + $hour, $min, 1900+$year, 1+$mon, $mday); +} + + +# +# expand_project_val(tag) +# +# Internal function for Project(). +# Expands a project value string. +# + +sub expand_project_val { + my($v) = @_; + my($c); + $v =~ s/^\s+//; # trim white space + $v =~ s/\s+$//; + $c = 0; + while ( $c < 100 ) { # expand $$ + if ( $v =~ s/(\$\$\w+)/\035/ ) { + $_ = $1; + s/\$\$//g; + $v =~ s/\035/$project{$_}/g; + $c++; + } else { + $c = 100; + } + } + return $v; +} + + +# +# Project(strings) +# +# This is a powerful function for setting or reading project variables. +# Returns the resulting project variables (joined with space between). +# +# Get a project variable: +# $s = Project("TEMPLATE"); -> $s = "TEMPLATE" +# +# Set a project variable: +# Project("TEMPLATE = lib"); -> TEMPLATE = lib +# Project("CONFIG =";) -> CONFIG empty +# +# Append to a project variable: +# Project("CONFIG = qt"); -> CONFIG = qt +# Project("CONFIG += debug"); -> CONFIG = qt debug +# +# Append to a project variable if it does not contain the value already: +# Project("CONFIG = qt release"); -> CONFIG = qt release +# Project("CONFIG *= qt"); -> CONFIG = qt release +# Project("CONFIG *= opengl"); -> CONFIG = qt release opengl +# +# Subtract from a project variable: +# Project("THINGS = abc xyz"); -> THINGS = abc xyz +# Project("THINGS -= abc"); -> THINGS = xyz +# +# Search/replace on a project variable: +# Project("CONFIG = tq opengl"); -> CONFIG = tq opengl +# Project("CONFIG /= s/tq/qt/"); -> CONFIG = qt opengl +# +# The operations can be performed on several project variables at a time. +# +# Project("TEMPLATE = app", "CONFIG *= opengl", "THINGS += klm"); +# + +sub Project { + my @settings = @_; + my($r,$if_tag,$t,$s,$v,$p,$c); + $r = ""; + foreach ( @settings ) { + $v = $_; + if ( $v =~ s/^\s*([\w\-]+:)?(\w+)\s*(\+=|\*=|\-=|\/=|=)\s*// ) { + $if_tag = $1; + if ( $if_tag ne "" ) { + chop $if_tag; + if ( $if_tag eq "unix" ) { + return "" if !$is_unix; + } elsif ( $if_tag eq "win32" ) { + return "" if $is_unix; + } elsif ( ($if_tag ne $tmake_platform) && !Config($if_tag) ) { + return ""; + } + } + $t = $2; + $s = $3; + $v = expand_project_val($v); + $p = $project{$t}; + if ( $s eq "=" ) { # set variable + $p = $v; + } elsif ( $s eq "+=" ) { # append + if ( $p eq "" ) { + $p = $v; + } else { + $p .= " " . $v; + } + } elsif ( $s eq "*=" ) { # append if not contained + if ( !($p =~ /(?:^|\s)\Q$v\E(?:\s|$)/) ) { + if ( $p eq "" ) { + $p = $v; + } else { + $p .= " " . $v; + } + } + } elsif ( $s eq "-=" ) { # subtract + $p =~ s/$v//g; + } elsif ( $s eq "/=" ) { # sed + $cmd = '$p =~ ' . $v; + eval $cmd; + } + $project{$t} = expand_project_val($p); + } else { + $p = expand_project_val($project{$v}); + } + if ( $p ne "" ) { + $r = ($r eq "") ? $p : ($r . " " . $p); + } + } + return $r; +} + + +# +# Substitute(string) +# +# This function substitutes project variables in a text. +# +# Example: +# Substitute('The project name is "$$PROJECT"') +# + +sub Substitute { + my($subst) = @_; + $text = expand_project_val($subst); + return $text; +} + + +# +# ScanProject(file) +# +# Scans a project file. Inserts project variables into the global +# associative project array. +# + +sub ScanProject { + my($file) = @_; + my($tag,$var,@v,$more,$line); + + $tag = ""; + $line = 0; + open(TMP,fix_path($file)) || return 0; + + while ( <TMP> ) { + $line++; + s/\#.*//; # strip comment + s/^\s+//; # strip white space + s/\s+$//; + if ( /^\s*((?:[\w\-]+:)?\w+\s*(\+|\-|\*|\/)?=)/ ) { + $tag = $1; # tag also contains the ".=" + s/^.*?=\s*//; + } + if ( $tag ne "" ) { + $more = ( $_ =~ s/\s*\\\s*$// ); # more if \ at end of line + push( @v, split( /\s+/, $_ ) ); + if ( ! $more ) { + $var = join(" ",@v); + Project( $tag . $var ); + $tag = ""; + @v = (); + } + } elsif ( $_ ne "" ) { + tmake_error("$file:$line: Syntax error"); + } + } + close(TMP); + return 1; +} + + +# +# IncludeTemplate(template_name) +# +# Includes and processes a template file. +# +# Below, we read the template file and executes any perl code found. +# Perl code comes after "#$". The variable $text contains the text +# to replace the perl code that was executed. +# Template comments begin with "#!". +# + +sub IncludeTemplate { + my($t_name) = @_; + my($cmd,$cmd_block,$cmd_end,$is_cmd_block,$saveline,$spaceonly); + local($text); + local(*T); + + $t_name = &find_template($t_name); + if ( $tmake_template_dict{$t_name} ) { + &tmake_error("Cyclic template inclusion for $t_name"); + } else { + $tmake_template_dict{$t_name} = 1; + } + $template_base = $t_name; + $template_base =~ s-(.*[/\\]).*-$1-; + &tmake_verb("Reading the template $t_name"); + open(T,fix_path($t_name)) || + &tmake_error("Can't open template file \"$t_name\""); + + while ( <T> ) { + if ( /\#\!/ ) { # tmake comment + s/\s*\#\!.*//; + next if /^$/; + } + if ( /\#\$(\{)?\s*(.*)\n/ ) { # code + $cmd = $2; + $is_cmd_block = ($1 eq "{"); + s/\#\$.*\n//; + if ( $is_cmd_block ) { # code block #${ ... + $saveline = $_; + $cmd_block = $cmd; + $cmd_end = 0; + while ( <T> ) { + $cmd = $_; + $cmd =~ s/\s*\#\!.*//; # tmake comment + if ( $cmd =~ /^\s*\#\$\}/ ) { + $_ = ""; + $cmd_end = 1; + last; + } + $cmd =~ s/^\s*\#(\$)?\s*//; + $cmd_block .= $cmd; + } + $cmd_end || &tmake_error('#$} expected but not found'); + $cmd = $cmd_block; + $_ = $saveline; + } + $spaceonly = /^\s*$/; + $saveline = $_; + &tmake_verb("Evaluate: $cmd"); + $text = ""; + eval $cmd; + die $@ if $@; + next if $spaceonly && ($text =~ /^\s*$/); + print $saveline . $text . "\n" if $output_count <= 0; + } else { # something else + print if $output_count <= 0; + } + } + close( T ); +} + + +# +# Expand(tag) - appends to $text +# +# Expands a list of $project{} variables with a space character between them. +# + +sub Expand { + my @tags = @_; + my($t); + $t = Project(@tags); + if ( $text eq "" ) { + $text = $t; + } elsif ( $t ne "" ) { + $text .= " " . $t; + } + return $text; +} + + +# +# ExpandGlue(tag,prepend,glue,append) - appends to $text +# +# Expands a $project{} tag, splits on whitespace +# and joins with $glue. $prepend is put at the start +# of the string and $append is put at the end of the +# string. The resulting string becomes "" if the project +# tag is empty or not defined. +# +# Example: +# +# The project file defines: +# SOURCES = a b c +# +# ExpandGlue("SOURCES","<","-",">") +# +# The result: +# $text = "<a-b-c>" +# + +sub ExpandGlue { + my($tag,$prepend,$glue,$append) = @_; + my($t,$v); + $v = Project($tag); + if ( $v eq "" ) { + $t = ""; + } else { + $t = $prepend . join($glue,split(/\s+/,$v)) . $append; + } + if ( $text eq "" ) { + $text = $t; + } elsif ( $t ne "" ) { + $text .= " " . $t; + } + return $text; +} + + +# +# ExpandList(tag) - sets $text. +# +# Suitable for expanding HEADERS = ... etc. in a Makefile +# + +sub ExpandList { + my($tag) = @_; + return ExpandGlue($tag,""," ${linebreak}\n\t\t",""); +} + + +# +# TmakeSelf() +# +# Generates makefile rule to regenerate the makefile using tmake. +# + +sub TmakeSelf { + my $a = "tmake $project_name"; + if ( $nodepend ) { + $a .= " -nodepend"; + } + if ( $outfile ) { + $text = "tmake: $outfile\n\n$outfile: $project_name\n\t"; + $a .= " -o $outfile"; + } else { + $text = "tmake:\n\t"; + } + $text .= $a +} + + +# +# Objects(files) +# +# Replaces any extension with .o ($obj_ext). +# + +sub Objects { + local($_) = @_; + my(@a); + @a = split(/\s+/,$_); + foreach ( @a ) { + s-\.\w+$-.${obj_ext}-; + if ( defined($project{"OBJECTS_DIR"}) ) { + s-^.*[\\/]--; + $_ = $project{"OBJECTS_DIR"} . $_; + } + } + return join(" ",@a); +} + + +# +# list_moc(files,prefix,extension) +# +# Scans all files and selects all files that contain Q_OBJECT. +# Insert a prefix before the filename and replaces the filename extention. +# + +sub list_moc { + my($files,$pre,$ext) = @_; + my(@v,@m,@lines,$contents,$n,$f,$t); + @v = split(/\s+/,$files); + undef $/; + foreach $f ( @v ) { + if ( open(TMP,fix_path($f)) ) { + $contents = <TMP>; + close(TMP); + $n = 0; + @lines = split(/\n/,$contents); + grep( /tmake\s+ignore\s+Q_OBJECT/ && $n--, @lines ); + $contents =~ s-/\*.*?\*/--gs; # strip C/C++ comments + $contents =~ s-//.*\n--g; + @lines = split(/\n/,$contents); + grep( /(^|\W)Q_OBJECT(\W|$)/ && $n++, @lines ); + if ( $n > 0 ) { + $t = $f; + $t =~ s-^(.*[/\\])?([^/\\]*?)\.(\w+)$-$1${pre}$2.${ext}-; + if ( defined($project{"MOC_DIR"}) ) { + $t =~ s-^.*[\\/]--; + $t = $project{"MOC_DIR"} . $t; + } + $moc_output{$f} = $t; + $moc_input{$t} = $f; + push(@m,$t); + } + $contents = ""; + } + } + $/ = "\n"; + return join(" ",@m); +} + + +# +# BuildObj(objects,sources) +# +# Builds the object files. +# + +sub BuildObj { + my($obj,$src) = @_; + my(@objv,$srcv,$i,$s,$o,$d,$c); + @objv = split(/\s+/,$obj); + @srcv = split(/\s+/,$src); + for $i ( 0..$#objv ) { + $s = $srcv[$i]; + $o = $objv[$i]; + next if $s eq ""; + $text .= $o . ": " . $s; + if ( $moc_output{$s} ne "" ) { + $text .= " ${linebreak}\n\t\t" . $moc_output{$s}; + } + $d = &make_depend($s); + $text .= " ${linebreak}\n\t\t" . $d if $d ne ""; + if ( defined($project{"OBJECTS_DIR"}) || + !defined($project{"TMAKE_COMPILE_IMP"}) ) { + $c = $project{"TMAKE_COMPILE"}; + $c =~ s/\$src/$s/; + $c =~ s/\$obj/$o/; + $text .= "\n\t$c"; + } + $text .= "\n\n"; + } + chop $text; +} + + +# +# BuildMocObj(objects,sources) +# +# Builds the moc object files. +# + +sub BuildMocObj { + my($obj,$src) = @_; + my(@objv,$srcv,$i,$s,$o,$hdr,$d); + @objv = split(/\s+/,$obj); + @srcv = split(/\s+/,$src); + for $i ( 0..$#objv ) { + $s = $srcv[$i]; + $o = $objv[$i]; + $hdr = $moc_input{$srcv[$i]}; + $text .= $o . ": " . $s . " ${linebreak}\n\t\t" . $hdr; + $d = &make_depend($hdr); + $text .= " ${linebreak}\n\t\t" . $d if $d ne ""; + if ( defined($project{"OBJECTS_DIR"}) || defined($project{"MOC_DIR"})|| + !defined($project{"TMAKE_COMPILE_IMP"}) ) { + $c = $project{"TMAKE_COMPILE"}; + $c =~ s/\$src/$s/; + $c =~ s/\$obj/$o/; + $text .= "\n\t$c"; + } + $text .= "\n\n"; + } + chop $text; +} + + +# +# BuildMocSrc(files) +# +# Builds the moc source files from headers and sources. +# + +sub BuildMocSrc { + my($f) = @_; + my(@v,$m,$o); + @v = split(/\s+/,$f); + foreach $m ( @v ) { + $o = $moc_output{$m}; + if ( $o ne "" ) { + $text .= "$o: $m\n\t$moc_cmd $m -o $o\n\n"; + } + } + chop $text; +} + + +# +# AddIncludePath(path) +# +# Adds path to the current include path, $project{"INCLUDEPATH"}. +# + +sub AddIncludePath { + my($path) = @_; + my($p); + if ( $project{"INCPATH"} && + ($project{"INCPATH"} =~ /(?:^|\s)\Q$path\E(?:\s|$)/) ) { + return; + } + $p = $project{"INCLUDEPATH"}; + $p = ($p && $path) ? ($p . ";" . $path) : ($p . $path); + $project{"INCLUDEPATH"} = $p; + $p = join(" ",&split_path($p)); + $p =~ s=[\\/](\s|$)= =g; + $project{"INCPATH"} = $p; +} + + +# +# FindHighestLibVersion(dir,name) +# +# Returns the newest library version. Scans all the files in the specifies +# directory and returns the highest version number. +# +# Used on Windows only. +# +# Example: +# FindHighestLibVersion("c:\qt\lib","qt") returns "200" if +# the c:\qt\lib directory contains qt141.lib and qt200.lib. +# + +sub FindHighestLibVersion { + my($dir,$name) = @_; + my(@files,$f,$v,$highest); + $highest = ""; + @files = find_files($dir,"${name}.*\.lib"); + for $f ( @files ) { + if ( $f =~ /(\d+)\.lib/ ) { + $v = $1; + if ( $highest eq "" || $v > $highest ) { + $highest = $v; + } + } + } + return $highest; +} + + +# +# Finds files. +# +# Examples: +# find_files("/usr","\.cpp$",1) - finds .cpp files in /usr and below +# find_files("/tmp","^#",0) - finds #* files in /tmp +# + +sub find_files { + my($dir,$match,$descend) = @_; + my($file,$p,@files); + local(*D); + $dir =~ s=\\=/=g; + ($dir eq "") && ($dir = "."); + if ( opendir(D,fix_path($dir)) ) { + if ( $dir eq "." ) { + $dir = ""; + } else { + ($dir =~ /\/$/) || ($dir .= "/"); + } + foreach $file ( readdir(D) ) { + next if ( $file =~ /^\.\.?$/ ); + $p = $dir . $file; + if ( $is_unix ) { + ($file =~ /$match/) && (push @files, $p); + } else { + ($file =~ /$match/i) && (push @files, $p); + } + if ( $descend && -d $p && ! -l $p ) { + push @files, &find_files($p,$match,$descend); + } + } + closedir(D); + } + return @files; +} + + +# +# make_depend(file) +# +# Returns a list of included files. +# Uses the global $depend_path variable. +# + +sub make_depend { + my($file) = @_; + my($i,$count); + if ( $nodepend ) { + return ""; + } + if ( ! $depend_path_fixed ) { + $depend_path_fixed = 1; + $depend_path = $project{"DEPENDPATH"}; + $count = 0; + while ( $count < 100 ) { + if ( $depend_path =~ s/(\$[\{\(]?\w+[\}\)]?)/035/ ) { + $_ = $1; + s/[\$\{\}\(\)]//g; + $depend_path =~ s/035/$ENV{$_}/g; + } else { + $count = 100; + } + } + @dep_path = &split_path($depend_path); + } + @cur_dep_path = @dep_path; + if ( $file =~ /(.*[\/\\])/ ) { + $dep_curdir = $1; + splice( @cur_dep_path, 0, 0, $dep_curdir ); + } else { + $dep_curdir = ""; + } + $dep_file = $file; + &canonical_dep($file); + %dep_dict = (); + $i = &build_dep($file); + chop $i; + $i =~ s=/=$dir_sep=g unless $is_unix; + $i =~ s=([a-zA-Z]):/=//$1/=g if $gnuwin32; + return join(" ${linebreak}\n\t\t",split(/ /,$i) ); +} + +# +# build_dep() - Internal for make_depend() +# + +sub build_dep { + my($file) = @_; + my(@i,$a,$n); + $a = ""; + return $a if !(defined $depend_dict{$file}); + @i = split(/ /,$depend_dict{$file}); + for $n ( @i ) { + if ( !defined($dep_dict{$n}) && defined($full_path{$n}) ) { + $dep_dict{$n} = 1; + $a .= $full_path{$n} . " " . &build_dep($n); + } + } + return $a; +} + +# +# canonical_dep(file) - Internal for make_depend() +# +# Reads the file and all included files recursively. +# %depend_dict associates a file name to a list of included files. +# + +sub canonical_dep { + my($file) = @_; + my(@inc,$i); + @inc = &scan_dep($file); + if ( @inc ) { + $depend_dict{$file} = join(" ",@inc); + for $i ( @inc ) { + &canonical_dep($i) if !defined($depend_dict{$i}); + } + } +} + +# +# scan_dep(file) - Internal for make_depend() +# +# Returns an array of included files. +# + +sub scan_dep { + my($file) = @_; + my($dir,$path,$found,@allincs,@includes,%incs); + $path = ($file eq $dep_file) ? $file : $dep_curdir . $file; + @includes = (); + return @includes if $file =~ /\.$moc_ext$/; # avoid .moc files + if ( ! (-f fix_path($path)) ) { + $found = 0; + for $dir ( @cur_dep_path ) { + $path = $dir . $file; + last if ( $found = (-f fix_path($path)) ); + } + return @includes if ! $found; + } + undef $/; + if ( open(TMP,fix_path($path)) ) { + $full_path{$file} = $path; + $_ = <TMP>; + s-/\*.*?\*/--gs; # strip C/C++ comments + s-//.*\n-\n-g; + @allincs = split(/\n/,$_); + @allincs = grep(/^\s*#\s*include/,@allincs); + foreach ( @allincs ) { # all #include lines + next if !(/^\s*#\s*include\s+[<"]([^>"]*)[>"]/) || defined($incs{$1}); + push(@includes,$1); + $incs{$1} = "1"; + } + close(TMP); + } + $/ = "\n"; + return @includes; +} + + +# +# split_path(path) +# +# Splits a path containing : (Unix) or ; (MSDOS, NT etc.) separators. +# Returns an array. +# + +sub split_path { + my($p) = @_; + $p =~ s=:=;=g if $is_unix; + $p =~ s=[/\\]+=/=g; + $p =~ s=([^/:]);=$1/;=g; + $p =~ s=([^:;/])$=$1/=; + $p =~ s=/=$dir_sep=g unless $is_unix; + return split(/;/,$p); +} + + +# +# fix_path(path) +# +# Converts all '\' to '/' if this really seems to be a Unix box. +# + +sub fix_path { + my($p) = @_; + if ( $really_unix ) { + $p =~ s-\\-/-g; + } else { + $p =~ s-/-\\-g; + } + return $p; +} +__END__ +:endofperl |