1#!/usr/bin/python
2#
3# Simple utility script to manipulate
4# certain types of strings in a file
5
6# This can be used in various projects where
7# there is the need to replace strings in files,
8# and is copied from GLib's $(srcroot)/win32
9
10# Author: Fan, Chun-wei
11# Date: September 03, 2014
12
13import sys
14import re
15import argparse
16
17valid_actions = ['remove-prefix',
18                 'replace-var',
19                 'replace-str',
20                 'remove-str']
21
22def open_file(filename, mode):
23    if sys.version_info[0] < 3:
24        return open(filename, mode=mode)
25    else:
26        return open(filename, mode=mode, encoding='utf-8')
27
28def replace_multi(src, dest, replace_items):
29    with open_file(src, 'r') as s:
30        with open_file(dest, 'w') as d:
31            for line in s:
32                replace_dict = dict((re.escape(key), value) \
33                               for key, value in replace_items.items())
34                replace_pattern = re.compile("|".join(replace_dict.keys()))
35                d.write(replace_pattern.sub(lambda m: \
36                        replace_dict[re.escape(m.group(0))], line))
37
38def replace(src, dest, instring, outstring):
39    replace_item = {instring: outstring}
40    replace_multi(src, dest, replace_item)
41
42def check_required_args(args, params):
43    for param in params:
44        if getattr(args, param, None) is None:
45            raise SystemExit('%s: error: --%s argument is required' % (__file__, param))
46
47def warn_ignored_args(args, params):
48    for param in params:
49        if getattr(args, param, None) is not None:
50            print('%s: warning: --%s argument is ignored' % (__file__, param))
51
52def main(argv):
53
54    parser = argparse.ArgumentParser(description='Process strings in a file.')
55    parser.add_argument('-a',
56                        '--action',
57                        help='Action to carry out.  Can be one of:\n'
58                             'remove-prefix\n'
59                             'replace-var\n'
60                             'replace-str\n'
61                             'remove-str',
62                        choices=valid_actions)
63    parser.add_argument('-i', '--input', help='Input file')
64    parser.add_argument('-o', '--output', help='Output file')
65    parser.add_argument('--instring', help='String to replace or remove')
66    parser.add_argument('--var', help='Autotools variable name to replace')
67    parser.add_argument('--outstring',
68                        help='New String to replace specified string or variable')
69    parser.add_argument('--removeprefix', help='Prefix of string to remove')
70
71    args = parser.parse_args()
72
73    input_string = ''
74    output_string = ''
75
76    # We must have action, input, output for all operations
77    check_required_args(args, ['action','input','output'])
78
79    # Build the arguments by the operation that is to be done,
80    # to be fed into replace()
81
82    # Get rid of prefixes from a string
83    if args.action == 'remove-prefix':
84        check_required_args(args, ['instring','removeprefix'])
85        warn_ignored_args(args, ['outstring','var'])
86        input_string = args.removeprefix + args.instring
87        output_string = args.instring
88
89    # Replace an m4-style variable (those surrounded by @...@)
90    if args.action == 'replace-var':
91        check_required_args(args, ['var','outstring'])
92        warn_ignored_args(args, ['instring','removeprefix'])
93        input_string = '@' + args.var + '@'
94        output_string = args.outstring
95
96    # Replace a string
97    if args.action == 'replace-str':
98        check_required_args(args, ['instring','outstring'])
99        warn_ignored_args(args, ['var','removeprefix'])
100        input_string = args.instring
101        output_string = args.outstring
102
103    # Remove a string
104    if args.action == 'remove-str':
105        check_required_args(args, ['instring'])
106        warn_ignored_args(args, ['var','outstring','removeprefix'])
107        input_string = args.instring
108        output_string = ''
109
110    replace(args.input, args.output, input_string, output_string)
111
112    return 0
113
114if __name__ == '__main__':
115    sys.exit(main(sys.argv))
116