diff options
-rw-r--r-- | ChangeLog.txt | 1 | ||||
-rwxr-xr-x | makewrappers | 442 |
2 files changed, 222 insertions, 221 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt index 2f15cc8..a197776 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,5 +1,6 @@ 2010-10-12: * (seebs) add missing copyright to Python makewrappers. + * (seebs) detab makewrappers 2010-10-11: * (seebs) do the other *xattr() wrappers. diff --git a/makewrappers b/makewrappers index c27afa8..8fb1484 100755 --- a/makewrappers +++ b/makewrappers @@ -30,97 +30,97 @@ class SourceFile(object): "A template for creating a source file" def __init__(self, path): - # default values... - # no name or file yet - self.name = '' - self.sections = {} - self.file = None - self.path = None - # open a new file for each function - self.file_per_func = False - - # empty footer if none specified: - self.sections['footer'] = [] - - # lines appended to body by default - self.sections['body'] = [] - current = self.sections['body'] + # default values... + # no name or file yet + self.name = '' + self.sections = {} + self.file = None + self.path = None + # open a new file for each function + self.file_per_func = False + + # empty footer if none specified: + self.sections['footer'] = [] + + # lines appended to body by default + self.sections['body'] = [] + current = self.sections['body'] self.f = file(path, 'r') - if not self.f: - return None - for line in self.f: - line = line.rstrip() - if line.startswith('@'): - if ' ' in line: - leading, trailing = line.split(' ', 1) - else: - leading, trailing = line, None - - if leading == '@name': - if not trailing: - raise Exception("@name requires a file name.") - self.path = trailing - if '$' in self.path: - self.file_per_func = True - else: - section = leading[1:] - if not section in self.sections: - self.sections[section] = [] - current = self.sections[section] - else: - current.append(line) - for section, data in self.sections.items(): - self.sections[section] = Template("\n".join(data)) + if not self.f: + return None + for line in self.f: + line = line.rstrip() + if line.startswith('@'): + if ' ' in line: + leading, trailing = line.split(' ', 1) + else: + leading, trailing = line, None + + if leading == '@name': + if not trailing: + raise Exception("@name requires a file name.") + self.path = trailing + if '$' in self.path: + self.file_per_func = True + else: + section = leading[1:] + if not section in self.sections: + self.sections[section] = [] + current = self.sections[section] + else: + current.append(line) + for section, data in self.sections.items(): + self.sections[section] = Template("\n".join(data)) # You need a file if this isn't a file-per-func - if not self.file_per_func: - self.file = file(self.path, 'w') - if not self.file: - raise IOError("Couldn't open %s to read a template." % self.path) + if not self.file_per_func: + self.file = file(self.path, 'w') + if not self.file: + raise IOError("Couldn't open %s to read a template." % self.path) def __del__(self): if self.file: - self.file.close() + self.file.close() def __repr__(self): - strings = [] - if self.file_per_func: + strings = [] + if self.file_per_func: strings.append("path: %s (per func)" % self.path) - else: + else: strings.append("path: %s" % self.path) - for name, data in self.sections.items(): - strings.append("%s:" % name) - strings.append(data.safe_substitute({})) - return "\n".join(strings) + for name, data in self.sections.items(): + strings.append("%s:" % name) + strings.append(data.safe_substitute({})) + return "\n".join(strings) def emit(self, template, func = None): - if self.file_per_func: - if not func: - # print "Must have a function to emit any part of a file-per-func template." - return - path = Template(self.path).safe_substitute(func) - if os.path.exists(path): - # print "We don't overwrite existing files." - return - self.file = file(path, 'w') - if not self.file: - print "Couldn't open '%s' (expanded from %s), not emitting '%s'." % (path, self.path, template) - return - - if template == "copyright": - # hey, at least it's not a global variable, amirite? - self.file.write(SourceFile.copyright) - elif template in self.sections: - templ = self.sections[template] - self.file.write(templ.safe_substitute(func)) - self.file.write("\n") - else: - print "Warning: Unknown template '%s'." % template - - if self.file_per_func: - self.file.close() - self.file = None + if self.file_per_func: + if not func: + # print "Must have a function to emit any part of a file-per-func template." + return + path = Template(self.path).safe_substitute(func) + if os.path.exists(path): + # print "We don't overwrite existing files." + return + self.file = file(path, 'w') + if not self.file: + print "Couldn't open '%s' (expanded from %s), not emitting '%s'." % (path, self.path, template) + return + + if template == "copyright": + # hey, at least it's not a global variable, amirite? + self.file.write(SourceFile.copyright) + elif template in self.sections: + templ = self.sections[template] + self.file.write(templ.safe_substitute(func)) + self.file.write("\n") + else: + print "Warning: Unknown template '%s'." % template + + if self.file_per_func: + self.file.close() + self.file = None class ArgumentList: "A (possibly empty) list of arguments" @@ -128,14 +128,14 @@ class ArgumentList: def __init__(self, text): "parse a comma-separated argument list (may contain function prototypes)" self.args = [] - self.variadic = False - self.variadic_decl = "" - self.variadic_start = "" - self.variadic_end = "" - self.prologue_call_real = "/* pass the call on to the underlying syscall */" - # (void) is an empty list, not a list of a single argument which is void - if text == "void": - return + self.variadic = False + self.variadic_decl = "" + self.variadic_start = "" + self.variadic_end = "" + self.prologue_call_real = "/* pass the call on to the underlying syscall */" + # (void) is an empty list, not a list of a single argument which is void + if text == "void": + return depth = 0 accum = '' @@ -151,117 +151,117 @@ class ArgumentList: self.args.append(C_Argument(accum + arg)) accum = '' if depth != 0: - raise Exception("mismatched ()s while parsing '%s'" % text) + raise Exception("mismatched ()s while parsing '%s'" % text) if self.args[-1].vararg: - self.variadic = True - self.variadic_arg = self.args[-1] - self.last_fixed_arg = self.args[-2].name - self.variadic_decl = "va_list ap;\n" - self.variadic_start = "va_start(ap, %s);\n" % self.last_fixed_arg - if self.variadic_arg.vararg_wraps: - self.variadic_decl += "\t%s;\n" % self.variadic_arg.vararg_wraps.decl() - self.variadic_start += "\t%s = va_arg(ap, %s);\n\tva_end(ap);\n" % (self.variadic_arg.name, self.variadic_arg.type) - else: - self.variadic_end = "va_end(ap);\n" + self.variadic = True + self.variadic_arg = self.args[-1] + self.last_fixed_arg = self.args[-2].name + self.variadic_decl = "va_list ap;\n" + self.variadic_start = "va_start(ap, %s);\n" % self.last_fixed_arg + if self.variadic_arg.vararg_wraps: + self.variadic_decl += "\t%s;\n" % self.variadic_arg.vararg_wraps.decl() + self.variadic_start += "\t%s = va_arg(ap, %s);\n\tva_end(ap);\n" % (self.variadic_arg.name, self.variadic_arg.type) + else: + self.variadic_end = "va_end(ap);\n" self.prologue_call_real = '/* no way to pass a ... */\n\t\t\t\tassert(!"cannot chain to real versions of variadic functions");' def decl(self, **kw): - if not self.args: - return "void" + if not self.args: + return "void" - list = map(lambda x: x.decl(**kw), self.args) + list = map(lambda x: x.decl(**kw), self.args) return ', '.join(list) def call(self): if not self.args: - return "" - list = map(lambda x: x.call(), self.args) - return ', '.join(list) + return "" + list = map(lambda x: x.call(), self.args) + return ', '.join(list) def __repr__(self): if not self.args: - return "no arguments" + return "no arguments" else: - return '::'.join(map(lambda x:x.decl(), self.args)) + return '::'.join(map(lambda x:x.decl(), self.args)) class C_Argument: "A function argument such as 'char *path' or 'char (*foo)(void)'" def __init__(self, text): "get the type and name of a trivial C declaration" - self.vararg = False - self.function_pointer = False - self.spacer = '' - - if text == 'void': - raise Exception("Tried to declare a nameless object of type void.") - - if text.startswith('...'): - self.vararg = True - if len(text) > 3: - # we're a wrapper for something else, declared as - # ...{real_decl}, as in the third argument to open(2) - text = text[4:-1] - # stash a copy of these values without the vararg flag, so we can - # declare them prettily later - self.vararg_wraps = C_Argument(text) - else: - # nothing to do. - self.vararg_wraps = None - self.type, self.name = None, None - return - else: - self.vararg = False + self.vararg = False + self.function_pointer = False + self.spacer = '' + + if text == 'void': + raise Exception("Tried to declare a nameless object of type void.") + + if text.startswith('...'): + self.vararg = True + if len(text) > 3: + # we're a wrapper for something else, declared as + # ...{real_decl}, as in the third argument to open(2) + text = text[4:-1] + # stash a copy of these values without the vararg flag, so we can + # declare them prettily later + self.vararg_wraps = C_Argument(text) + else: + # nothing to do. + self.vararg_wraps = None + self.type, self.name = None, None + return + else: + self.vararg = False # try for a function pointer match = re.match('(.*)\(\*([a-zA-Z0-9_]*)\)\((.*)\)', text) if match: - self.function_pointer = True - self.args = match.group(3) + self.function_pointer = True + self.args = match.group(3) ret_type = match.group(1) args = match.group(3) - self.fulltype = "$ret_type(*)($args)" - self.name = match.group(2).rstrip(' ') - self.type = ret_type - else: + self.fulltype = "$ret_type(*)($args)" + self.name = match.group(2).rstrip(' ') + self.type = ret_type + else: # plain declaration match = re.match('(.*[ *])\(?\*?([a-zA-Z0-9_]*)\)?', text) # there may not be a match, say in the special case where an arg is '...' if match: - self.type, self.name = match.group(1).rstrip(' '), match.group(2) + self.type, self.name = match.group(1).rstrip(' '), match.group(2) else: self.type, self.name = None, None - # spacing between type and name, needed if type ends with a character - # which could be part of an identifier - if re.match('[_a-zA-Z0-9]', self.type[-1]): - self.spacer = ' ' + # spacing between type and name, needed if type ends with a character + # which could be part of an identifier + if re.match('[_a-zA-Z0-9]', self.type[-1]): + self.spacer = ' ' def decl(self, **kw): - comment = kw.get('comment', False) - if self.function_pointer: - decl = "%s%s(*%s)(%s)" % (self.type, self.spacer, self.name, self.args) - else: + comment = kw.get('comment', False) + if self.function_pointer: + decl = "%s%s(*%s)(%s)" % (self.type, self.spacer, self.name, self.args) + else: decl = "%s%s%s" % (self.type, self.spacer, self.name) if self.vararg: - if self.vararg_wraps: - if comment: - decl = "... { %s }" % decl - else: - decl = "... /* %s */" % decl - else: - decl = "..." - return decl + if self.vararg_wraps: + if comment: + decl = "... { %s }" % decl + else: + decl = "... /* %s */" % decl + else: + decl = "..." + return decl def call(self): - if self.type == 'void': - return '' + if self.type == 'void': + return '' if self.vararg and not self.vararg_wraps: - return "ap" + return "ap" - return self.name + return self.name def str(self): return self.decl() @@ -289,11 +289,11 @@ class C_Function: self.comments = None bits = re.match('([^(]*)\((.*)\)', function) - x = C_Argument(bits.group(1)) + x = C_Argument(bits.group(1)) self.type, self.name = x.type, x.name - # it's convenient to have this declared here so we can use its .decl later - if self.type != 'void': - self.rc = C_Argument("%s rc" % x.type) + # it's convenient to have this declared here so we can use its .decl later + if self.type != 'void': + self.rc = C_Argument("%s rc" % x.type) # Some args get special treatment: # * If the arg has a name ending in 'path', we will canonicalize it. @@ -303,9 +303,9 @@ class C_Function: # override the dirfd/flags values. self.args = ArgumentList(bits.group(2)) for arg in self.args.args: - # ignore varargs, they never get these special treatments - if arg.vararg: - pass + # ignore varargs, they never get these special treatments + if arg.vararg: + pass elif arg.name == 'dirfd': self.dirfd = 'dirfd' elif arg.name == 'flags': @@ -313,16 +313,16 @@ class C_Function: elif arg.name[-4:] == 'path': self.paths_to_munge.append(arg.name) - # pick default values - if self.type == 'void': - self.default_value = '' + # pick default values + if self.type == 'void': + self.default_value = '' elif self.type[-1:] == '*': - self.default_value = 'NULL' - else: - try: - self.default_value = default_values[self.type] + self.default_value = 'NULL' + else: + try: + self.default_value = default_values[self.type] except KeyError: - raise Exception("Function %s has return type %s, for which there is no default value." % (self.name, self.type)) + raise Exception("Function %s has return type %s, for which there is no default value." % (self.name, self.type)) # handle special comments, such as flags=AT_SYMLINK_NOFOLLOW if self.comments: @@ -337,10 +337,10 @@ class C_Function: def decl(self, **kw): if self.type[-1:] == '*': - spacer = '' - else: - spacer = ' ' - return "%s%s%s(%s)" % (self.type, spacer, self.name, self.args.decl(**kw)) + spacer = '' + else: + spacer = ' ' + return "%s%s%s(%s)" % (self.type, spacer, self.name, self.args.decl(**kw)) def decl_args(self): return self.args.decl() @@ -353,63 +353,63 @@ class C_Function: def alloc_paths(self): alloc_paths = [] - for p in self.paths_to_munge: + for p in self.paths_to_munge: alloc_paths.append("%s = pseudo_root_path(__func__, __LINE__, %s, %s, %s);" % (p, self.dirfd, p, self.flags)) - return "\n\t\t\t".join(alloc_paths); + return "\n\t\t\t".join(alloc_paths); def free_paths(self): free_paths = [] - # the cast is here because free's argument isn't const qualified, but - # the original path may have been -- but we only GET here if the path has - # been overwritten. - for p in self.paths_to_munge: + # the cast is here because free's argument isn't const qualified, but + # the original path may have been -- but we only GET here if the path has + # been overwritten. + for p in self.paths_to_munge: free_paths.append("free((void *) %s);" % p) - return "\n\t\t\t".join(free_paths); + return "\n\t\t\t".join(free_paths); def rc_return(self): if self.type == 'void': - return "return;" + return "return;" else: - return "return rc;" + return "return rc;" def rc_decl(self): if self.type == 'void': - return "" - else: - return "%s = %s;" % (self.rc.decl(), self.default_value) + return "" + else: + return "%s = %s;" % (self.rc.decl(), self.default_value) def rc_assign(self): if self.type == 'void': - return "(void)" - else: - return "rc =" + return "(void)" + else: + return "rc =" def def_return(self): if self.type == 'void': - return "return;" - else: - return "return %s;" % self.default_value + return "return;" + else: + return "return %s;" % self.default_value def __getitem__(self, key): - "Make this object look like a dict for Templates to use" - try: + "Make this object look like a dict for Templates to use" + try: attr = getattr(self, key) - except AttributeError: - # There's a few attributes that are handled inside the args object, so check there - # too... - attr = getattr(self.args, key) + except AttributeError: + # There's a few attributes that are handled inside the args object, so check there + # too... + attr = getattr(self.args, key) - if callable(attr): - return attr() - else: - return attr + if callable(attr): + return attr() + else: + return attr def __repr__(self): pretty = "%(name)s returns %(type)s and takes " % self - pretty += repr(self.args) + pretty += repr(self.args) if self.comments: pretty += ' (%s)' % self.comments - return pretty + return pretty files = {} @@ -424,13 +424,13 @@ def main(): for path in glob.glob('templates/*'): try: - source = SourceFile(path) - source.emit('copyright') - source.emit('header') - sources.append(source) - except IOError: - print "Invalid or malformed template %s. Aborting." % path - exit(1) + source = SourceFile(path) + source.emit('copyright') + source.emit('header') + sources.append(source) + except IOError: + print "Invalid or malformed template %s. Aborting." % path + exit(1) for filename in sys.argv[1:]: "parse the list of functions" @@ -440,27 +440,27 @@ def main(): line = line.rstrip(" \r\n") if line.startswith('#') or line == "": continue - try: + try: func = C_Function(line) - funcs.append(func) - sys.stdout.write(".") - except Exception as e: - print "Parsing failed:", e - exit(1) + funcs.append(func) + sys.stdout.write(".") + except Exception as e: + print "Parsing failed:", e + exit(1) f.close() - print "" + print "" # the per-function stuff print "Writing functions...", for func in funcs: "populate various tables and files with each function" - for source in sources: - source.emit('body', func) + for source in sources: + source.emit('body', func) print "done. Cleaning up." for source in sources: "clean up files" - source.emit('footer') + source.emit('footer') del source if __name__ == '__main__': |