From f186c71b9abc6d1beed5b200121d385d1d22f968 Mon Sep 17 00:00:00 2001 From: Partha Susarla <parthasarathi.susarla@nicta.com.au> Date: Mon, 4 Apr 2016 15:31:22 +1000 Subject: [PATCH] SELFOUR-404: Remove hardcoded constants in stub generator. `syscall_stub_gen` has hardcoded constants for word size, this patch removes that constraint and makes the word size an argument to the program instead. The word size can either be passed either as command line arugmemt (-w option) or a path to the build configuration file can be given(-c option) and the generator will use the value of `CONFIG_WORD_SIZE` instead. The `Makefile` in `libsel4` calls the generator with the configuration file as an option. Ideally, the architecture should be determined from the configration file, but since we don't have unit tests for the generator, I will make one change at a time. This commit also includes a few changes to make it Python 2.7 compliant. --- libsel4/Makefile | 2 +- libsel4/tools/syscall_stub_gen.py | 347 ++++++++++++++++-------------- 2 files changed, 191 insertions(+), 158 deletions(-) diff --git a/libsel4/Makefile b/libsel4/Makefile index 529bdff04..c1324561b 100644 --- a/libsel4/Makefile +++ b/libsel4/Makefile @@ -113,4 +113,4 @@ include/interfaces/sel4_client.h: \ @${CHANGED_PATH} $@ \ python ${SOURCE_DIR}/tools/syscall_stub_gen.py \ --buffer \ - -a $(SEL4_ARCH) -o $@ $^ + -a $(SEL4_ARCH) -c ${srctree}/.config -o $@ $^ diff --git a/libsel4/tools/syscall_stub_gen.py b/libsel4/tools/syscall_stub_gen.py index 92816b1cb..c2784613a 100644 --- a/libsel4/tools/syscall_stub_gen.py +++ b/libsel4/tools/syscall_stub_gen.py @@ -35,12 +35,6 @@ # object's size wrong, which should help mitigate the number of bugs caused # because of this script becoming out of date compared to the source files. # -# * The word-size is fixed at 32 bits, and we may implicitly assume that -# sizeof(int) == sizeof(long) == 32. -# -# Though the constant 'WORD_SIZE_BITS' has been used throughout, there -# may be implicit assumptions hanging around causing things to fail. -# # * The script has only been tested on the actual seL4 API XML description. # # No stress testing has taken place; there may be bugs if new and wonderful @@ -48,12 +42,21 @@ # import xml.dom.minidom -import optparse +from argparse import ArgumentParser +import sys # Number of bits in a standard word WORD_SIZE_BITS_ARCH = { "aarch32": 32, "ia32": 32, + "aarch64": 64, + "ia64": 64, + "x86_64": 64 +} + +MESSAGE_REGISTERS_FOR_ARCH = { + "aarch32": 4, + "ia32": 2, } WORD_CONST_SUFFIX_BITS = { @@ -64,11 +67,6 @@ WORD_CONST_SUFFIX_BITS = { # Maximum number of words that will be in a message. MAX_MESSAGE_LENGTH = 32 -MESSAGE_REGISTERS_FOR_ARCH = { - "aarch32": 4, - "ia32": 2, -} - # Headers to include INCLUDES = [ 'autoconf.h', 'sel4/types.h' @@ -87,7 +85,7 @@ class Type(object): pointer. """ - def __init__(self, name, size_bits, double_word=False, native_size_bits=None): + def __init__(self, name, size_bits, wordsize, double_word=False, native_size_bits=None): """ Define a new type, named 'name' that is 'size_bits' bits long. @@ -95,6 +93,7 @@ class Type(object): self.name = name self.size_bits = size_bits + self.wordsize = wordsize self.double_word = double_word # @@ -110,7 +109,7 @@ class Type(object): self.native_size_bits = size_bits def pass_by_reference(self): - return self.size_bits > WORD_SIZE_BITS and not self.double_word + return self.size_bits > self.wordsize and not self.double_word def render_parameter_name(self, name): """ @@ -124,7 +123,7 @@ class Type(object): Return a new Type class representing a pointer to this object. """ - return PointerType(self) + return PointerType(self, self.wordsize) def c_expression(self, var_name, word_num=0): """ @@ -136,20 +135,21 @@ class Type(object): def double_word_expression(self, var_name, word_num): - assert(word_num == 0 or word_num == 1) - + assert word_num == 0 or word_num == 1 + if word_num == 0: - return "({0}) {1}".format(TYPES[WORD_SIZE_BITS], var_name) + return "({0}) {1}".format(TYPES[self.size_bits], var_name) elif word_num == 1: - return "({0}) ({1} >> {2})".format(TYPES[WORD_SIZE_BITS], var_name, WORD_SIZE_BITS) - + return "({0}) ({1} >> {2})".format(TYPES[self.size_bits], var_name, + self.size_bits) + class PointerType(Type): """ A pointer to a standard type. """ - def __init__(self, base_type): - Type.__init__(self, base_type.name, WORD_SIZE_BITS) + def __init__(self, base_type, wordsize): + Type.__init__(self, base_type.name, wordsize, wordsize) self.base_type = base_type def render_parameter_name(self, name): @@ -166,18 +166,18 @@ class CapType(Type): """ A type that is just a typedef of seL4_CPtr. """ - def __init__(self, name): - Type.__init__(self, name, WORD_SIZE_BITS) + def __init__(self, name, wordsize): + Type.__init__(self, name, wordsize, wordsize) class StructType(Type): """ A C 'struct' definition. """ - def __init__(self, name, size_bits): - Type.__init__(self, name, size_bits) + def __init__(self, name, size_bits, wordsize): + Type.__init__(self, name, size_bits, wordsize) def c_expression(self, var_name, word_num, member_name): - assert word_num < self.size_bits / WORD_SIZE_BITS + assert word_num < self.size_bits / self.wordsize # Multiword structure. assert self.pass_by_reference() @@ -187,80 +187,80 @@ class BitFieldType(Type): """ A special C 'struct' generated by the bitfield generator """ - def __init__(self, name, size_bits): - Type.__init__(self, name, size_bits) - + def __init__(self, name, size_bits, wordsize): + Type.__init__(self, name, size_bits, wordsize) + def c_expression(self, var_name, word_num=0): - + return "%s.words[%d]" % (var_name, word_num) - + class Parameter(object): def __init__(self, name, type): self.name = name self.type = type # -# Return the size (in bits) of a particular type. +# Types # -def InitTypes(): - global types - global arch_types +def init_data_types(wordsize): types = [ # Simple Types - Type("int", WORD_SIZE_BITS), + Type("int", wordsize, wordsize), - Type("seL4_Uint8", 8), - Type("seL4_Uint16", 16), - Type("seL4_Uint32", 32), - Type("seL4_Uint64", 64, double_word=(WORD_SIZE_BITS == 32)), - Type("seL4_Word", WORD_SIZE_BITS), - Type("seL4_Bool", 1, native_size_bits=8), - Type("seL4_CapRights", WORD_SIZE_BITS), + Type("seL4_Uint8", 8, wordsize), + Type("seL4_Uint16", 16, wordsize), + Type("seL4_Uint32", 32, wordsize), + Type("seL4_Uint64", 64, wordsize, double_word=(wordsize == 32)), + Type("seL4_Word", wordsize, wordsize), + Type("seL4_Bool", 1, wordsize, native_size_bits=8), + Type("seL4_CapRights", wordsize, wordsize), # seL4 Structures - BitFieldType("seL4_CapData_t", WORD_SIZE_BITS), + BitFieldType("seL4_CapData_t", wordsize, wordsize), # Object types - CapType("seL4_CPtr"), - CapType("seL4_CNode"), - CapType("seL4_IRQHandler"), - CapType("seL4_IRQControl"), - CapType("seL4_TCB"), - CapType("seL4_Untyped"), - CapType("seL4_DomainSet"), + CapType("seL4_CPtr", wordsize), + CapType("seL4_CNode", wordsize), + CapType("seL4_IRQHandler", wordsize), + CapType("seL4_IRQControl", wordsize), + CapType("seL4_TCB", wordsize), + CapType("seL4_Untyped", wordsize), + CapType("seL4_DomainSet", wordsize), ] - # - # Arch-specific types. - # + return types + +def init_arch_types(wordsize): arch_types = { "aarch32" : [ - Type("seL4_ARM_VMAttributes", WORD_SIZE_BITS), - CapType("seL4_ARM_Page"), - CapType("seL4_ARM_PageTable"), - CapType("seL4_ARM_PageDirectory"), - CapType("seL4_ARM_ASIDControl"), - CapType("seL4_ARM_ASIDPool"), - StructType("seL4_UserContext", WORD_SIZE_BITS * 17), + Type("seL4_ARM_VMAttributes", wordsize, wordsize), + CapType("seL4_ARM_Page", wordsize), + CapType("seL4_ARM_PageTable", wordsize), + CapType("seL4_ARM_PageDirectory", wordsize), + CapType("seL4_ARM_ASIDControl", wordsize), + CapType("seL4_ARM_ASIDPool", wordsize), + StructType("seL4_UserContext", wordsize * 17, wordsize), ], "ia32" : [ - Type("seL4_X86_VMAttributes", WORD_SIZE_BITS), - CapType("seL4_X86_IOPort"), - CapType("seL4_X86_ASIDControl"), - CapType("seL4_X86_ASIDPool"), - CapType("seL4_X86_IOSpace"), - CapType("seL4_X86_Page"), - CapType("seL4_X86_PageDirectory"), - CapType("seL4_X86_PageTable"), - CapType("seL4_X86_IOPageTable"), - StructType("seL4_UserContext", WORD_SIZE_BITS * 13), + Type("seL4_X86_VMAttributes", wordsize, wordsize), + CapType("seL4_X86_IOPort", wordsize), + CapType("seL4_X86_ASIDControl", wordsize), + CapType("seL4_X86_ASIDPool", wordsize), + CapType("seL4_X86_IOSpace", wordsize), + CapType("seL4_X86_Page", wordsize), + CapType("seL4_X86_PageDirectory", wordsize), + CapType("seL4_X86_PageTable", wordsize), + CapType("seL4_X86_IOPageTable", wordsize), + StructType("seL4_UserContext", wordsize * 13, wordsize), ] } + return arch_types + # Retrieve a member list for a given struct type -def struct_members(type, structs): - members = [member for struct_name, member in structs if struct_name == type.name] +def struct_members(typ, structs): + members = [member for struct_name, member in structs if struct_name == typ.name] assert len(members) == 1 return members[0] @@ -270,7 +270,7 @@ def align_up(x, a): return x return x + a - (x % a) -def get_parameter_positions(parameters): +def get_parameter_positions(parameters, wordsize): """ Determine where each parameter should be packed in the generated message. We generate a list of: @@ -281,7 +281,6 @@ def get_parameter_positions(parameters): We guarantee that either (num_words == 1) or (bit_offset == 0). """ - words_used = 0 bits_used = 0 results = [] @@ -290,10 +289,10 @@ def get_parameter_positions(parameters): type_size = param.type.size_bits # We need everything to be a power of two, or word sized. - assert ((type_size & (type_size - 1)) == 0) or (type_size % WORD_SIZE_BITS == 0) + assert ((type_size & (type_size - 1)) == 0) or (type_size % wordsize == 0) # Align up to our own size, or the next word. (Whichever is smaller) - bits_used = align_up(bits_used, min(type_size, WORD_SIZE_BITS)) + bits_used = align_up(bits_used, min(type_size, wordsize)) # Place ourself. results.append((param, bits_used, type_size)) @@ -316,7 +315,7 @@ def generate_param_list(input_params, output_params): return ", ".join(params) -def generate_marshal_expressions(params, num_mrs, structs): +def generate_marshal_expressions(params, num_mrs, structs, wordsize): """ Generate marshalling expressions for the given set of inputs. @@ -324,7 +323,7 @@ def generate_marshal_expressions(params, num_mrs, structs): to marshal all the inputs. """ - def generate_param_code(param, first_bit, num_bits, word_array): + def generate_param_code(param, first_bit, num_bits, word_array, wordsize): """ Generate code to marshal the given parameter into the correct location in the message. @@ -335,8 +334,8 @@ def generate_marshal_expressions(params, num_mrs, structs): be bitwise-or'ed into it. """ - target_word = first_bit / WORD_SIZE_BITS - target_offset = first_bit % WORD_SIZE_BITS + target_word = first_bit / wordsize + target_offset = first_bit % wordsize # double word type if param.type.double_word: @@ -345,16 +344,17 @@ def generate_marshal_expressions(params, num_mrs, structs): return # Single full word? - if num_bits == WORD_SIZE_BITS: + if num_bits == wordsize: assert target_offset == 0 - expr = param.type.c_expression(param.name); + expr = param.type.c_expression(param.name) word_array[target_word].append(expr) return # Part of a word? - if num_bits < WORD_SIZE_BITS: - expr = param.type.c_expression(param.name); - expr = "(%s & %#x%s)" % (expr, (1 << num_bits) - 1, WORD_CONST_SUFFIX) + if num_bits < wordsize: + expr = param.type.c_expression(param.name) + expr = "(%s & %#x%s)" % (expr, (1 << num_bits) - 1, + WORD_CONST_SUFFIX_BITS[wordsize]) if target_offset: expr = "(%s << %d)" % (expr, target_offset) word_array[target_word].append(expr) @@ -362,24 +362,24 @@ def generate_marshal_expressions(params, num_mrs, structs): # Multiword array assert target_offset == 0 - num_words = num_bits / WORD_SIZE_BITS + num_words = num_bits / wordsize for i in range(num_words): - expr = param.type.c_expression(param.name, i, struct_members(param.type, structs)); + expr = param.type.c_expression(param.name, i, struct_members(param.type, structs)) word_array[target_word + i].append(expr) # Get their marshalling positions - positions = get_parameter_positions(params) + positions = get_parameter_positions(params, wordsize) # Generate marshal code. words = [[] for _ in range(num_mrs, MAX_MESSAGE_LENGTH)] for (param, first_bit, num_bits) in positions: - generate_param_code(param, first_bit, num_bits, words) + generate_param_code(param, first_bit, num_bits, words, wordsize) # Return list of expressions. return [" | ".join(x) for x in words if len(x) > 0] -def generate_unmarshal_expressions(params): +def generate_unmarshal_expressions(params, wordsize): """ Generate unmarshalling expressions for the given set of outputs. @@ -390,37 +390,37 @@ def generate_unmarshal_expressions(params): in them, indicating a read from a word in the message. """ - def unmarshal_single_param(first_bit, num_bits): + def unmarshal_single_param(first_bit, num_bits, wordsize): """ Unmarshal a single parameter. """ - first_word = first_bit / WORD_SIZE_BITS - bit_offset = first_bit % WORD_SIZE_BITS + first_word = first_bit / wordsize + bit_offset = first_bit % wordsize # Multiword type? - if num_bits > WORD_SIZE_BITS: + if num_bits > wordsize: result = [] - for x in range(num_bits / WORD_SIZE_BITS): + for x in range(num_bits / wordsize): result.append("%%(w%d)s" % (x + first_word)) return result # Otherwise, bit packed. - if num_bits == WORD_SIZE_BITS: + if num_bits == wordsize: return ["%%(w%d)s" % first_word] elif bit_offset == 0: return ["(%%(w%d)s & %#x)" % ( - first_word, (1 << num_bits) - 1)] + first_word, (1 << num_bits) - 1)] else: return ["(%%(w%d)s >> %d) & %#x" % ( - first_word, bit_offset, (1 << num_bits) - 1)] + first_word, bit_offset, (1 << num_bits) - 1)] # Get their marshalling positions - positions = get_parameter_positions(params) + positions = get_parameter_positions(params, wordsize) # Generate the unmarshal code. results = [] for (param, first_bit, num_bits) in positions: - results.append((param, unmarshal_single_param(first_bit, num_bits))) + results.append((param, unmarshal_single_param(first_bit, num_bits, wordsize))) return results def generate_result_struct(interface_name, method_name, output_params): @@ -461,12 +461,12 @@ def generate_result_struct(interface_name, method_name, output_params): result.append("\t%s;" % i.type.render_parameter_name(i.name)) result.append("};") result.append("typedef struct %s_%s %s_%s_t;" % ( - (interface_name, method_name, interface_name, method_name))) + (interface_name, method_name, interface_name, method_name))) result.append("") return "\n".join(result) -def generate_stub(arch, interface_name, method_name, method_id, input_params, output_params, structs, use_only_ipc_buffer): +def generate_stub(arch, wordsize, interface_name, method_name, method_id, input_params, output_params, structs, use_only_ipc_buffer): result = [] if use_only_ipc_buffer: @@ -501,13 +501,14 @@ def generate_stub(arch, interface_name, method_name, method_id, input_params, ou # result.append("LIBSEL4_INLINE %s" % return_type) result.append("%s_%s(%s)" % (interface_name, method_name, - generate_param_list(input_params, output_params))) + generate_param_list(input_params, output_params))) result.append("{") # # Get a list of expressions for our caps and inputs. # - input_expressions = generate_marshal_expressions(standard_params, num_mrs, structs) + input_expressions = generate_marshal_expressions(standard_params, num_mrs, + structs, wordsize) cap_expressions = [x.name for x in cap_params] service_cap = cap_expressions[0] cap_expressions = cap_expressions[1:] @@ -516,7 +517,7 @@ def generate_stub(arch, interface_name, method_name, method_id, input_params, ou # Compute how many words the inputs and output will require. # input_param_words = len(input_expressions) - output_param_words = sum([p.type.size_bits for p in output_params]) / WORD_SIZE_BITS + output_param_words = sum([p.type.size_bits for p in output_params]) / wordsize # # Setup variables we will need. @@ -573,7 +574,7 @@ def generate_stub(arch, interface_name, method_name, method_id, input_params, ou result.append("\t/* Perform the call, passing in-register arguments directly. */") result.append("\toutput_tag = seL4_CallWithMRs(%s, tag," % (service_cap)) result.append("\t\t%s);" % ', '.join( - [call_arguments[i] for i in range(num_mrs)])) + [call_arguments[i] for i in range(num_mrs)])) result.append("") # @@ -584,18 +585,21 @@ def generate_stub(arch, interface_name, method_name, method_id, input_params, ou source_words = {} for i in range(MAX_MESSAGE_LENGTH): if i < num_mrs: - source_words["w%d" % i] = "mr%d" % i; + source_words["w%d" % i] = "mr%d" % i else: - source_words["w%d" % i] = "seL4_GetMR(%d)" % i; - unmashalled_params = generate_unmarshal_expressions(output_params) + source_words["w%d" % i] = "seL4_GetMR(%d)" % i + unmashalled_params = generate_unmarshal_expressions(output_params, wordsize) for (param, words) in unmashalled_params: if param.type.pass_by_reference(): - members = struct_members(param.type, structs); + members = struct_members(param.type, structs) for i in range(len(words)): - result.append("\t%s->%s = %s;" % (param.name, members[i], words[i] % source_words)) + result.append("\t%s->%s = %s;" % + (param.name, members[i], words[i] % source_words)) else: if param.type.double_word: - result.append("\tresult.%s = ((%s)%s + ((%s)%s << 32));" % (param.name, TYPES[64], words[0] % source_words, TYPES[64], words[1] % source_words)) + result.append("\tresult.%s = ((%s)%s + ((%s)%s << 32));" % + (param.name, TYPES[64], words[0] % source_words, + TYPES[64], words[1] % source_words)) else: for word in words: result.append("\tresult.%s = %s;" % (param.name, word % source_words)) @@ -632,12 +636,12 @@ def parse_xml_file(input_file, valid_types): doc = xml.dom.minidom.parse(input_file) for struct in doc.getElementsByTagName("struct"): - struct_members = [] + _struct_members = [] struct_name = struct.getAttribute("name") for members in struct.getElementsByTagName("member"): member_name = members.getAttribute("name") - struct_members.append(member_name) - structs.append( (struct_name, struct_members) ) + _struct_members.append(member_name) + structs.append((struct_name, _struct_members)) for interface in doc.getElementsByTagName("interface"): interface_name = interface.getAttribute("name") @@ -659,7 +663,7 @@ def parse_xml_file(input_file, valid_types): raise Exception("Unknown type '%s'." % (param.getAttribute("type"))) param_dir = param.getAttribute("dir") assert (param_dir == "in") or (param_dir == "out") - if (param_dir == "in"): + if param_dir == "in": input_params.append(Parameter(param_name, param_type)) else: output_params.append(Parameter(param_name, param_type)) @@ -667,28 +671,24 @@ def parse_xml_file(input_file, valid_types): return (methods, structs) -def generate_stub_file(arch, input_files, output_file, use_only_ipc_buffer): +def generate_stub_file(arch, wordsize, input_files, output_file, use_only_ipc_buffer): """ Generate a header file containing system call stubs for seL4. """ result = [] # Ensure architecture looks sane. - if not arch in WORD_SIZE_BITS_ARCH.keys(): - raise Exception("Invalid architecture. Expected %s.", - " or ".join(arch_types.keys())) + if arch not in WORD_SIZE_BITS_ARCH.keys(): + raise Exception("Invalid architecture.") - global WORD_SIZE_BITS - global WORD_CONST_SUFFIX - WORD_SIZE_BITS = WORD_SIZE_BITS_ARCH[arch] - WORD_CONST_SUFFIX = WORD_CONST_SUFFIX_BITS[WORD_SIZE_BITS] - InitTypes() + data_types = init_data_types(wordsize) + arch_types = init_arch_types(wordsize) # Parse XML methods = [] structs = [] - for file in input_files: - method, struct = parse_xml_file(file, types + arch_types[arch]) + for infile in input_files: + method, struct = parse_xml_file(infile, data_types + arch_types[arch]) methods += method structs += struct @@ -700,10 +700,10 @@ def generate_stub_file(arch, input_files, output_file, use_only_ipc_buffer): #ifndef __LIBSEL4_SEL4_CLIENT_H #define __LIBSEL4_SEL4_CLIENT_H -"""); +""") # Emit the includes - result.append('\n'.join(map(lambda x: '#include <%s>' % x, INCLUDES))) + result.append('\n'.join(['#include <%s>' % include for include in INCLUDES])) # # Emit code to ensure that all of our type sizes are consistent with @@ -721,7 +721,7 @@ def generate_stub_file(arch, input_files, output_file, use_only_ipc_buffer): typedef unsigned long __type_##type##_size_incorrect[ \\ (sizeof(type) == expected_bytes) ? 1 : -1] """) - for x in types + arch_types[arch]: + for x in data_types + arch_types[arch]: result.append("assert_size_correct(%s, %d);" % (x.name, x.native_size_bits / 8)) result.append("") @@ -746,8 +746,8 @@ def generate_stub_file(arch, input_files, output_file, use_only_ipc_buffer): result.append(" * Generated stubs.") result.append(" */") for (interface_name, method_name, method_id, inputs, outputs) in methods: - result.append(generate_stub(arch, interface_name, method_name, - method_id, inputs, outputs, structs, use_only_ipc_buffer)) + result.append(generate_stub(arch, wordsize, interface_name, method_name, + method_id, inputs, outputs, structs, use_only_ipc_buffer)) # Print footer. result.append("#endif /* __LIBSEL4_SEL4_CLIENT_H */") @@ -758,32 +758,65 @@ def generate_stub_file(arch, input_files, output_file, use_only_ipc_buffer): output.write("\n".join(result)) output.close() +def process_args(): + usage_str = """ + %(prog)s [OPTIONS] [FILES] """ + epilog_str = """ + + """ + parser = ArgumentParser(description='seL4 System Call Stub Generator.', + usage=usage_str, + epilog=epilog_str) + parser.add_argument("-o", "--output", dest="output", default="/dev/stdout", + help="Output file to write stub to. (default: %(default)s).") + parser.add_argument("-b", "--buffer", dest="buffer", action="store_true", default=False, + help="Use IPC buffer exclusively, i.e. do not pass syscall arguments by registers. (default: %(default)s)") + parser.add_argument("-a", "--arch", dest="arch", required=True, choices=WORD_SIZE_BITS_ARCH, + help="Architecture to generate stubs for.") + + wsizegroup = parser.add_mutually_exclusive_group() + wsizegroup.add_argument("-w", "--word-size", dest="wsize", + help="Word size(in bits), for the platform.") + wsizegroup.add_argument("-c", "--cfile", dest="cfile", + help="Config file for Kbuild, used to get Word size.") + + parser.add_argument("files", metavar="FILES", nargs="+", + help="Input XML files.") + + return parser + def main(): - # - # Read command line arguments. - # - parser = optparse.OptionParser() - parser.add_option("-a", "--arch", - dest="arch", help="Architecture to generate stubs for.") - parser.add_option("-o", "--output", - dest="output", help="Output file to write stub to.") - parser.add_option("-b", "--buffer", action="store_true", - help="Use IPC buffer exclusively (i.e. do not pass syscall " - "arguments by registers).") - (options, args) = parser.parse_args() - - # Validate arguments - if len(args) < 1: - parser.error("Require at least one input file.") - if not options.arch: - parser.error("Require an architecture to be specified.") - if not options.output: - options.output = "/dev/stdout" - input_files = args + + parser = process_args() + args = parser.parse_args() + + if not (args.wsize or args.cfile): + parser.error("Require either -w/--word-size or -c/--cfile argument.") + sys.exit(2) + + # Get word size + wordsize = -1 + + if args.cfile: + try: + with open(args.cfile) as conffile: + for line in conffile: + if line.startswith('CONFIG_WORD_SIZE'): + wordsize = int(line.split('=')[1].strip()) + except IndexError: + print "Invalid word size in configuration file." + sys.exit(2) + else: + wordsize = args.wsize + + if wordsize is -1: + print "Invalid word size." + sys.exit(2) # Generate the stubs. + generate_stub_file(args.arch, wordsize, args.files, args.output, args.buffer) - generate_stub_file(options.arch, input_files, options.output, options.buffer) -main() +if __name__ == "__main__": + sys.exit(main()) -- GitLab