Example #1
0
    def __init__(self, elt, member, parent):
        Type.__init__(self, member.name)
        self.is_list = True
        self.member = member
        self.parent = parent

        if elt.tag == 'list':
            elts = list(elt)
            self.expr = Expression(elts[0] if len(elts) else elt, self)
        elif elt.tag == 'valueparam':
            self.expr = Expression(elt, self)

        self.size = member.size if member.fixed_size() else None
        self.nmemb = self.expr.nmemb if self.expr.fixed_size() else None
Example #2
0
class ExpressionMapping(str):
    """Class for parsing and expanding an expression."""
    def __init__(self, value):
        """Parse the expression as a string."""
        self.expression = Expression(value[1:-1])
        super(ExpressionMapping, self).__init__(value)

    def values(self, variables):
        """Expand the expression using the variables specified."""
        return [self.expression.value(variables)]

    def attributes(self):
        """Return the attributes defined in the expression."""
        return self.expression.variables()
Example #3
0
    def __init__(self, elt, member, parent):
        Type.__init__(self, member.name)
        self.is_list = True
        self.member = member
        self.parent = parent

        if elt.tag == 'list':
            elts = list(elt)
            self.expr = Expression(elts[0] if len(elts) else elt, self)
        elif elt.tag == 'valueparam':
            self.expr = Expression(elt, self)

        self.size = member.size if member.fixed_size() else None
        self.nmemb = self.expr.nmemb if self.expr.fixed_size() else None
Example #4
0
class ExpressionMapping(str):
    """Class for parsing and expanding an expression."""

    def __init__(self, value):
        """Parse the expression as a string."""
        self.expression = Expression(value[1:-1])
        super(ExpressionMapping, self).__init__(value)

    def values(self, variables):
        """Expand the expression using the variables specified."""
        return [self.expression.value(variables)]

    def attributes(self):
        """Return the attributes defined in the expression."""
        return self.expression.variables()
Example #5
0
 def create_expressions_dcr_graph(self):
     """
     Creates all expressions within a dcr graph
     :return:
     """
     for expression in self.dcr_xml_root.iter('expression'):
         expression_id = expression.get('id')
         expression_str = expression.get('value')
         expression_tmp = Expression(expression_str, expression_id)
         self.Expressions.append(expression_tmp)
Example #6
0
    def __init__(self, elt, member, parent):
        Type.__init__(self, member.name)
        self.is_expr = True
        self.member = member
        self.parent = parent

        self.expr = Expression(list(elt)[0], self)

        self.size = member.size
        self.nmemb = 1
Example #7
0
class ExpressionMapping(object):
    """Class for parsing and expanding an expression."""
    def __init__(self, value):
        """Parse the expression as a string."""
        self.value = value
        self.expression = Expression(value[1:-1])

    def __str__(self):
        return self.value

    def __repr__(self):
        return repr(str(self))

    def values(self, variables):
        """Expand the expression using the variables specified."""
        return [self.expression.value(variables)]

    def attributes(self):
        """Return the attributes defined in the expression."""
        return self.expression.variables()
Example #8
0
    def rule_id(self, stack):
        it = iter(reversed(stack))

        try:
            identifier = Parser.check_token(next(it), TokenType.IDENTIFIER)
            Parser.check_token(next(it), ExprPrecedence.SHIFT)
        except TokenMismatchError:
            return False

        new_expr = Expression(FAGenerator.load_c(identifier.data))
        Parser.reduce(stack, new_expr)

        return True
Example #9
0
    def rule_quan_0_N(self, stack):
        it = iter(reversed(stack))

        try:
            Parser.check_token(next(it), TokenType.META_QUANTIFIER_0_N)
            expr = Parser.check_token(next(it), Expression)
            Parser.check_token(next(it), ExprPrecedence.SHIFT)
        except TokenMismatchError:
            return False

        new_expr = Expression(FAGenerator.iterate(expr.automat))
        Parser.reduce(stack, new_expr)

        return True
Example #10
0
    def rule_brackets(self, stack):
        it = iter(reversed(stack))

        try:
            Parser.check_token(next(it), TokenType.RIGHT_BRACKET)
            expr = Parser.check_token(next(it), Expression)
            Parser.check_token(next(it), TokenType.LEFT_BRACKET)
            Parser.check_token(next(it), ExprPrecedence.SHIFT)
        except TokenMismatchError:
            return False

        new_expr = Expression(expr.automat)
        Parser.reduce(stack, new_expr)

        return True
Example #11
0
    def rule_or(self, stack):
        it = iter(reversed(stack))

        try:
            expr_1 = Parser.check_token(next(it), Expression)
            Parser.check_token(next(it), TokenType.META_OR)
            expr_2 = Parser.check_token(next(it), Expression)
            Parser.check_token(next(it), ExprPrecedence.SHIFT)
        except TokenMismatchError:
            return False

        new_expr = Expression(FAGenerator.union(expr_2.automat,
                                                expr_1.automat))
        Parser.reduce(stack, new_expr)

        return True
Example #12
0
 def __init__(self, value):
     """Parse the expression as a string."""
     self.expression = Expression(value[1:-1])
     super(ExpressionMapping, self).__init__(value)
Example #13
0
def read(filename):  # noqa: C901 (many simple branches)
    maps = _get_maps()
    lineno = 0
    for line in open(filename, 'r'):
        lineno += 1
        line = line.strip()
        # skip comments and blank lines
        if re.match(r'(#.*)?$', line, re.IGNORECASE):
            continue
        # parse options with a single integer argument
        m = re.match(
            r'(?P<keyword>threads|ldap_version|bind_timelimit|timelimit|'
            r'idle_timelimit|reconnect_sleeptime|reconnect_retrytime|pagesize|'
            r'nss_min_uid|nss_uid_offset|nss_gid_offset)\s+(?P<value>\d+)',
            line, re.IGNORECASE)
        if m:
            globals()[m.group('keyword').lower()] = int(m.group('value'))
            continue
        # parse options with a single boolean argument
        m = re.match(
            r'(?P<keyword>referrals|nss_nested_groups|nss_getgrent_skipmembers|'
            r'nss_disable_enumeration)\s+(?P<value>%s)' %
            ('|'.join(_boolean_options.keys())), line, re.IGNORECASE)
        if m:
            globals()[m.group('keyword').lower()] = _boolean_options[m.group(
                'value').lower()]
            continue
        # parse options with a single no-space value
        m = re.match(
            r'(?P<keyword>uid|gid|bindpw|rootpwmodpw|sasl_mech)\s+(?P<value>\S+)',
            line, re.IGNORECASE)
        if m:
            globals()[m.group('keyword').lower()] = m.group('value')
            continue
        # parse options with a single value that can contain spaces
        m = re.match(
            r'(?P<keyword>binddn|rootpwmoddn|sasl_realm|sasl_authcid|'
            r'sasl_authzid|sasl_secprops|krb5_ccname|tls_cacertdir|'
            r'tls_cacertfile|tls_randfile|tls_ciphers|tls_cert|tls_key|'
            r'pam_password_prohibit_message)\s+(?P<value>\S.*)', line,
            re.IGNORECASE)
        if m:
            globals()[m.group('keyword').lower()] = m.group('value')
            continue
        # log <SCHEME> [<LEVEL>]
        m = re.match(
            r'log\s+(?P<scheme>syslog|/\S*)(\s+(?P<level>%s))?' %
            ('|'.join(_log_levels.keys())), line, re.IGNORECASE)
        if m:
            logs.append((m.group('scheme'),
                         _log_levels[str(m.group('level')).lower()]))
            continue
        # uri <URI>
        m = re.match(r'uri\s+(?P<uri>\S+)', line, re.IGNORECASE)
        if m:
            # FIXME: support multiple URI values
            # FIXME: support special DNS and DNS:domain values
            global uri
            uri = m.group('uri')
            continue
        # base <MAP>? <BASEDN>
        m = re.match(
            r'base\s+((?P<map>%s)\s+)?(?P<value>\S.*)' %
            ('|'.join(maps.keys())), line, re.IGNORECASE)
        if m:
            mod = maps[str(m.group('map')).lower()]
            if not hasattr(mod, 'bases'):
                mod.bases = []
            mod.bases.append(m.group('value'))
            continue
        # filter <MAP> <SEARCHFILTER>
        m = re.match(
            r'filter\s+(?P<map>%s)\s+(?P<value>\S.*)' %
            ('|'.join(maps.keys())), line, re.IGNORECASE)
        if m:
            mod = maps[m.group('map').lower()]
            mod.filter = m.group('value')
            continue
        # scope <MAP>? <SCOPE>
        m = re.match(
            r'scope\s+((?P<map>%s)\s+)?(?P<value>%s)' %
            ('|'.join(maps.keys()), '|'.join(_scope_options.keys())), line,
            re.IGNORECASE)
        if m:
            mod = maps[str(m.group('map')).lower()]
            mod.scope = _scope_options[m.group('value').lower()]
            continue
        # map <MAP> <ATTRIBUTE> <ATTMAPPING>
        m = re.match(
            r'map\s+(?P<map>%s)\s+(?P<attribute>\S+)\s+(?P<value>\S.*)' %
            ('|'.join(maps.keys())), line, re.IGNORECASE)
        if m:
            mod = maps[m.group('map').lower()]
            attribute = m.group('attribute')
            if attribute not in mod.attmap:
                raise ParseError(filename, lineno,
                                 'attribute %s unknown' % attribute)
            mod.attmap[attribute] = m.group('value')
            # TODO: filter out attributes that cannot be an expression
            continue
        # deref <DEREF>
        m = re.match(
            r'deref\s+(?P<value>%s)' % '|'.join(_deref_options.keys()), line,
            re.IGNORECASE)
        if m:
            global deref
            deref = _deref_options[m.group('value').lower()]
            continue
        # nss_initgroups_ignoreusers <USER,USER>|<ALLLOCAL>
        m = re.match(r'nss_initgroups_ignoreusers\s+(?P<value>\S.*)', line,
                     re.IGNORECASE)
        if m:
            users = m.group('value')
            if users.lower() == 'alllocal':
                # get all users known to the system currently (since nslcd
                # isn't yet running, this should work)
                import pwd
                users = (x.pw_name for x in pwd.getpwall())
            else:
                users = users.split(',')
                # TODO: warn about unknown users
            nss_initgroups_ignoreusers.update(users)
            continue
        # pam_authz_search <FILTER>
        m = re.match(r'pam_authz_search\s+(?P<value>\S.*)', line,
                     re.IGNORECASE)
        if m:
            from expr import Expression
            pam_authz_searches.append(Expression(m.group('value')))
            # TODO: check pam_authz_search expression to only contain
            # username, service, ruser, rhost, tty, hostname, fqdn, dn or
            # uid variables
            continue
        # ssl <on|off|start_tls>
        m = re.match(r'ssl\s+(?P<value>%s)' % '|'.join(_ssl_options.keys()),
                     line, re.IGNORECASE)
        if m:
            global ssl
            ssl = _ssl_options[m.group('value').lower()]
            continue
        # sasl_canonicalize yes|no
        m = re.match(
            r'(ldap_?)?sasl_(?P<no>no)?canon(icali[sz]e)?\s+(?P<value>%s)' %
            ('|'.join(_boolean_options.keys())), line, re.IGNORECASE)
        if m:
            global sasl_canonicalize
            sasl_canonicalize = _boolean_options[m.group('value').lower()]
            if m.group('no'):
                sasl_canonicalize = not sasl_canonicalize
            continue
        # tls_reqcert <demand|hard|yes...>
        m = re.match(
            r'tls_reqcert\s+(?P<value>%s)' %
            ('|'.join(_tls_reqcert_options.keys())), line, re.IGNORECASE)
        if m:
            global tls_reqcert
            tls_reqcert = _tls_reqcert_options[m.group('value').lower()]
            continue
        # validnames /REGEX/i?
        m = re.match(r'validnames\s+/(?P<value>.*)/(?P<flags>[i]?)$', line,
                     re.IGNORECASE)
        if m:
            global validnames
            flags = 0 | re.IGNORECASE if m.group('flags') == 'i' else 0
            validnames = re.compile(m.group('value'), flags=flags)
            continue
        # reconnect_invalidate <MAP>,<MAP>,...
        m = re.match(r'reconnect_invalidate\s+(?P<value>\S.*)', line,
                     re.IGNORECASE)
        if m:
            dbs = re.split('[ ,]+', m.group('value').lower())
            for db in dbs:
                if db not in list(maps.keys()) + ['nfsidmap']:
                    raise ParseError(filename, lineno, 'map %s unknown' % db)
            reconnect_invalidate.update(dbs)
            continue
        # unrecognised line
        raise ParseError(filename, lineno, 'error parsing line %r' % line)
    # if logging is not configured, default to syslog
    if not logs:
        logs.append(('syslog', logging.INFO))
    # dump config (debugging code)
    for k, v in globals().items():
        if not k.startswith('_'):
            logging.debug('%s=%r', k, v)
Example #14
0
 def __init__(self, value):
     """Parse the expression as a string."""
     self.expression = Expression(value[1:-1])
     super(ExpressionMapping, self).__init__(value)
Example #15
0
 def __init__(self, value):
     """Parse the expression as a string."""
     self.value = value
     self.expression = Expression(value[1:-1])
Example #16
0
class ListType(Type):
    '''
    Derived class which represents a list of some other datatype.  Fixed- or variable-sized.

    Public fields added:
    member is the datatype of the list elements.
    parent is the structure type containing the list.
    expr is an Expression object containing the length information, for variable-sized lists.
    '''
    def __init__(self, elt, member, parent):
        Type.__init__(self, member.name)
        self.is_list = True
        self.member = member
        self.parent = parent

        if elt.tag == 'list':
            elts = list(elt)
            self.expr = Expression(elts[0] if len(elts) else elt, self)
        elif elt.tag == 'valueparam':
            self.expr = Expression(elt, self)

        self.size = member.size if member.fixed_size() else None
        self.nmemb = self.expr.nmemb if self.expr.fixed_size() else None

    def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto):
        if not self.fixed_size():
            # We need a length field.
            # Ask our Expression object for it's name, type, and whether it's on the wire.
            lenfid = self.expr.lenfield_type
            lenfield_name = self.expr.lenfield_name
            lenwire = self.expr.lenwire
            needlen = True

            # See if the length field is already in the structure.
            for field in self.parent.fields:
                if field.field_name == lenfield_name:
                    needlen = False

            # It isn't, so we need to add it to the structure ourself.
            if needlen:
                type = module.get_type(lenfid)
                lenfield_type = module.get_type_name(lenfid)
                type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False)

        # Add ourself to the structure by calling our original method.
        Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto)

    def resolve(self, module):
        if self.resolved:
            return
        self.member.resolve(module)

        # Find my length field again.  We need the actual Field object in the expr.
        # This is needed because we might have added it ourself above.
        if not self.fixed_size():
            for field in self.parent.fields:
                if field.field_name == self.expr.lenfield_name and field.wire:
                    self.expr.lenfield = field
                    break
            
        self.resolved = True

    def fixed_size(self):
        return self.member.fixed_size() and self.expr.fixed_size()
Example #17
0
class TestConnectionsMethods(unittest.TestCase):
    def setUp(self):
        self.expression = Expression()

    def test_convert_right_side_float(self):
        """
        Tests if the right side can be correctly evaluated
        :return:
        """
        expression_str = 'costs!=4.3'
        self.expression.split_singular_expression(expression_str)
        self.expression.try_convert_expression_right()
        self.assertTrue(type(self.expression.expression_right) is float)
        self.assertEqual(self.expression.expression_right, 4.3)
        self.assertEqual(self.expression.expression_left, 'costs')
        self.assertEqual(self.expression.expression_middle, '!=')

    def test_convert_right_side_bool(self):
        """
        Tests if the right side can be correctly evaluated
        :return:
        """
        expression_str = 'Walter=True'
        self.expression.split_singular_expression(expression_str)
        self.expression.try_convert_expression_right()
        self.assertTrue(type(self.expression.expression_right) is bool)
        self.assertEqual(self.expression.expression_right, True)
        self.assertEqual(self.expression.expression_left, 'Walter')
        self.assertEqual(self.expression.expression_middle, '=')

    def test_convert_right_side_int(self):
        """
        Tests if the right side can be correctly evaluated
        :return:
        """
        expression_str = 'Int=12'
        self.expression.split_singular_expression(expression_str)
        self.expression.try_convert_expression_right()
        self.assertTrue(type(self.expression.expression_right) is int)
        self.assertEqual(self.expression.expression_right, 12)
        self.assertEqual(self.expression.expression_left, 'Int')
        self.assertEqual(self.expression.expression_middle, '=')

    def test_convert_right_side_str(self):
        """
        Tests if the right side can be correctly evaluated
        :return:
        """
        expression_str = 'Driver=Driver'
        self.expression.split_singular_expression(expression_str)
        self.expression.try_convert_expression_right()
        self.assertTrue(type(self.expression.expression_right) is str)
        self.assertEqual(self.expression.expression_right, 'Driver')
        self.assertEqual(self.expression.expression_left, 'Driver')
        self.assertEqual(self.expression.expression_middle, '=')

    def test_split_expression_greater_simple(self):
        """
        Uses the expression costs>3
        :return:
        """
        expression_str = 'costs>3'
        self.expression.split_singular_expression(expression_str)
        self.assertEqual(self.expression.expression_left, 'costs')
        self.assertEqual(self.expression.expression_middle, '>')
        self.assertEqual(self.expression.expression_right, '3')

    def test_split_expression_smaller_simple(self):
        """
        Uses the expression "loss<55"
        :return:
        """
        expression_str = 'loss<55'
        self.expression.split_singular_expression(expression_str)
        self.assertEqual(self.expression.expression_left, 'loss')
        self.assertEqual(self.expression.expression_middle, '<')
        self.assertEqual(self.expression.expression_right, '55')

    def test_split_expression_equals_simple(self):
        """

        :return:
        """
        expression_str = 'state=Cool'
        self.expression.split_singular_expression(expression_str)
        self.assertEqual(self.expression.expression_left, 'state')
        self.assertEqual(self.expression.expression_middle, '=')
        self.assertEqual(self.expression.expression_right, 'Cool')

    def test_split_expression_smaller_equal_simple(self):
        """
        Uses the expression "loss<55"
        :return:
        """
        expression_str = 'costs<=55'
        self.expression.split_singular_expression(expression_str)
        self.assertEqual(self.expression.expression_left, 'costs')
        self.assertEqual(self.expression.expression_middle, '<=')
        self.assertEqual(self.expression.expression_right, '55')

    def test_split_expression_whitespace(self):
        """

        :return:
        """
        expression_str = ' costs <= 55 '
        self.expression.split_singular_expression(expression_str)
        self.assertEqual(self.expression.expression_left, 'costs')
        self.assertEqual(self.expression.expression_middle, '<=')
        self.assertEqual(self.expression.expression_right, '55')

    def test_split_isNot_whitespaceInComparison(self):
        """

        :return:
        """
        expression_str = ' costs = ! 55 '
        self.expression.split_singular_expression(expression_str)
        self.assertEqual(self.expression.expression_left, 'costs')
        self.assertEqual(self.expression.expression_middle, '=!')
        self.assertEqual(self.expression.expression_right, '55')

    def test_convert_comparator_gte0(self):
        """

        :return:
        """
        expression_str = 'costs>=xxx'
        self.expression.split_singular_expression(expression_str)
        self.expression.convert_comparator()
        self.assertEqual(self.expression.expression_middle, '>=')
        self.assertEqual(self.expression.expression_comparator,
                         Comparators.gte)

    def test_convert_comparator_gte1(self):
        """

        :return:
        """
        expression_str = 'costs=>xxx'
        self.expression.split_singular_expression(expression_str)
        self.expression.convert_comparator()
        self.assertEqual(self.expression.expression_middle, '=>')
        self.assertEqual(self.expression.expression_comparator,
                         Comparators.gte)

    def test_convert_comparator_lte0(self):
        """

        :return:
        """
        expression_str = 'costs=<xxx'
        self.expression.split_singular_expression(expression_str)
        self.expression.convert_comparator()
        self.assertEqual(self.expression.expression_middle, '=<')
        self.assertEqual(self.expression.expression_comparator,
                         Comparators.lte)

    def test_convert_comparator_lte1(self):
        """

        :return:
        """
        expression_str = 'costs<=xxx'
        self.expression.split_singular_expression(expression_str)
        self.expression.convert_comparator()
        self.assertEqual(self.expression.expression_middle, '<=')
        self.assertEqual(self.expression.expression_comparator,
                         Comparators.lte)

    def test_convert_comparator_lt(self):
        """

        :return:
        """
        expression_str = 'costs<xxx'
        self.expression.split_singular_expression(expression_str)
        self.expression.convert_comparator()
        self.assertEqual(self.expression.expression_middle, '<')
        self.assertEqual(self.expression.expression_comparator, Comparators.lt)

    def test_convert_comparator_gt(self):
        """

        :return:
        """
        expression_str = 'costs>xxx'
        self.expression.split_singular_expression(expression_str)
        self.expression.convert_comparator()
        self.assertEqual(self.expression.expression_middle, '>')
        self.assertEqual(self.expression.expression_comparator, Comparators.gt)

    def test_convert_comparator_eq0(self):
        """

        :return:
        """
        expression_str = 'costs=xxx'
        self.expression.split_singular_expression(expression_str)
        self.expression.convert_comparator()
        self.assertEqual(self.expression.expression_middle, '=')
        self.assertEqual(self.expression.expression_comparator, Comparators.eq)

    def test_convert_comparator_eq1(self):
        """

        :return:
        """
        expression_str = 'costs==xxx'
        self.expression.split_singular_expression(expression_str)
        self.expression.convert_comparator()
        self.assertEqual(self.expression.expression_middle, '==')
        self.assertEqual(self.expression.expression_comparator, Comparators.eq)

    def test_convert_comparator_neq0(self):
        """

        :return:
        """
        expression_str = 'costs!xxx'
        self.expression.split_singular_expression(expression_str)
        self.expression.convert_comparator()
        self.assertEqual(self.expression.expression_middle, '!')
        self.assertEqual(self.expression.expression_comparator,
                         Comparators.neq)

    def test_convert_comparator_neq1(self):
        """

        :return:
        """
        expression_str = 'costs!!xxx'
        self.expression.split_singular_expression(expression_str)
        self.expression.convert_comparator()
        self.assertEqual(self.expression.expression_middle, '!!')
        self.assertEqual(self.expression.expression_comparator,
                         Comparators.neq)

    def test_convert_comparator_neq2(self):
        """

        :return:
        """
        expression_str = 'costs!=xxx'
        self.expression.split_singular_expression(expression_str)
        self.expression.convert_comparator()
        self.assertEqual(self.expression.expression_middle, '!=')
        self.assertEqual(self.expression.expression_comparator,
                         Comparators.neq)

    def test_convert_comparator_neq3(self):
        """

        :return:
        """
        expression_str = 'costs=!xxx'
        self.expression.split_singular_expression(expression_str)
        self.expression.convert_comparator()
        self.assertEqual(self.expression.expression_middle, '=!')
        self.assertEqual(self.expression.expression_comparator,
                         Comparators.neq)
Example #18
0
 def setUp(self):
     self.expression = Expression()
Example #19
0
class ListType(Type):
    '''
    Derived class which represents a list of some other datatype.  Fixed- or variable-sized.

    Public fields added:
    member is the datatype of the list elements.
    parent is the structure type containing the list.
    expr is an Expression object containing the length information, for variable-sized lists.
    '''
    def __init__(self, elt, member, parent):
        Type.__init__(self, member.name)
        self.is_list = True
        self.member = member
        self.parent = parent

        if elt.tag == 'list':
            elts = list(elt)
            self.expr = Expression(elts[0] if len(elts) else elt, self)
        elif elt.tag == 'valueparam':
            self.expr = Expression(elt, self)

        self.size = member.size if member.fixed_size() else None
        self.nmemb = self.expr.nmemb if self.expr.fixed_size() else None

    def make_member_of(self, module, complex_type, field_type, field_name,
                       visible, wire, auto):
        if not self.fixed_size():
            # We need a length field.
            # Ask our Expression object for it's name, type, and whether it's on the wire.
            lenfid = self.expr.lenfield_type
            lenfield_name = self.expr.lenfield_name
            lenwire = self.expr.lenwire
            needlen = True

            # See if the length field is already in the structure.
            for field in self.parent.fields:
                if field.field_name == lenfield_name:
                    needlen = False

            # It isn't, so we need to add it to the structure ourself.
            if needlen:
                type = module.get_type(lenfid)
                lenfield_type = module.get_type_name(lenfid)
                type.make_member_of(module, complex_type, lenfield_type,
                                    lenfield_name, True, lenwire, False)

        # Add ourself to the structure by calling our original method.
        Type.make_member_of(self, module, complex_type, field_type, field_name,
                            visible, wire, auto)

    def resolve(self, module):
        if self.resolved:
            return
        self.member.resolve(module)

        # Find my length field again.  We need the actual Field object in the expr.
        # This is needed because we might have added it ourself above.
        if not self.fixed_size():
            for field in self.parent.fields:
                if field.field_name == self.expr.lenfield_name and field.wire:
                    self.expr.lenfield = field
                    break

        self.resolved = True

    def fixed_size(self):
        return self.member.fixed_size() and self.expr.fixed_size()