mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +01:00
1672678bc4
Fixes get_type function generation for: - GMountMountFlags - GDriveStartFlags - GResourceLookupFlags - GSocketMsgFlags - GTlsDatabaseVerifyFlags - GTestDBusFlags which were registered as enum types before, which broke some unit tests. Problem is that the flags annotation has no value, so options.get('flags') would always return None even if it was present. https://bugzilla.gnome.org/show_bug.cgi?id=779332
594 lines
22 KiB
Python
Executable File
594 lines
22 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# If the code below looks horrible and unpythonic, do not panic.
|
|
#
|
|
# It is.
|
|
#
|
|
# This is a manual conversion from the original Perl script to
|
|
# Python. Improvements are welcome.
|
|
|
|
import os, sys, re, argparse, tempfile
|
|
|
|
output_stream = sys.stdout
|
|
|
|
def write_output(output):
|
|
global output_stream
|
|
print(output, file=output_stream)
|
|
|
|
version = '@GLIB_VERSION@'
|
|
|
|
# glib-mkenums.py
|
|
# Information about the current enumeration
|
|
flags = False # Is enumeration a bitmask?
|
|
option_underscore_name = '' # Overriden underscore variant of the enum name
|
|
# for example to fix the cases we don't get the
|
|
# mixed-case -> underscorized transform right.
|
|
option_lowercase_name = '' # DEPRECATED. A lower case name to use as part
|
|
# of the *_get_type() function, instead of the
|
|
# one that we guess. For instance, when an enum
|
|
# uses abnormal capitalization and we can not
|
|
# guess where to put the underscores.
|
|
seenbitshift = 0 # Have we seen bitshift operators?
|
|
enum_prefix = None # Prefix for this enumeration
|
|
enumname = '' # Name for this enumeration
|
|
enumshort = '' # $enumname without prefix
|
|
enumname_prefix = '' # prefix of $enumname
|
|
enumindex = 0 # Global enum counter
|
|
firstenum = 1 # Is this the first enumeration per file?
|
|
entries = [] # [ name, val ] for each entry
|
|
sandbox = None # sandbox for safe evaluation of expressions
|
|
|
|
output = '' # Filename to write result into
|
|
|
|
def parse_trigraph(opts):
|
|
result = {}
|
|
|
|
for opt in re.split(r'\s*,\s*', opts):
|
|
opt = re.sub(r'^\s*', '', opt)
|
|
opt = re.sub(r'\s*$', '', opt)
|
|
m = re.search(r'(\w+)(?:=(.+))?', opt)
|
|
assert(m is not None)
|
|
groups = m.groups()
|
|
key = groups[0]
|
|
if len(groups) > 1:
|
|
val = groups[1]
|
|
else:
|
|
val = 1
|
|
result[key] = val
|
|
return result
|
|
|
|
def parse_entries(file, file_name):
|
|
global entries, enumindex, enumname, seenbitshift, flags
|
|
looking_for_name = False
|
|
|
|
for line in file:
|
|
# read lines until we have no open comments
|
|
while re.search(r'/\*([^*]|\*(?!/))*$', line):
|
|
line = file.readline()
|
|
|
|
# strip comments w/o options
|
|
line = re.sub(r'''/\*(?!<)
|
|
([^*]+|\*(?!/))*
|
|
\*/''', '', line, flags=re.X)
|
|
|
|
line = line.rstrip()
|
|
|
|
# skip empty lines
|
|
if len(line.strip()) == 0:
|
|
continue
|
|
|
|
if looking_for_name:
|
|
m = re.match('\s*(\w+)', line)
|
|
if m:
|
|
enumname = m.group(1);
|
|
return True
|
|
|
|
# Handle include files
|
|
m = re.match(r'\#include\s*<([^>]*)>', line)
|
|
if m:
|
|
newfilename = os.path.join("..", m.group(1))
|
|
newfile = open(newfilename)
|
|
|
|
if not parse_entries(newfile, newfilename):
|
|
return False
|
|
else:
|
|
continue
|
|
|
|
m = re.match(r'\s*\}\s*(\w+)', line)
|
|
if m:
|
|
enumname = m.group(1)
|
|
enumindex+=1;
|
|
return 1;
|
|
|
|
m = re.match(r'\s*\}', line)
|
|
if m:
|
|
enumindex+=1;
|
|
looking_for_name = True
|
|
continue
|
|
|
|
m = re.match(r'''\s*
|
|
(\w+)\s* # name
|
|
(?:=( # value
|
|
\s*\w+\s*\(.*\)\s* # macro with multiple args
|
|
| # OR
|
|
(?:[^,/]|/(?!\*))* # anything but a comma or comment
|
|
))?,?\s*
|
|
(?:/\*< # options
|
|
(([^*]|\*(?!/))*)
|
|
>\s*\*/)?,?
|
|
\s*$''', line, flags=re.X)
|
|
if m:
|
|
groups = m.groups()
|
|
name = groups[0]
|
|
value = None
|
|
options = None
|
|
if len(groups) > 1:
|
|
value = groups[1]
|
|
if len(groups) > 2:
|
|
options = groups[2]
|
|
if not flags and value is not None and '<<' in value:
|
|
seenbitshift = 1
|
|
|
|
if options is not None:
|
|
options = parse_trigraph(options)
|
|
if 'skip' in options:
|
|
entries.append((name, value, options['nick']));
|
|
else:
|
|
entries.append((name, value))
|
|
elif re.match('s*\#', line):
|
|
pass
|
|
else:
|
|
sys.exit("Failed to parse %s." % file_name)
|
|
return False
|
|
|
|
def print_version():
|
|
print("glib-mkenums version glib-" + version)
|
|
print("glib-mkenums comes with ABSOLUTELY NO WARRANTY.")
|
|
print("You may redistribute copies of glib-mkenums under the terms of")
|
|
print("the GNU General Public License which can be found in the")
|
|
print("GLib source package. Sources, examples and contact")
|
|
print("information are available at http://www.gtk.org")
|
|
sys.exit(0)
|
|
|
|
help_epilog = '''Production text substitutions:
|
|
\u0040EnumName\u0040 PrefixTheXEnum
|
|
\u0040enum_name\u0040 prefix_the_xenum
|
|
\u0040ENUMNAME\u0040 PREFIX_THE_XENUM
|
|
\u0040ENUMSHORT\u0040 THE_XENUM
|
|
\u0040ENUMPREFIX\u0040 PREFIX
|
|
\u0040VALUENAME\u0040 PREFIX_THE_XVALUE
|
|
\u0040valuenick\u0040 the-xvalue
|
|
\u0040valuenum\u0040 the integer value (limited support, Since: 2.26)
|
|
\u0040type\u0040 either enum or flags
|
|
\u0040Type\u0040 either Enum or Flags
|
|
\u0040TYPE\u0040 either ENUM or FLAGS
|
|
\u0040filename\u0040 name of current input file
|
|
\u0040basename\u0040 base name of the current input file (Since: 2.22)
|
|
'''
|
|
|
|
|
|
# production variables:
|
|
idprefix = "" # "G", "Gtk", etc
|
|
symprefix = "" # "g", "gtk", etc, if not just lc($idprefix)
|
|
fhead = "" # output file header
|
|
fprod = "" # per input file production
|
|
ftail = "" # output file trailer
|
|
eprod = "" # per enum text (produced prior to value itarations)
|
|
vhead = "" # value header, produced before iterating over enum values
|
|
vprod = "" # value text, produced for each enum value
|
|
vtail = "" # value tail, produced after iterating over enum values
|
|
comment_tmpl = "" # comment template
|
|
|
|
def read_template_file(file):
|
|
global idprefix, symprefix, fhead, fprod, ftail, eprod, vhead, vprod, vtail, comment_tmpl
|
|
tmpl = {'file-header': fhead,
|
|
'file-production': fprod,
|
|
'file-tail': ftail,
|
|
'enumeration-production': eprod,
|
|
'value-header': vhead,
|
|
'value-production': vprod,
|
|
'value-tail': vtail,
|
|
'comment': comment_tmpl,
|
|
}
|
|
in_ = 'junk'
|
|
|
|
ifile = open(file)
|
|
for line in ifile:
|
|
m = re.match(r'\/\*\*\*\s+(BEGIN|END)\s+([\w-]+)\s+\*\*\*\/', line)
|
|
if m:
|
|
if in_ == 'junk' and m.group(1) == 'BEGIN' and m.group(2) in tmpl:
|
|
in_ = m.group(2)
|
|
continue
|
|
elif in_ == m.group(2) and m.group(1) == 'END' and m.group(2) in tmpl:
|
|
in_ = 'junk'
|
|
continue
|
|
else:
|
|
sys.exit("Malformed template file " + file);
|
|
|
|
if in_ != 'junk':
|
|
tmpl[in_] += line
|
|
|
|
if in_ != 'junk':
|
|
sys.exit("Malformed template file " + file)
|
|
|
|
fhead = tmpl['file-header']
|
|
fprod = tmpl['file-production']
|
|
ftail = tmpl['file-tail']
|
|
eprod = tmpl['enumeration-production']
|
|
vhead = tmpl['value-header']
|
|
vprod = tmpl['value-production']
|
|
vtail = tmpl['value-tail']
|
|
comment_tmpl = tmpl['comment']
|
|
|
|
# default to C-style comments
|
|
if comment_tmpl == "":
|
|
comment_tmpl = "/* \u0040comment\u0040 */"
|
|
|
|
if len(sys.argv) == 1:
|
|
usage()
|
|
|
|
parser = argparse.ArgumentParser(epilog=help_epilog,
|
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
|
|
parser.add_argument('--identifier-prefix', default='', dest='idprefix',
|
|
help='Identifier prefix')
|
|
parser.add_argument('--symbol-prefix', default='', dest='symprefix',
|
|
help='symbol-prefix')
|
|
parser.add_argument('--fhead', default='', dest='fhead',
|
|
help='Output file header')
|
|
parser.add_argument('--ftail', default='', dest='ftail',
|
|
help='Per input file production')
|
|
parser.add_argument('--eprod', default='', dest='eprod',
|
|
help='Per enum text (produced prior to value iterations)')
|
|
parser.add_argument('--vhead', default='', dest='vhead',
|
|
help='Value header, produced before iterating over enum values')
|
|
parser.add_argument('--vprod', default='', dest='vprod',
|
|
help='Value text, produced for each enum value.')
|
|
parser.add_argument('--vtail', default='', dest='vtail',
|
|
help='Value tail, produced after iterating over enum values')
|
|
parser.add_argument('--comments', default='', dest='comment_tmpl',
|
|
help='Comment structure')
|
|
parser.add_argument('--template', default='', dest='template',
|
|
help='Template file')
|
|
parser.add_argument('--output', default=None, dest='output')
|
|
parser.add_argument('--version', '-v', default=False, action='store_true', dest='version',
|
|
help='Print version informations')
|
|
parser.add_argument('args', nargs='*')
|
|
|
|
options = parser.parse_args()
|
|
|
|
if options.version:
|
|
print_version()
|
|
|
|
if options.template != '':
|
|
read_template_file(options.template)
|
|
|
|
idprefix += options.idprefix
|
|
symprefix += options.symprefix
|
|
fhead += options.fhead
|
|
ftail += options.ftail
|
|
eprod += options.eprod
|
|
vhead += options.vhead
|
|
vprod += options.vprod
|
|
vtail += options.vtail
|
|
if options.comment_tmpl != '':
|
|
comment_tmpl = options.comment_tmpl
|
|
output = options.output
|
|
|
|
if output is not None:
|
|
(out_dir, out_fn) = os.path.split(options.output)
|
|
out_suffix = '_' + os.path.splitext(out_fn)[1]
|
|
if out_dir == '':
|
|
out_dir = '.'
|
|
tmpfile = tempfile.NamedTemporaryFile(dir=out_dir, delete=False)
|
|
output_stream = tmpfile
|
|
else:
|
|
tmpfile = None
|
|
|
|
# put auto-generation comment
|
|
comment = comment_tmpl.replace('\u0040comment\u0040', 'Generated data (by glib-mkenums)')
|
|
write_output("\n" + comment + '\n')
|
|
|
|
def replace_specials(prod):
|
|
prod = prod.replace(r'\\a', r'\a')
|
|
prod = prod.replace(r'\\b', r'\b')
|
|
prod = prod.replace(r'\\t', r'\t')
|
|
prod = prod.replace(r'\\n', r'\n')
|
|
prod = prod.replace(r'\\f', r'\f')
|
|
prod = prod.replace(r'\\r', r'\r')
|
|
prod = prod.rstrip()
|
|
return prod
|
|
|
|
if len(fhead) > 0:
|
|
prod = fhead;
|
|
base = os.path.basename(options.args[0])
|
|
|
|
prod = prod.replace('\u0040filename\u0040', options.args[0])
|
|
prod = prod.replace('\u0040basename\u0040', base)
|
|
prod = replace_specials(prod)
|
|
write_output(prod)
|
|
|
|
def process_file(curfilename):
|
|
global entries, flags, seenbitshift, enum_prefix
|
|
firstenum = True
|
|
curfile = open(curfilename)
|
|
for line in curfile:
|
|
# read lines until we have no open comments
|
|
while re.search(r'/\*([^*]|\*(?!/))*$', line):
|
|
line = curfile.readline()
|
|
|
|
# strip comments w/o options
|
|
line = re.sub(r'''/\*(?!<)
|
|
([^*]+|\*(?!/))*
|
|
\*/''', '', line)
|
|
|
|
# ignore forward declarations
|
|
if re.match(r'\s*typedef\s+enum.*;', line):
|
|
continue
|
|
|
|
m = re.match(r'''\s*typedef\s+enum\s*
|
|
({)?\s*
|
|
(?:/\*<
|
|
(([^*]|\*(?!/))*)
|
|
>\s*\*/)?
|
|
\s*({)?''', line, flags=re.X)
|
|
if m:
|
|
groups = m.groups()
|
|
if len(groups) >= 2 and groups[1] is not None:
|
|
options = parse_trigraph(groups[1]);
|
|
if 'skip' in options:
|
|
continue
|
|
enum_prefix = options.get('prefix', None)
|
|
flags = 'flags' in options
|
|
option_lowercase_name = options.get('lowercase_name', None)
|
|
option_underscore_name = options.get('underscore_name', None)
|
|
else:
|
|
enum_prefix = None
|
|
flags = False
|
|
option_lowercase_name = None
|
|
option_underscore_name = None
|
|
|
|
if option_lowercase_name is not None:
|
|
if option_underscore_name is not None:
|
|
print("$0: $ARGV:$.: lowercase_name overriden with underscore_name", file=sys.stderr)
|
|
option_lowercase_name = None
|
|
else:
|
|
print("$0: $ARGV:$.: lowercase_name is deprecated, use underscore_name", file=sys.stderr)
|
|
|
|
# Didn't have trailing '{' look on next lines
|
|
if groups[0] is None and (len(groups) < 4 or groups[3] is None):
|
|
while True:
|
|
line = curfile.readline()
|
|
if re.match(r'\s*\{', line):
|
|
break
|
|
|
|
seenbitshift = 0;
|
|
entries = [];
|
|
|
|
# Now parse the entries
|
|
parse_entries(curfile, curfilename);
|
|
|
|
# figure out if this was a flags or enums enumeration
|
|
if not flags:
|
|
flags = seenbitshift
|
|
|
|
# Autogenerate a prefix
|
|
if enum_prefix is None:
|
|
for entry in entries:
|
|
if len(entry) < 3 or entry[2] is None:
|
|
name = entry[0];
|
|
if enum_prefix is not None:
|
|
enum_prefix = os.path.commonprefix([name, enum_prefix])
|
|
else:
|
|
enum_prefix = name;
|
|
if enum_prefix is None:
|
|
enum_prefix = ""
|
|
else:
|
|
# Trim so that it ends in an underscore
|
|
enum_prefix = re.sub(r'_[^_]*$', '_', enum_prefix)
|
|
else:
|
|
# canonicalize user defined prefixes
|
|
enum_prefix = enum_prefix.upper()
|
|
enum_prefix = enum_prefix.replace('-', '_')
|
|
enum_prefix = re.sub(r'(.*)([^_])$', r'\1\2_')
|
|
|
|
fixed_entries = []
|
|
for e in entries:
|
|
name = e[0]
|
|
num = e[1]
|
|
if len(e) < 3 or e[2] is None:
|
|
nick = re.sub(r'^' + enum_prefix, '', name)
|
|
nick = nick.replace('_', '-').lower()
|
|
e = (name, num, nick)
|
|
fixed_entries.append(e)
|
|
entries = fixed_entries
|
|
|
|
# Spit out the output
|
|
if option_underscore_name is not None:
|
|
enumlong = option_underscore_name.upper()
|
|
enumsym = option_underscore_name.lower()
|
|
enumshort = re.sub(r'^[A-Z][A-Z0-9]*_', '', enumlong)
|
|
|
|
enumname_prefix = re.sub('_' + enumshort + '$', '', enumlong)
|
|
elif symprefix == '' and idprefix == '':
|
|
# enumname is e.g. GMatchType
|
|
enspace = re.sub(r'^([A-Z][a-z]*).*$', r'\1', enumname)
|
|
|
|
enumshort = re.sub(r'^[A-Z][a-z]*', '', enumname)
|
|
enumshort = re.sub(r'([^A-Z])([A-Z])', r'\1_\2', enumshort)
|
|
enumshort = re.sub(r'([A-Z][A-Z])([A-Z][0-9a-z])', r'\1_\2', enumshort)
|
|
enumshort = enumshort.upper()
|
|
|
|
enumname_prefix = re.sub(r'^([A-Z][a-z]*).*$', r'\1', enumname).upper()
|
|
|
|
enumlong = enspace.upper() + "_" + enumshort
|
|
enumsym = enspace.lower() + "_" + enumshort.lower()
|
|
|
|
if option_lowercase_name is not None:
|
|
enumsym = option_lowercase_name;
|
|
else:
|
|
enumshort = enumname;
|
|
if idprefix:
|
|
enumshort = re.sub(r'^' + idprefix, '', enumshort)
|
|
else:
|
|
enumshort = re.sub(r'/^[A-Z][a-z]*', '', enumshort)
|
|
|
|
enumshort = re.sub(r'([^A-Z])([A-Z])', r'\1_\2', enumshort)
|
|
enumshort = re.sub(r'([A-Z][A-Z])([A-Z][0-9a-z])', r'\1_\2', enumshort)
|
|
enumshort = enumshort.upper();
|
|
|
|
if symprefix is not None:
|
|
enumname_prefix = symprefix.upper()
|
|
else:
|
|
enumname_prefix = idprefix.upper()
|
|
|
|
enumlong = enumname_prefix + "_" + enumshort
|
|
enumsym = enumlong.lower()
|
|
|
|
if firstenum:
|
|
firstenum = False
|
|
|
|
if len(fprod) > 0:
|
|
prod = fprod;
|
|
base = os.path.basename(curfilename);
|
|
|
|
prod = prod.replace('\u0040filename\u0040', curfilename)
|
|
prod = prod.replace('\u0040basename\u0040', base)
|
|
prod = replace_specials(prod)
|
|
|
|
write_output(prod)
|
|
|
|
if len(eprod) > 0:
|
|
prod = eprod;
|
|
|
|
prod = prod.replace('\u0040enum_name\u0040', enumsym)
|
|
prod = prod.replace('\u0040EnumName\u0040', enumname)
|
|
prod = prod.replace('\u0040ENUMSHORT\u0040', enumshort)
|
|
prod = prod.replace('\u0040ENUMNAME\u0040', enumlong)
|
|
prod = prod.replace('\u0040ENUMPREFIX\u0040', enumname_prefix)
|
|
if flags:
|
|
prod =~ prod.replace('\u0040type\u0040', 'flags')
|
|
else:
|
|
prod = prod.replace('\u0040type\u0040', 'enum')
|
|
if flags:
|
|
prod = prod.replace('\u0040Type\u0040', 'Flags')
|
|
else:
|
|
prod = prod.replace('\u0040Type\u0040', 'Enum')
|
|
if flags:
|
|
prod = prod.replace('\u0040TYPE\u0040', 'FLAGS')
|
|
else:
|
|
prod = prod.replace('\u0040TYPE\u0040', 'ENUM')
|
|
prod = replace_specials(prod)
|
|
write_output(prod)
|
|
|
|
if len(vhead) > 0:
|
|
prod = vhead;
|
|
prod = prod.replace('\u0040enum_name\u0040', enumsym)
|
|
prod = prod.replace('\u0040EnumName\u0040', enumname)
|
|
prod = prod.replace('\u0040ENUMSHORT\u0040', enumshort)
|
|
prod = prod.replace('\u0040ENUMNAME\u0040', enumlong)
|
|
prod = prod.replace('\u0040ENUMPREFIX\u0040', enumname_prefix)
|
|
if flags:
|
|
prod = prod.replace('\u0040type\u0040', 'flags')
|
|
else:
|
|
prod = prod.replace('\u0040type\u0040', 'enum')
|
|
if flags:
|
|
prod = prod.replace('\u0040Type\u0040', 'Flags')
|
|
else:
|
|
prod = prod.replace('\u0040Type\u0040', 'Enum')
|
|
if flags:
|
|
prod = prod.replace('\u0040TYPE\u0040', 'FLAGS')
|
|
else:
|
|
prod = prod.replace('\u0040TYPE\u0040', 'ENUM')
|
|
prod = replace_specials(prod)
|
|
write_output(prod)
|
|
|
|
if len(vprod) > 0:
|
|
prod = vprod;
|
|
next_num = 0
|
|
|
|
prod = replace_specials(prod)
|
|
for name, num, nick in entries:
|
|
tmp_prod = prod
|
|
|
|
if '\u0040valuenum\u0040' in prod:
|
|
# only attempt to eval the value if it is requested
|
|
# this prevents us from throwing errors otherwise
|
|
if num is not None:
|
|
# use sandboxed evaluation as a reasonable
|
|
# approximation to C constant folding
|
|
inum = eval(num, {}, {});
|
|
|
|
# make sure it parsed to an integer
|
|
if not isinstance(inum, int):
|
|
sys.exit("Unable to parse enum value '%s'" % num)
|
|
num = inum
|
|
else:
|
|
num = next_num
|
|
|
|
tmp_prod = tmp_prod.replace('\u0040valuenum\u0040', str(num))
|
|
next_num = int(num) + 1
|
|
|
|
tmp_prod = tmp_prod.replace('\u0040VALUENAME\u0040', name)
|
|
tmp_prod = tmp_prod.replace('\u0040valuenick\u0040', nick)
|
|
if flags:
|
|
tmp_prod = tmp_prod.replace('\u0040type\u0040', 'flags')
|
|
else:
|
|
tmp_prod = tmp_prod.replace('\u0040type\u0040', 'enum')
|
|
if flags:
|
|
tmp_prod = tmp_prod.replace('\u0040Type\u0040', 'Flags')
|
|
else:
|
|
tmp_prod = tmp_prod.replace('\u0040Type\u0040', 'Enum')
|
|
if flags:
|
|
tmp_prod = tmp_prod.replace('\u0040TYPE\u0040', 'FLAGS')
|
|
else:
|
|
tmp_prod = tmp_prod.replace('\u0040TYPE\u0040', 'ENUM')
|
|
tmp_prod = tmp_prod.rstrip()
|
|
|
|
write_output(tmp_prod)
|
|
|
|
if len(vtail) > 0:
|
|
prod = vtail
|
|
prod = prod.replace('\u0040enum_name\u0040', enumsym)
|
|
prod = prod.replace('\u0040EnumName\u0040', enumname)
|
|
prod = prod.replace('\u0040ENUMSHORT\u0040', enumshort)
|
|
prod = prod.replace('\u0040ENUMNAME\u0040', enumlong)
|
|
prod = prod.replace('\u0040ENUMPREFIX\u0040', enumname_prefix)
|
|
if flags:
|
|
prod = prod.replace('\u0040type\u0040', 'flags')
|
|
else:
|
|
prod = prod.replace('\u0040type\u0040', 'enum')
|
|
if flags:
|
|
prod = prod.replace('\u0040Type\u0040', 'Flags')
|
|
else:
|
|
prod = prod.replace('\u0040Type\u0040', 'Enum')
|
|
if flags:
|
|
prod = prod.replace('\u0040TYPE\u0040', 'FLAGS')
|
|
else:
|
|
prod = prod.replace('\u0040TYPE\u0040', 'ENUM')
|
|
prod = replace_specials(prod)
|
|
write_output(prod)
|
|
|
|
for fname in options.args:
|
|
process_file(fname)
|
|
|
|
if len(ftail) > 0:
|
|
prod = ftail
|
|
base = os.path.basename(options.args[-1]) # FIXME, wrong
|
|
|
|
prod = prod.replace('\u0040filename\u0040', 'ARGV') # wrong too
|
|
prod = prod.replace('\u0040basename\u0040', base)
|
|
prod = replace_specials(prod)
|
|
write_output(prod)
|
|
|
|
# put auto-generation comment
|
|
comment = comment_tmpl;
|
|
comment = comment.replace('\u0040comment\u0040', 'Generated data ends here')
|
|
write_output("\n" + comment + "\n")
|
|
|
|
if tmpfile is not None:
|
|
tmpfilename = tmpfile.name
|
|
tmpfile.close()
|
|
os.unlink(options.output)
|
|
os.rename(tmpfilename, options.output)
|