eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*- if $running_under_some_shell; # makeBaseApp # Authors: Ralph Lange and Marty Kraimer # $Revision$ $Date$ use Cwd; use Getopt::Std; use File::Copy; use File::Find; use File::Path; $user = GetUser(); $cwd = cwd(); $eAPPTYPE = $ENV{EPICS_MBA_DEF_APP_TYPE}; $eTOP = $ENV{EPICS_MBA_TEMPLATE_TOP}; &get_commandline_opts; # Read and check options # # Declare two default callback routines for file copy plus two # hook routines to add conversions # These may be overriden within $top/$apptypename/Replace.pl # First: the hooks sub ReplaceFilenameHook { return $_[0]; } sub ReplaceLineHook { return $_[0]; } # ReplaceFilename # called with the source (template) file or directory name, returns # the "real" name (which gets the target after $top is removed) # Empty string: Don't copy this file sub ReplaceFilename { # (filename) my($file) = $_[0]; $file =~ s|.*/CVS/?.*||; # Ignore CVS files if($opt_i) { $file =~ s|/$apptypename|/iocBoot|; } if ($ioc) { # iocBoot/ioc template has dynamic name $file =~ s|/iocBoot/ioc|/iocBoot/$ioc|; $file =~ s|_IOC_|$ioc|; } else { $file =~ s|.*/iocBoot/ioc/?.*||; } if ($app) { # apptypenameApp itself is dynamic, too $file =~ s|/$apptypename|/$appdir|; $file =~ s|/$appdir/configure|/configure/$apptype|; } $file =~ s|_APPNAME_|$appname|; $file =~ s|_APPTYPE_|$apptype|; # We don't want the Replace overrides $file =~ s|.*/$appdir/Replace.pl$||; $file = &ReplaceFilenameHook($file); # Call the user-defineable hook return $file; } # ReplaceLine # called with one line of a file, returns the line after replacing # this and that sub ReplaceLine { # (line) my($line) = $_[0]; $line =~ s/_USER_/$user/o; $line =~ s/_EPICS_BASE_/$epics_base/o; $line =~ s/_ARCH_/$arch/o; $line =~ s/_APPNAME_/$appname/o; $line =~ s/_APPTYPE_/$apptype/o; $line =~ s/_TEMPLATE_TOP_/$top/o; if ($ioc) { $line =~ s/_IOC_/$ioc/o; } $line = &ReplaceLineHook($line); # Call the user-defineable hook return $line; } # Source replace overrides for file copy if (-r "$top/$apptypename/Replace.pl") { require "$top/$apptypename/Replace.pl"; } # # Copy files and trees from (non-App & non-Boot) if not present # opendir TOPDIR, "$top" or die "Can't open $top: $!"; foreach $f ( grep !/^\.\.?$|^[^\/]*(App|Boot)/, readdir TOPDIR ) { if (-f "$f") { &CopyFile("$top/$f") unless (-e "$f"); } else { find(\&FCopyTree, "$top/$f") unless (-e "$f"); } } closedir TOPDIR; # # Create ioc directories # if ($opt_i) { find(\&FCopyTree, "$top/$apptypename") unless (-d "iocBoot"); foreach $ioc ( @ARGV ) { ($ioc =~ /^ioc/) or $ioc = "ioc" . $ioc; if (-d "iocBoot/$ioc") { print "ioc iocBoot/$ioc is already there!\n"; next; } find(\&FCopyTree, "$top/$apptypename/ioc"); } exit 0; # finished here for -i (no xxxApps) } # # Create app directories (if any names given) # foreach $app ( @ARGV ) { ($appname = $app) =~ s/App$//; $appdir = $appname . "App"; if (-d "$appdir") { print "Application $appname is already there!\n"; next; } print "Creating template structure " . "for $appname (of type $apptypename)\n" if $Debug; find(\&FCopyTree, "$top/$apptypename/"); } exit 0; # END OF SCRIPT # # Get commandline options and check for validity # sub get_commandline_opts { #no args ($len = @ARGV) and getopts("ldit:T:b:a:") or Cleanup(1); # Debug option $Debug = 1 if $opt_d; # Locate epics_base my ($command) = UnixPath($0); if ($opt_b) { # first choice is -b base $epics_base = UnixPath($opt_b); } elsif (-r "configure/RELEASE") { # second choice is configure/RELEASE open(IN, "configure/RELEASE") or die "Cannot open configure/RELEASE"; while () { chomp; s/EPICS_BASE\s*=\s*// and $epics_base = UnixPath($_), break; } close IN; } elsif ($command =~ m|/bin/|) { # assume script was called with full path to base $epics_base = $command; $epics_base =~ s|(/.*)/bin/.*makeBaseApp.*|$1|; } "$epics_base" or Cleanup(1, "Cannot find EPICS base"); # Locate template top directory if ($opt_T) { # first choice is -T templ-top $top = UnixPath($opt_T); } elsif (-r "configure/RELEASE") { # second choice is configure/RELEASE open(IN, "configure/RELEASE") or die "Cannot open configure/RELEASE"; while () { chomp; s/TEMPLATE_TOP\s*=\s*// and $top = UnixPath($_), break; } close IN; } if("$top" eq "") { if ($eTOP) { # third choice is $ENV{EPICS_MBA_TEMPL_TOP} $top = UnixPath($eTOP); } else { # use templates from EPICS base $top = $epics_base . "/templates/makeBaseApp/top"; } } "$top" or Cleanup(1, "Cannot find template top directory"); # Print application type list? if ($opt_l) { &ListAppTypes; exit 0; # finished for -l command } # iocBoot and architecture stuff if ($opt_i) { if ($opt_a) { $arch = $opt_a; } else { print "What architecture do you want to use for your IOC,"; print "e.g. vxWorks-ppc604, vxWorks-68040 ? "; $arch = ; chomp($arch); } } # Application template type if ($opt_t) { # first choice is -t type $apptype = $opt_t; } elsif ($eAPPTYPE) { # second choice is $ENV{EPICS_DEFAULT_APP_TYPE} $apptype = $eAPPTYPE; } elsif (-r "$top/defaultApp") {# third choice is (a link) in the $top dir $apptype = "default"; } elsif (-r "$top/exampleApp") {# fourth choice is (a link) in the $top dir $apptype = "example"; } $apptype =~ s/App$//; $apptype =~ s/Boot$//; "$apptype" or Cleanup(1, "Cannot find default application type"); if ($opt_i) { # fixed name when doing ioc dirs $apptypename = $apptype . "Boot"; } else { $apptypename = $apptype . "App"; } # Valid $apptypename? unless (-r "$top/$apptypename") { print "Template for application type '$apptype' is unreadable or does not exist.\n"; &ListAppTypes; exit 1; } print "\nCommand line / environment options validated:\n" . " Templ-Top: $top\n" . "Templ-Type: $apptype\n" . "Templ-Name: $apptypename\n" . " opt_i: $opt_i\n" . " arch: $arch\n" . "EPICS-Base: $epics_base\n\n" if $Debug; } # # List application types # sub ListAppTypes { # no args print "Valid application types are:\n"; foreach $name (<$top/*App>) { $name =~ s|$top/||; $name =~ s|App||; printf "\t$name\n" if ($name && -r "$top/$name" . "App"); } print "Valid iocBoot types are:\n"; foreach $name (<$top/*Boot>) { $name =~ s|$top/||; $name =~ s|Boot||; printf "\t$name\n" if ($name && -r "$top/$name" . "Boot");; } } # # Copy a file with replacements # sub CopyFile { # (source) $source = $_[0]; $target = &ReplaceFilename($source); if ($target) { $target =~ s|$top/||; open(INP, "<$source") and open(OUT, ">$target") or die "$! Copying $source -> $target"; print "Copying file $source -> $target\n" if $Debug; while () { print OUT &ReplaceLine($_); } close INP; close OUT; } } # # Find() callback for file or structure copy # sub FCopyTree { chdir $cwd; # Sigh if (-d $File::Find::name and ($dir = &ReplaceFilename($File::Find::name))) { $dir =~ s|$top/||; print "Creating directory $dir\n" if $Debug; &mkpath($dir); } else { &CopyFile($File::Find::name); } chdir $File::Find::dir; } # # Cleanup and exit # sub Cleanup { # (return-code [ messsage-line1, line 2, ... ]) my ($rtncode, @message) = @_; foreach $line ( @message ) { print "$line\n"; } print </bin//makeBaseApp.pl -t example example /bin//makeBaseApp.pl -i -t example example EOF exit $rtncode; } sub GetUser { # no args my ($user); # add to this list if new possibilities arise, # currently it's UNIX and WIN32: $user = $ENV{USER} || $ENV{USERNAME} || Win32::LoginName(); unless ($user) { print "I cannot figure out your user name.\n"; print "What shall you be called ?\n"; print ">"; $user = ; chomp $user; } die "No user name" unless $user; return $user; } # replace "\" by "/" (for WINxx) sub UnixPath { # path my($newpath) = $_[0]; $newpath =~ s|\\|/|go; return $newpath; }