#!/usr/bin/env python
#
# Copyright 2006 Free Software Foundation, Inc.
# 
# This file is part of GNU Radio
# 
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# 
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#

import re
import os
import os.path
import sys
from optparse import OptionParser

dry_run = False
modified_files = []

dirs_to_ignore = ('CVS', '.svn', '.deps', '.libs')
extensions_to_ignore = ('.o', '.lo',
                        '.a', '.la', '.lai',
                        '.so', '.soT',
                        '.pyc', '.pyo',
                        '.ko', '.fasl', '.rwbak',
                        '.tar', '.gz', '.log',
                        '.eps', '.ps', '.pdf',
                        '.png', '.jpg', '.jpeg', '.bmp',
                        '.dat', '.ihx',
                        '.diff',
                        '.lib', '.lst', '.rel', '.sym', '.asm', '.rst', 'mem', '.map', # sdcc output
                        '.rbf', '.esf', '.qpf', '.psf', '.quartus', '.bsf', '.cmp'     # quartus
                        )

def destructively_remove(list, predicate):
    """
    Destructively remove elements from LIST for which PREDICATE is true
    """
    for i in range(len(list)):
        if predicate(list[i]):
            del list[i]
            destructively_remove(list, predicate)
            return


def expunge_unwanted_dirnames(dirnames):
    """
    Destructively remove directory names that we don't want to visit.
    This is a _very_ non-functional approach to programming...
    """
    destructively_remove(dirnames, lambda d: d in dirs_to_ignore)

def expunge_unwanted_filenames(filenames):
    """
    Destructively remove filenames that we don't want to visit.
    This is a _very_ non-functional approach to programming...
    """
    destructively_remove(filenames,
                         lambda f: f.endswith('~') or os.path.splitext(f)[1] in extensions_to_ignore)


def walk_directory(dirname):
    for dirpath, dirnames, filenames in os.walk(dirname):
        expunge_unwanted_dirnames(dirnames)
        expunge_unwanted_filenames(filenames)
        for f in filenames:
            update_one(os.path.join(dirpath, f))


addr_pattern = re.compile(r'\b59 Temple Place(,| *-) *Suite 330\b', re.IGNORECASE)
addr_replacement = '51 Franklin Street'
zip_pattern  = re.compile(r'\b02111-1307\b')
zip_replacement = '02110-1301'

def update_one(filename):
    f = open(filename, 'r')
    s = f.read()
    f.close()
    t = s
    t = addr_pattern.sub(addr_replacement, t)
    t = zip_pattern.sub(zip_replacement, t)
    if s != t:
        modified_files.append(filename)
        if not dry_run:
            f = open(filename, 'w')
            f.write(t)


def handle_file_or_dir(file_or_dir):
    if os.path.isfile(file_or_dir):
        update_one(file_or_dir)
    elif os.path.isdir(file_or_dir):
        walk_directory(file_or_dir)
    else:
        pass   # ignore the other cases


def main():
    global dry_run
    
    usage = '%prog: [options] [file_or_dir...]'
    parser = OptionParser (usage=usage)
    parser.add_option('-l', '--list-modified-files', action='store_true', default=False,
                      help='List modified files to stdout [default=%default]')
    parser.add_option('', '--dry-run', action='store_true', default=False,
                      help="Don't modify any files, just report what would be modified [default=%default]")
    (options, args) = parser.parse_args()

    dry_run = options.dry_run
    if options.dry_run:
        options.list_modified_files = True
        
    for file_or_dir in args:
        handle_file_or_dir(file_or_dir)

    if options.list_modified_files:
        for f in modified_files:
            sys.stdout.write(f + '\n')

        
if __name__ == '__main__':
    main()