#!/usr/bin/perl ## ## Program Name: tsr (Tcrofut Search and Replace) ## Author: Timothy M. Crofut ## Date: Fri Apr 27 09:14:01 EDT 2001 ## File Type: perl script ## ## Purpose: To replace a pattern with another pattern ## in the specified files of an entire ## subdirectory tree. ## ## set module-scoped variables and 'constants'. ## $TRUE = "true"; $FALSE = "false"; $HOME = $ENV{"HOME"}; $USER = $ENV{"USER"}; $USER =~ tr/a-z/A-Z/; $USER_Length = length( $USER ); $DATE = &getDate; $ARGC = @ARGV; $CVS_LOG_DIR = $HOME . "/.cvs_log"; $TEMP_FILE_EXTENTION = ".TSR"; $SEARCH_PATTERN = ""; $REPLACE_PATTERN = ""; $FILES_PATTERN = "*"; $TSR_METAFILE = ""; $TSR_METAFILE_EXT = ".tsrm"; $ANNOTATE = $FALSE; $PRINT_FILE_NAMES = $TRUE; $PRINT_LINE_NUMBERS = $FALSE; ## ## set some default values. ## $cmd_str = ""; $previous_file = ""; ## ## loop through the command line arguments screening for tsr flags. ## for( $i=0; $i<$ARGC; $i++ ) { $_ = $ARGV[$i]; if( /^-s$/ ) { $SEARCH_PATTERN = $ARGV[++$i]; ##printf stdout "SEARCH_PATTERN: ->%s<-\n", $SEARCH_PATTERN; } elsif( /^-r$/ ) { $REPLACE_PATTERN = $ARGV[++$i]; ##printf stdout "REPLACE_PATTERN: ->%s<-\n", $REPLACE_PATTERN; } elsif( /^-f$/ ) { $FILES_PATTERN = $ARGV[++$i]; ##printf stdout "FILES_PATTERN: ->%s<-\n", $FILES_PATTERN; } elsif( /^-a$/ ) { $ANNOTATE = $TRUE; } elsif( /^-fn$/ ) { $PRINT_FILE_NAMES = $TRUE; } elsif( /^-ln$/ ) { $PRINT_LINE_NUMBERS = $TRUE; } elsif( /^-MF$/ ) { $TSR_METAFILE = $ARGV[++$i]; ##printf stdout "TSR_METAFILE: ->%s<-\n", $TSR_METAFILE; if( $TSR_METAFILE eq "" ) { &listTsrMetafiles; &cleanup; } else { if( ! (-f $CVS_LOG_DIR . "/" . $TSR_METAFILE . $TSR_METAFILE_EXT) ) { $NEW_TSR_METAFILE = $TSR_METAFILE; $TSR_METAFILE = ""; $_ = ""; while( (! /^Y/) && (! /^N/) ) { printf stdout "!! Attention !!\n"; printf stdout "The tsr metafile you have specified ('" . $NEW_TSR_METAFILE . "')\n"; printf stdout "does NOT exist, would you like to" . " create it (Y/N) ? "; $_ = ; chop; $_ =~ tr/[a-z]/[A-Z]/; } if( ! /^Y/ ) { &cleanup; } } } } elsif( /^-h$/ || /^-help$/ ) { &showHelp; } else { @FILE_LIST = splice( @ARGV, $i ); ##printf "FILE_LIST: ->%s<-\n", join( ' ', @FILE_LIST ); $i = $ARGC; } } ## ## if no search pattern specified, cleanup. ## if( $SEARCH_PATTERN eq "" ) { printf "Error: tsr - No search pattern specified\n"; &usage; &cleanup( 1 ); } ## ## if a tsr metafile was specified on the command line, ## use its contents as the list of source files. ## if( $TSR_METAFILE ne "" ) { $cmd_str = $CVS_LOG_DIR . "/" . $TSR_METAFILE . $TSR_METAFILE_EXT; } elsif( $NEW_TSR_METAFILE ne "" ) { $cmd_str = "find . -name \"" . $FILES_PATTERN . "\" |"; } ## ## if files were specified on the command line, ## search through the specified files, otherwise ## maintain default of searching through ALL files. ## elsif( $FILES_PATTERN ne "" ) { $cmd_str = "find . -name \"" . $FILES_PATTERN . "\" |"; } if( $cmd_str ne "" ) { ## ## open pipe to the command. ## open( pCmd, $cmd_str ) || die "Error: tsr - Unable to open '" . $cmd_str . "' command"; $file_count = 0; while( ) { chop; ( @FILE_LIST[$file_count++], @junk ) = split( ':' ); } close( pCmd ); } if( @FILE_LIST ) { if( $NEW_TSR_METAFILE ne "" ) { $NEW_TSR_METAFILE_PATH = $CVS_LOG_DIR . "/" . $NEW_TSR_METAFILE . $TSR_METAFILE_EXT; printf stdout "NEW_TSR_METAFILE_PATH: ->%s<-\n", $NEW_TSR_METAFILE_PATH; open( pNewTsrMetafile, "> $NEW_TSR_METAFILE_PATH" ) || die "Error: tsr - Unable to create tsr metafile '" . $NEW_TSR_METAFILE . "'"; } foreach $input_file ( @FILE_LIST ) { if( pNewTsrMetafile ) { printf pNewTsrMetafile "%s\n", $input_file; } if( $input_file eq $previous_file ) { next; } $previous_file = $input_file; $_ = $input_file; ## ## do not process the current and parent directory entries. ## if( /^\.$/ || /^\.\.$/ ) { next; } if( $ANNOTATE eq $TRUE ) { @ANNOTATION = &getAnnotation( $input_file ); } ## ## open the input file for read. ## if( ! open( pInputFile, $input_file ) ) { printf stderr "Error: tsr - Unable to open file '" . $_ . "' for read\n"; next; } ## ## open the temp output file for write. ## if( $REPLACE_PATTERN ne "" ) { $temp_file = $input_file . $TEMP_FILE_EXTENTION; open( pOutputFile, "> $temp_file" ) || die "Error: tsr - Unable to open temp output file '" . $temp_file . "' for write"; } $line_count = 0; while( ) { ++$line_count; chop; if( /$SEARCH_PATTERN/ ) { if( $REPLACE_PATTERN ne "" ) { printf stdout "MATCH FOUND in '%s' ...", $input_file; if( @ANNOTATION[0] ne "" ) { printf pOutputFile "%s\n", $ANNOTATION[0]; printf pOutputFile "%s\n", $_; printf pOutputFile "%s\n", $ANNOTATION[1]; s/$SEARCH_PATTERN/$REPLACE_PATTERN/g; printf pOutputFile "%s\n", $_; printf pOutputFile "%s\n", $ANNOTATION[2]; } else { s/$SEARCH_PATTERN/$REPLACE_PATTERN/g; printf pOutputFile "%s\n", $_; } printf stdout "REPLACED.", $input_file; printf stdout "\n"; } else { if( $PRINT_FILE_NAMES eq $TRUE ) { printf stdout "%s:", $input_file; } if( $PRINT_LINE_NUMBERS eq $TRUE ) { printf stdout "%d:", $line_count; } printf stdout "%s\n", $_; } } else { print pOutputFile $_, "\n"; } } if( pInputFile ) { close( pInputFile ); } if( $REPLACE_PATTERN ) { close( pOutputFile ); ## ## rename the temp file to replace the original file. ## system( "mv " . $temp_file . " " . $input_file ); } } if( pNewTsrMetafile ) { close( pNewTsrMetafile ); } } else { printf "Error: tsr - No files specified.\n"; &usage; &cleanup; } ##----- sub getAnnotation ----- sub getAnnotation { local( $_ ) = @_; local( @annotation ) = null; local( $file_type_known ) = $FALSE; local( $open_comment ) = ""; local( $hang_comment ) = ""; local( $close_comment ) = ""; if( /\.c$/ || /\.reg$/ || /\.h$/ ) { $open_comment = "/*"; $hang_comment = "* /"; $close_comment = "*/"; $file_type_known = $TRUE; } elsif( /\.html$/ ) { $open_comment = ""; $file_type_known = $TRUE; } if( $file_type_known eq $TRUE ) { @annotation[0] = $open_comment . "tsr-annotation{ ===== " . $USER . " " . $DATE . " =====" . $hang_comment; @annotation[1] = $open_comment . "-" x ( length(@annotation[0]) -4 ) . $close_comment; @annotation[2] = $open_comment . "tsr-annotation} " . "=" x (length(@annotation[0]) - length("tsr-annotation{ ") -4) . $close_comment; } return @annotation; } ##----- sub listTsrMetafiles ----- sub listTsrMetafiles { local( $cmd_str ) = "cd " . $CVS_LOG_DIR . "; ls *" . $TSR_METAFILE_EXT; open( pCmd, "$cmd_str |" ) || die "Error: cvs - Unable to open '" . $cmd_str . "' command pipe"; while( ) { chop; @fields = split( /\./, $_ ); printf stdout "%s\n", @fields[0]; } close( pCmd ); } ##----- sub getDate ----- sub getDate { local( $date ) = ""; local( $cmd_str ); $cmd_str = "date"; open( pDateCmd, "$cmd_str |" ) || die "Error: tsr - Unable to open '" . $cmd_str . "' command pipe"; $date = ; chop $date; close( pDateCmd ); return $date; } ##----- sub usage ----- sub usage { printf stdout "Usage: tsr [-h[elp]] [-s] [-r] [-f] [-a] [-ln]" . " [-MF [tsr metafile]] [file specs]\n"; } ##----- sub showHelp ----- sub showHelp { &usage; printf stdout "\n"; printf stdout " flags:\n"; printf stdout " -h,-help display this help info.\n"; printf stdout " -s pattern for which to" . " search\n"; printf stdout " -r pattern with which to" . " replace 'search pattern'\n"; printf stdout " -f files in which to" . " perform search/replace\n"; printf stdout " -a create annotations" . " (comments) arround search and\n" . " replace patterns" . " in target files\n"; printf stdout " -ln print line numbers\n"; printf stdout " -MF [metafile] 'metafile' contains names of" . " modules (one per line)\n" . " upon which to perform the" . " specified command. If\n" . " 'metafile' not specified" . ", returns list of available\n" . " metafiles\n"; ##printf stdout " -fn print file names\n"; &cleanup( 0 ); } ##----- sub cleanup ----- sub cleanup { local( $exit_code ) = @_; exit $exit_code; }