[Numpy-svn] r3170 - in trunk/numpy/f2py/lib: . research research/pointers src

numpy-svn at scipy.org numpy-svn at scipy.org
Sat Sep 16 01:56:48 EDT 2006


Author: pearu
Date: 2006-09-16 00:56:18 -0500 (Sat, 16 Sep 2006)
New Revision: 3170

Added:
   trunk/numpy/f2py/lib/doc.txt
   trunk/numpy/f2py/lib/python_wrapper.py
   trunk/numpy/f2py/lib/research/pointers/
   trunk/numpy/f2py/lib/research/pointers/pointer_size.c
   trunk/numpy/f2py/lib/research/pointers/settypeinfo.f90
   trunk/numpy/f2py/lib/src/
   trunk/numpy/f2py/lib/src/F_FUNC.cpp
   trunk/numpy/f2py/lib/src/pyobj_to_Py_complex.c
   trunk/numpy/f2py/lib/src/pyobj_to_double.c
   trunk/numpy/f2py/lib/src/pyobj_to_long.c
   trunk/numpy/f2py/lib/src/pyobj_to_npy_longlong.c
   trunk/numpy/f2py/lib/src/pyobj_to_string_len.c
Modified:
   trunk/numpy/f2py/lib/analyzefortran.py
   trunk/numpy/f2py/lib/base_classes.py
   trunk/numpy/f2py/lib/block_statements.py
   trunk/numpy/f2py/lib/parsefortran.py
   trunk/numpy/f2py/lib/statements.py
   trunk/numpy/f2py/lib/typedecl_statements.py
   trunk/numpy/f2py/lib/utils.py
Log:
4G f2py: first working example.

Modified: trunk/numpy/f2py/lib/analyzefortran.py
===================================================================
--- trunk/numpy/f2py/lib/analyzefortran.py	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/analyzefortran.py	2006-09-16 05:56:18 UTC (rev 3170)
@@ -19,11 +19,14 @@
         block is a BeginSource instance with relevant attributes:
           name - reader name
           content - a list of statements
+
         Statements are either block statements or simple statements.
+
         Block statements have the following relevant attributes:
           name - block name
           blocktype - statement name (equal to lowered statement class name)
           content - a list of statements
+
         Block statements may have additional attributes:
           BeginSource: top
           Module:
@@ -42,6 +45,7 @@
           Associate: associations
           Type: specs, params
           Enum:
+
         Simple statements have various attributes:
           Assignment: variable, expr
           PointerAssignment: variable, expr

Modified: trunk/numpy/f2py/lib/base_classes.py
===================================================================
--- trunk/numpy/f2py/lib/base_classes.py	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/base_classes.py	2006-09-16 05:56:18 UTC (rev 3170)
@@ -50,13 +50,29 @@
                   % (self.__class__.__name__,name,','.join(self._attributes.keys()))
         self._attributes[name] = value
 
-    def __repr__(self):
-        l = []
+    def isempty(self):
         for k in self._attributes.keys():
             v = getattr(self,k)
-            l.append('%s=%r' % (k,v))
-        return '%s(%s)' % (self.__class__.__name__,', '.join(l))
+            if v: return False
+        return True
 
+    def __repr__(self): return self.torepr()
+
+    def torepr(self, depth=-1, tab = ''):
+        if depth==0: return tab + self.__class__.__name__
+        l = [self.__class__.__name__+':']
+        ttab = tab + '    '
+        for k in self._attributes.keys():
+            v = getattr(self,k)
+            if v:
+                if isinstance(v,list):
+                    l.append(ttab + '%s=<%s-list>' % (k,len(v)))
+                elif isinstance(v,dict):
+                    l.append(ttab + '%s=<dict with keys %s>' % (k,v.keys()))
+                else:
+                    l.append(ttab + '%s=<%s>' % (k,type(v)))
+        return '\n'.join(l)
+
     def todict(self):
         d = {}
         for k in self._attributes.keys():
@@ -95,6 +111,33 @@
         self.init = None
         return
 
+    def get_bit_size(self):
+        typesize = self.typedecl.get_bit_size(self)
+        if self.is_pointer():
+            # The size of pointer descriptor is compiler version dependent. Read:
+            #   http://www.nersc.gov/vendor_docs/intel/f_ug1/pgwarray.htm
+            #   https://www.cca-forum.org/pipermail/cca-fortran/2003-February/000123.html
+            #   https://www.cca-forum.org/pipermail/cca-fortran/2003-February/000122.html
+            # On sgi descriptor size may be 128+ bits!
+            if self.is_array():
+                wordsize = 4 # XXX: on a 64-bit system it is 8.
+                rank = len(self.bounds or self.dimension)
+                return 6 * wordsize + 12 * rank
+            return typesize
+        if self.is_array():
+            size = reduce(lambda x,y:x*y,self.bounds or self.dimension,1)
+            if self.length:
+                size *= self.length
+            return size * typesize
+        if self.length:
+            return self.length * typesize
+        return typesize
+
+    def get_typedecl(self):
+        if self.typedecl is None:
+            self.set_type(self.parent.get_type(self.name))
+        return self.typedecl
+
     def add_parent(self, parent):
         if id(parent) not in map(id, self.parents):
             self.parents.append(parent)
@@ -182,7 +225,10 @@
     def is_parameter(self): return 'PARAMETER' in self.attributes
     def is_optional(self): return 'OPTIONAL' in self.attributes
     def is_required(self): return 'REQUIRED' in self.attributes
+    def is_pointer(self): return 'POINTER' in self.attributes
 
+    def is_array(self): return not not (self.bounds or self.dimensions)
+
     def update(self, *attrs):
         attributes = self.attributes
         if len(attrs)==1 and isinstance(attrs[0],(tuple,list)):
@@ -221,8 +267,9 @@
 
     def __str__(self):
         s = ''
-        if self.typedecl is not None:
-            s += self.typedecl.tostr() + ' '
+        typedecl = self.get_typedecl()
+        if typedecl is not None:
+            s += typedecl.tostr() + ' '
         a = self.attributes[:]
         if self.dimension is not None:
             a.append('DIMENSION(%s)' % (', '.join(self.dimension)))
@@ -246,6 +293,10 @@
             s += ' = ' + self.init
         return s
 
+    def analyze(self):
+        typedecl = self.get_typedecl()
+        return
+
 class ProgramBlock:
     pass
 
@@ -257,6 +308,7 @@
       isvalid - boolean, when False, the Statement instance will be ignored
     """
     modes = ['free90','fix90','fix77','pyf']
+    _repr_attr_names = []
 
     def __init__(self, parent, item):
         self.parent = parent
@@ -264,16 +316,19 @@
             self.reader = item.reader
         else:
             self.reader = parent.reader
-        self.top = getattr(parent,'top',None)
+        self.top = getattr(parent,'top',None) # the top of statement tree
+        self.item = item
+
         if isinstance(parent, ProgramBlock):
             self.programblock = parent
         elif isinstance(self, ProgramBlock):
             self.programblock = self
         elif hasattr(parent,'programblock'):
             self.programblock = parent.programblock
+        else:
+            #self.warning('%s.programblock attribute not set.' % (self.__class__.__name__))
+            pass
 
-        self.item = item
-
         # when a statement instance is constructed by error, set isvalid to False
         self.isvalid = True
         # when a statement should be ignored, set ignore to True
@@ -292,6 +347,31 @@
 
         return
 
+    def __repr__(self):
+        return self.torepr()
+
+    def torepr(self, depth=-1,incrtab=''):
+        tab = incrtab + self.get_indent_tab()
+        clsname = self.__class__.__name__
+        l = [tab + yellow_text(clsname)]
+        if depth==0:
+            return '\n'.join(l)
+        ttab = tab + '  '
+        for n in self._repr_attr_names:
+            attr = getattr(self, n, None)
+            if not attr: continue
+            if hasattr(attr, 'torepr'):
+                r = attr.torepr(depht-1,incrtab)
+            else:
+                r = repr(attr)
+            l.append(ttab + '%s=%s' % (n, r))
+        if self.item is not None: l.append(ttab + 'item=%r' % (self.item))
+        if not self.isvalid: l.append(ttab + 'isvalid=%r' % (self.isvalid))
+        if self.ignore: l.append(ttab + 'ignore=%r' % (self.ignore))
+        if not self.a.isempty():
+            l.append(ttab + 'a=' + self.a.torepr(depth-1,incrtab+'  ').lstrip())
+        return '\n'.join(l)
+
     def get_indent_tab(self,colon=None,deindent=False):
         if self.reader.isfix:
             tab = ' '*6
@@ -321,8 +401,11 @@
         return tab
 
     def format_message(self, kind, message):
-        message = self.reader.format_message(kind, message,
-                                             self.item.span[0], self.item.span[1])
+        if self.item is not None:
+            message = self.reader.format_message(kind, message,
+                                                 self.item.span[0], self.item.span[1])
+        else:
+            return message
         return message
 
     def show_message(self, message, stream=sys.stderr):
@@ -350,14 +433,27 @@
         return
 
     def get_variable(self, name):
-        variables = self.parent.a.variables
-        if not variables.has_key(name):
-            variables[name] = var = Variable(self, name)
-        else:
-            var = variables[name]
-            var.add_parent(self)
-        return var
+        """ Return Variable instance of variable name.
+        """
+        mth = getattr(self,'get_variable_by_name', self.parent.get_variable)
+        return mth(name)
 
+    def get_type(self, name):
+        """ Return type declaration using implicit rules
+        for name.
+        """
+        mth = getattr(self,'get_type_by_name', self.parent.get_type)
+        return mth(name)
+
+    def get_type_decl(self, kind):
+        mth = getattr(self,'get_type_decl_by_kind', self.parent.get_type_decl)
+        return mth(kind)
+
+    def get_provides(self):
+        """ Returns dictonary containing statements that block provides or None when N/A.
+        """
+        return
+
 class BeginStatement(Statement):
     """ <blocktype> <name>
 
@@ -371,13 +467,14 @@
                 with the line label
       parent  - Block or FortranParser instance
       item    - Line instance containing the block start statement
-      get_item, put_item - methods to retrive/submit Line instaces
+      get_item, put_item - methods to retrive/submit Line instances
                 from/to Fortran reader.
       isvalid - boolean, when False, the Block instance will be ignored.
 
       stmt_cls, end_stmt_cls
 
     """
+    _repr_attr_names = ['blocktype','name'] + Statement._repr_attr_names
     def __init__(self, parent, item=None):
 
         self.content = []
@@ -388,7 +485,6 @@
         if not hasattr(self, 'name'):
             # process_item may change this
             self.name = '__'+self.blocktype.upper()+'__' 
-
         Statement.__init__(self, parent, item)
         return
 
@@ -401,6 +497,20 @@
             l.append(str(c))
         return '\n'.join(l)
 
+    def torepr(self, depth=-1, incrtab=''):
+        tab = incrtab + self.get_indent_tab()
+        ttab = tab + '  '
+        l=[Statement.torepr(self, depth=depth,incrtab=incrtab)]
+        if depth==0 or not self.content:
+            return '\n'.join(l)
+        l.append(ttab+'content:')
+        for c in self.content:
+            if isinstance(c,EndStatement):
+                l.append(c.torepr(depth-1,incrtab))
+            else:
+                l.append(c.torepr(depth-1,incrtab + '  '))
+        return '\n'.join(l)
+
     def process_item(self):
         """ Process the line
         """
@@ -543,6 +653,7 @@
       name
       blocktype
     """
+    _repr_attr_names = ['blocktype','name'] + Statement._repr_attr_names
 
     def __init__(self, parent, item):
         if not hasattr(self, 'blocktype'):
@@ -571,7 +682,10 @@
     def analyze(self):
         return
 
+    def get_indent_tab(self,colon=None,deindent=False):
+        return Statement.get_indent_tab(self, colon=colon, deindent=True)
+
     def __str__(self):
-        return self.get_indent_tab()[:-2] + 'END %s %s'\
+        return self.get_indent_tab() + 'END %s %s'\
                % (self.blocktype.upper(),self.name or '')
 

Modified: trunk/numpy/f2py/lib/block_statements.py
===================================================================
--- trunk/numpy/f2py/lib/block_statements.py	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/block_statements.py	2006-09-16 05:56:18 UTC (rev 3170)
@@ -14,7 +14,7 @@
 
     a = AttributeHolder(implicit_rules = {})
 
-    def get_type(self, name):
+    def get_type_by_name(self, name):
         implicit_rules = self.a.implicit_rules
         if implicit_rules is None:
             raise AnalyzeError,'Implicit rules mapping is null'
@@ -74,8 +74,19 @@
 
 class HasVariables:
 
-    a = AttributeHolder(variables = {})
+    a = AttributeHolder(variables = {},
+                        variable_names = [] # defines the order of declarations
+                        )
 
+    def get_variable_by_name(self, name):
+        variables = self.a.variables
+        if variables.has_key(name):
+            var = variables[name]
+        else:
+            var = variables[name] = Variable(self, name)
+            self.a.variable_names.append(name)
+        return var
+
     def topyf(self,tab=''):
         s = ''
         for name, var in self.a.variables.items():
@@ -92,8 +103,17 @@
             s += stmt.topyf(tab='  '+tab)
         return s
 
+    def get_type_decl_by_kind(self, kind):
+        type_decls = self.a.type_decls
+        type_decl = type_decls.get(kind, None)
+        if type_decl is None:
+            return self.get_entity(kind)
+            raise NotImplementedError,'get type_decl from use modules'
+        return type_decl
+
 class HasAttributes:
 
+    known_attributes = []
     a = AttributeHolder(attributes = [])
 
     def topyf(self, tab=''):
@@ -102,6 +122,29 @@
             s += tab + attr + '\n'
         return s
 
+    def is_private(self):
+        attributes = self.a.attributes
+        if 'PUBLIC' in attributes: return False
+        if 'PRIVATE' in attributes: return True
+        return
+    def is_public(self): return not self.is_private()
+
+    def update_attributes(self,*attrs):
+        attributes = self.a.attributes
+        known_attributes = self.known_attributes
+        if len(attrs)==1 and isinstance(attrs[0],(tuple,list)):
+            attrs = attrs[0]
+        for attr in attrs:
+            uattr = attr.upper()
+            if uattr not in attributes:
+                if isinstance(known_attributes,(list, tuple)):
+                    if uattr not in known_attributes:
+                        self.warning('unknown attribute %r' % (attr))
+                elif known_attributes(uattr):
+                    self.warning('unknown attribute %r' % (attr))
+                attributes.append(uattr)
+        return
+
 class HasModuleProcedures:
 
     a = AttributeHolder(module_procedures = [])
@@ -196,10 +239,15 @@
     """
     match = re.compile(r'module\s*\w+\Z', re.I).match
     end_stmt_cls = EndModule
+
     a = AttributeHolder(module_subprogram = {},
-                        module_data = {},
+                        module_provides = {}, # all symbols that are public and so
+                                              # can be imported via USE statement
+                                              # by other blocks
                         )
 
+    known_attributes = ['PUBLIC', 'PRIVATE']
+
     def get_classes(self):
         return access_spec + specification_part + module_subprogram_part
 
@@ -208,6 +256,9 @@
         self.name = name
         return BeginStatement.process_item(self)
 
+    def get_provides(self):
+        return self.a.module_provides
+
     def analyze(self):
         content = self.content[:]
 
@@ -225,11 +276,19 @@
         if content:
             self.show_message('Not analyzed content: %s' % content)
 
+        module_provides = self.a.module_provides
+        for name, var in self.a.variables.items():
+            if var.is_public():
+                if module_provides.has_key(name):
+                    self.warning('module data object name conflict with %s, overriding.' % (name))
+                module_provides[name] = var
+
         return
 
     def topyf(self, tab=''):
         s = tab + 'MODULE '+self.name + '\n'
         s +=  HasImplicitStmt.topyf(self, tab=tab+'  ')
+        s +=  HasAttributesStmt.topyf(self, tab=tab+'  ')
         s +=  HasTypeDecls.topyf(self, tab=tab+'  ')
         s +=  HasVariables.topyf(self, tab=tab+'  ')
         s +=  tab + '  CONTAINS\n'
@@ -270,7 +329,7 @@
     match = re.compile(r'end(\s*program\s*\w*|)\Z', re.I).match
 
 class Program(BeginStatement, ProgramBlock,
-              HasAttributes,
+              HasAttributes, # XXX: why Program needs .attributes?
               HasImplicitStmt, HasUseStmt):
     """ PROGRAM [name]
     """
@@ -340,6 +399,8 @@
     end_stmt_cls = EndInterface
     blocktype = 'interface'
 
+    a = AttributeHolder(interface_provides = {})
+
     def get_classes(self):
         return intrinsic_type_spec + interface_specification
 
@@ -358,7 +419,30 @@
             return 'ABSTRACT INTERFACE'
         return 'INTERFACE '+ str(self.generic_spec)
 
+    def get_provides(self):
+        return self.a.interface_provides
 
+    def analyze(self):
+        content = self.content[:]
+
+        while content:
+            stmt = content.pop(0)
+            if isinstance(stmt, self.end_stmt_cls):
+                break
+            stmt.analyze()
+            assert isinstance(stmt, SubProgramStatement),`stmt.__class__.__name__`
+        if content:
+            self.show_message('Not analyzed content: %s' % content)
+
+        parent_provides = self.parent.get_provides()
+        if parent_provides is not None:
+            if self.is_public():
+                if parent_provides.has_key(self.name):
+                    self.warning('interface name conflict with %s, overriding.' % (self.name))
+                parent_provides[self.name] = self
+    
+        return
+
 # Subroutine
 
 class SubProgramStatement(BeginStatement, ProgramBlock,
@@ -369,6 +453,8 @@
     """
     [ <prefix> ] <FUNCTION|SUBROUTINE> <name> [ ( <args> ) ] [ <suffix> ]
     """
+    known_attributes = ['PUBLIC', 'PRIVATE']
+
     a = AttributeHolder(internal_subprogram = {})
 
     def process_item(self):
@@ -430,7 +516,7 @@
         content = self.content[:]
 
         if self.prefix:
-            self.a.attributes.extend(prefix.upper().split())
+            self.update_attributes(prefix.upper().split())
 
         variables = self.a.variables
         for a in self.args:
@@ -459,6 +545,13 @@
         if content:
             self.show_message('Not analyzed content: %s' % content)
 
+        parent_provides = self.parent.get_provides()
+        if parent_provides is not None:
+            if self.is_public():
+                if parent_provides.has_key(self.name):
+                    self.warning('module subprogram name conflict with %s, overriding.' % (self.name))
+                parent_provides[self.name] = self
+
         return
 
     def topyf(self, tab=''):
@@ -486,6 +579,7 @@
     """
     end_stmt_cls = EndSubroutine
     match = re.compile(r'(recursive|pure|elemental|\s)*subroutine\s*\w+', re.I).match
+    _repr_attr_names = ['prefix','bind','suffix','args'] + Statement._repr_attr_names
 
 # Function
 
@@ -506,6 +600,7 @@
     """
     end_stmt_cls = EndFunction
     match = re.compile(r'(recursive|pure|elemental|\s)*function\s*\w+', re.I).match
+    _repr_attr_names = ['prefix','bind','suffix','args','typedecl'] + Statement._repr_attr_names
 
 # Handle subprogram prefixes
 
@@ -800,7 +895,11 @@
     end_stmt_cls = EndType
 
     a = AttributeHolder(extends = None,
-                        parameters = [])
+                        parameters = {},
+                        component_names = [], # specifies component order for sequence types
+                        components = {}
+                        )
+    known_attributes = re.compile(r'\A(PUBLIC|PRIVATE|SEQUENCE|ABSTRACT|BIND\s*\(.*\))\Z').match
 
     def process_item(self):
         line = self.item.get_line()[4:].lstrip()
@@ -858,15 +957,41 @@
                     spec = 'BIND(%s)' % (', '.join(args))
                 else:
                     spec = '%s(%s)' % (s,n)
-                    self.warning('Unknown type-attr-spec %r' % (spec))
             else:
                 spec = spec.upper()
-                if spec not in ['PUBLIC', 'PRIVATE', 'ABSTRACT']:
-                    self.warning('Unknown type-attr-spec %r' % (spec))
-            self.a.attributes.append(spec)
-        self.a.parameters.extend(self.params)
-        assert isinstance(self.parent,HasTypeDecls),`self.parent.__class__`
+            self.update_attributes(spec)
+
+        component_names = self.a.component_names
+        content = self.content[:]
+        while content:
+            stmt = content.pop(0)
+            if isinstance(stmt, self.end_stmt_cls):
+                break
+            stmt.analyze()
+
+        if content:
+            self.show_message('Not analyzed content: %s' % content)
+
+        parameters = self.a.parameters
+        components = self.a.components
+        component_names = self.a.component_names
+        for name in self.a.variable_names:
+            var = self.a.variables[name]
+            if name in self.params:
+                parameters[name] = var
+            else:
+                component_names.append(name)
+                components[name] = var
+
         self.parent.a.type_decls[self.name] = self
+
+        parent_provides = self.parent.get_provides()
+        if parent_provides is not None:
+            if self.is_public():
+                if parent_provides.has_key(self.name):
+                    self.warning('type declaration name conflict with %s, overriding.' % (self.name))
+                parent_provides[self.name] = self
+
         return
 
     def topyf(self, tab=''):

Added: trunk/numpy/f2py/lib/doc.txt
===================================================================
--- trunk/numpy/f2py/lib/doc.txt	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/doc.txt	2006-09-16 05:56:18 UTC (rev 3170)
@@ -0,0 +1,311 @@
+
+Created: September 2006
+Author: Pearu Peterson <pearu.peterson at gmail.com>
+
+Structure
+=========
+
+numpy.f2py.lib package contains the following files:
+
+readfortran.py
+--------------
+
+Tools for reading Fortran codes from file and string objects.
+
+To read Fortran code from a file, use FortranFileReader class.
+
+FortranFileReader class is iterator over Fortran code lines
+as is derived from FortranReaderBase class.
+It automatically handles line continuations and comments as
+well as detects if Fortran file is in free or fixed format.
+
+For example,
+
+::
+  >>> from readfortran import *
+  >>> import os
+  >>> reader = FortranFileReader(os.path.expanduser('~/src/blas/daxpy.f'))
+  >>> reader.next()
+  Line('subroutine daxpy(n,da,dx,incx,dy,incy)',(1, 1),'')
+  >>> reader.next()
+  Comment('c     constant times a vector plus a vector.\nc     uses unrolled loops for increments equal to one.\nc     jack dongarra, linpack, 3/11/78.\nc     modified 12/3/93, array(1) declarations changed to array(*)',(3, 6))
+  >>> reader.next()
+  Line('double precision dx(*),dy(*),da',(8, 8),'')
+  >>> reader.next()
+  Line('integer i,incx,incy,ix,iy,m,mp1,n',(9, 9),'')
+
+FortranReaderBase.next() method may return Line, SyntaxErrorLine, Comment, MultiLine,
+SyntaxErrorMultiLine instances.
+
+Line instance has the following attributes:
+
+  * .line - contains Fortran code line
+  * .span - a 2-tuple containing the span of line numbers containing
+            Fortran code in the original Fortran file
+  * .label - the label of Fortran code line
+  * .reader - the FortranReaderBase class instance
+  * .strline - if not None then contains Fortran code line with parenthesis
+             content and string literal constants saved in .strlinemap dictionary.
+  * .is_f2py_directive - True if line started with f2py directive comment.
+
+and the following methods:
+
+  * .get_line() - returns .strline (also evalutes it if None). Also
+                  handles Hollerith contstants in fixed F77 mode.
+  * .isempty()  - returns True if Fortran line contains no code.
+  * .copy(line=None, apply_map=False) - returns a Line instance
+    with given .span, .label, .reader information but line content
+    replaced with line (when not None) and applying .strlinemap
+    mapping (when apply_map is True).
+  * .apply_map(line) - apply .strlinemap mapping to line.
+  * .has_map() - returns True if .strlinemap mapping exists.
+
+For example,
+
+::
+
+  >>> item = reader.next()
+  >>> item
+  Line('if(n.le.0)return',(11, 11),'')
+  >>> item.line
+  'if(n.le.0)return'
+  >>> item.strline
+  'if(F2PY_EXPR_TUPLE_4)return'
+  >>> item.strlinemap
+  {'F2PY_EXPR_TUPLE_4': 'n.le.0'}
+  >>> item.label
+  ''
+  >>> item.span 
+  (11, 11)
+  >>> item.get_line()
+  'if(F2PY_EXPR_TUPLE_4)return'
+  >>> item.copy('if(F2PY_EXPR_TUPLE_4)pause',True)
+  Line('if(n.le.0)pause',(11, 11),'')
+
+Comment instance has the following attributes:
+
+  * .comment - comment string
+  * .span - a 2-tuple containing the span of line numbers containing
+            Fortran comment in the original Fortran file
+  * .reader - the FortranReaderBase class instance
+
+and .isempty() method.
+
+MultiLine class represents multiline syntax in .pyf files::
+
+  <prefix>'''<lines>'''<suffix>
+
+MultiLine instance has the following attributes:
+
+  * .prefix - the content of <prefix>
+  * .block - a list of lines
+  * .suffix - the content of <suffix>
+  * .span - a 2-tuple containing the span of line numbers containing
+            multiline syntax in the original Fortran file
+  * .reader - the FortranReaderBase class instance
+
+and .isempty() method.
+
+SyntaxErrorLine and SyntaxErrorMultiLine are like Line and MultiLine
+classes, respectively, with a functionality of issuing an error
+message to sys.stdout when constructing an instance of the corresponding
+class.
+
+To read a Fortran code from a string, use FortranStringReader class::
+
+  reader = FortranStringReader(<string>, <isfree>, <isstrict>)
+
+where the second and third arguments are used to specify the format
+of the given <string> content. When <isfree> and <isstrict> are both
+True, the content of a .pyf file is assumed. For example,
+
+::
+
+  >>> code = """                       
+  ... c      comment
+  ...       subroutine foo(a)
+  ...       print*, "a=",a
+  ...       end
+  ... """
+  >>> reader = FortranStringReader(code, False, True)
+  >>> reader.next()
+  Comment('c      comment',(2, 2))
+  >>> reader.next()
+  Line('subroutine foo(a)',(3, 3),'')
+  >>> reader.next()
+  Line('print*, "a=",a',(4, 4),'')
+  >>> reader.next()
+  Line('end',(5, 5),'')
+
+FortranReaderBase has the following attributes:
+
+  * .source - a file-like object with .next() method to retrive 
+              a source code line
+  * .source_lines - a list of read source lines
+  * .reader - a FortranReaderBase instance for reading files
+              from INCLUDE statements.
+  * .include_dirs - a list of directories where INCLUDE files
+              are searched. Default is ['.'].
+
+and the following methods:
+
+  * .set_mode(isfree, isstrict) - set Fortran code format information
+  * .close_source() - called when .next() raises StopIteration exception.
+
+parsefortran.py
+---------------
+
+Parse Fortran code from FortranReaderBase iterator.
+
+FortranParser class holds the parser information while
+iterating over items returned by FortranReaderBase iterator.
+The parsing information, collected when calling .parse() method,
+is saved in .block attribute as an instance
+of BeginSource class defined in block_statements.py file.
+
+For example,
+
+::
+
+  >>> reader = FortranStringReader(code, False, True)
+  >>> parser = FortranParser(reader)
+  >>> parser.parse()
+  >>> print parser.block
+        !BEGINSOURCE <cStringIO.StringI object at 0xb751d500> mode=fix77
+          SUBROUTINE foo(a)
+            PRINT *, "a=", a
+          END SUBROUTINE foo
+
+block_statements.py, base_classes.py, typedecl_statements.py, statements.py
+---------------------------------------------------------------------------
+
+The model for representing Fortran code statements consists of a tree of Statement
+classes defined in base_classes.py. There are two types of statements: one line
+statements and block statements. Block statements consists of start and end
+statements, and content statements in between that can be of both types again.
+
+Statement instance has the following attributes:
+
+  * .parent  - it is either parent block-type statement or FortranParser instance.
+  * .item    - Line instance containing Fortran statement line information, see above.
+  * .isvalid - when False then processing this Statement instance will be skipped,
+               for example, when the content of .item does not match with
+               the Statement class.
+  * .ignore  - when True then the Statement instance will be ignored.
+  * .modes   - a list of Fortran format modes where the Statement instance is valid.
+
+and the following methods:
+
+  * .info(message), .warning(message), .error(message) - to spit messages to
+               sys.stderr stream.
+  * .get_variable(name) - get Variable instance by name that is defined in
+               current namespace. If name is not defined, then the corresponding
+               Variable instance is created.
+  * .analyze() - calculate various information about the Statement, this information
+               is saved in .a attribute that is AttributeHolder instance.
+
+All statement classes are derived from Statement class. Block statements are
+derived from BeginStatement class and is assumed to end with EndStatement
+instance in .content attribute list. BeginStatement and EndStatement instances
+have the following attributes:
+
+  * .name      - name of the block, blocks without names use line label
+                 as the name.
+  * .blocktype - type of the block (derived from class name)
+  * .content   - a list of Statement (or Line) instances.
+
+and the following methods:
+
+  * .__str__() - returns string representation of Fortran code.
+
+A number of statements may declare a variable that is used in other
+statement expressions. Variables are represented via Variable class
+and its instances have the following attributes:
+
+  * .name      - name of the variable
+  * .typedecl  - type declaration
+  * .dimension - list of dimensions
+  * .bounds    - list of bounds
+  * .length    - length specs
+  * .attributes - list of attributes
+  * .bind      - list of bind information
+  * .intent    - list of intent information
+  * .check     - list of check expressions
+  * .init      - initial value of the variable
+  * .parent    - statement instance declaring the variable
+  * .parents   - list of statements that specify variable information
+
+and the following methods:
+
+  * .is_private()
+  * .is_public()
+  * .is_allocatable()
+  * .is_external()
+  * .is_intrinsic()
+  * .is_parameter()
+  * .is_optional()
+  * .is_required()
+
+The following type declaration statements are defined in typedecl_statements.py:
+
+  Integer, Real, DoublePrecision, Complex, DoubleComplex, Logical, 
+  Character, Byte, Type, Class
+
+and they have the following attributes:
+
+  * .selector           - contains lenght and kind specs
+  * .entity_decls, .attrspec
+
+and methods:
+
+  * .tostr() - return string representation of Fortran type declaration
+  * .astypedecl() - pure type declaration instance, it has no .entity_decls
+                    and .attrspec.
+  * .analyze() - processes .entity_decls and .attsspec attributes and adds
+                 Variable instance to .parent.a.variables dictionary.
+
+The following block statements are defined in block_statements.py:
+
+  BeginSource, Module, PythonModule, Program, BlockData, Interface,
+  Subroutine, Function, Select, Where, Forall, IfThen, If, Do,
+  Associate, TypeDecl (Type), Enum
+
+Block statement classes may have different properties which are declared via
+deriving them from the following classes:
+
+  HasImplicitStmt, HasUseStmt, HasVariables, HasTypeDecls,
+  HasAttributes, HasModuleProcedures, ProgramBlock
+
+In summary, .a attribute may hold different information sets as follows:
+
+  BeginSource - .module, .external_subprogram, .blockdata
+  Module - .attributes, .implicit_rules, .use, .use_provides, .variables,
+           .type_decls, .module_subprogram, .module_data
+  PythonModule - .implicit_rules, .use, .use_provides
+  Program - .attributes, .implicit_rules, .use, .use_provides
+  BlockData - .implicit_rules, .use, .use_provides, .variables
+  Interface - .implicit_rules, .use, .use_provides, .module_procedures
+  Function, Subroutine - .implicit_rules, .attributes, .use, .use_statements,
+              .variables, .type_decls, .internal_subprogram
+  TypeDecl - .variables, .attributes
+
+Block statements have the following methods:
+
+  * .get_classes() - returns a list of Statement classes that are valid
+                     as a content of given block statement.
+
+The following one line statements are defined:
+
+  Implicit, TypeDeclarationStatement derivatives (see above),
+  Assignment, PointerAssignment, Assign, Call, Goto, ComputedGoto,
+  AssignedGoto, Continue, Return, Stop, Print, Read, Write, Flush,
+  Wait, Contains, Allocate, Deallocate, ModuleProcedure, Access,
+  Public, Private, Close, Cycle, Backspace, Endfile, Reeinf, Open,
+  Format, Save, Data, Nullify, Use, Exit, Parameter, Equivalence,
+  Dimension, Target, Pointer, Protected, Volatile, Value, 
+  ArithmeticIf, Intrinsic, Inquire, Sequence, External, Namelist,
+  Common, Optional, Intent, Entry, Import, Forall,
+  SpecificBinding, GenericBinding, FinalBinding, Allocatable,
+  Asynchronous, Bind, Else, ElseIf, Case, Where, ElseWhere,
+  Enumerator, FortranName, Threadsafe, Depend, Check,
+  CallStatement, CallProtoArgument, Pause

Modified: trunk/numpy/f2py/lib/parsefortran.py
===================================================================
--- trunk/numpy/f2py/lib/parsefortran.py	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/parsefortran.py	2006-09-16 05:56:18 UTC (rev 3170)
@@ -10,6 +10,8 @@
 Created: May 2006
 """
 
+__all__ = ['FortranParser']
+
 import re
 import sys
 import traceback
@@ -24,6 +26,10 @@
     cache = {}
 
     def __init__(self, reader):
+        """
+        Parser of FortranReader structure.
+        Use .parse() method for parsing, parsing result is saved in .block attribute.
+        """
         self.reader = reader
         if self.cache.has_key(reader.id):
             parser = self.cache[reader.id]
@@ -156,7 +162,7 @@
         parser = FortranParser(reader)
         parser.parse()
         parser.analyze()
-        print parser.block.topyf()
+        print parser.block.torepr(4)
         #print parser.block
 
 def profile_main():

Added: trunk/numpy/f2py/lib/python_wrapper.py
===================================================================
--- trunk/numpy/f2py/lib/python_wrapper.py	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/python_wrapper.py	2006-09-16 05:56:18 UTC (rev 3170)
@@ -0,0 +1,549 @@
+
+__all__ = ['TypeWrapper']
+
+import re
+import os
+import sys
+
+from block_statements import *
+#from typedecl_statements import intrinsic_type_spec, Character
+from utils import CHAR_BIT
+
+class WrapperBase:
+
+
+    def __init__(self):
+        self.srcdir = os.path.join(os.path.dirname(__file__),'src')
+        return
+    def warning(self, message):
+        print >> sys.stderr, message
+    def info(self, message):
+        print >> sys.stderr, message
+
+    def get_resource_content(self, name, ext):
+        if name.startswith('pyobj_to_'):
+            body = self.generate_pyobj_to_ctype_c(name[9:])
+            if body is not None: return body
+        generator_mth_name = 'generate_' + name + ext.replace('.','_')
+        generator_mth = getattr(self, generator_mth_name, lambda : None)
+        body = generator_mth()
+        if body is not None:
+            return body
+        fn = os.path.join(self.srcdir,name+ext)
+        if os.path.isfile(fn):
+            f = open(fn,'r')
+            body = f.read()
+            f.close()
+            return body
+        self.warning('No such file: %r' % (fn))
+        return
+
+    def get_dependencies(self, code):
+        l = []
+        for uses in re.findall(r'(?<=depends:)([,\w\s.]+)', code, re.I):
+            for use in uses.split(','):
+                use = use.strip()
+                if not use: continue
+                l.append(use)
+        return l
+
+    def apply_attributes(self, template):
+        """
+        Apply instance attributes to template string.
+
+        Replace rules for attributes:
+        _list  - will be joined with newline
+        _clist - _list will be joined with comma
+        _elist - _list will be joined
+        ..+.. - attributes will be added
+        [..]  - will be evaluated
+        """
+        replace_names = set(re.findall(r'[ ]*%\(.*?\)s', template))
+        d = {}
+        for name in replace_names:
+            tab = ' ' * (len(name)-len(name.lstrip()))
+            name = name.lstrip()[2:-2]
+            names = name.split('+')
+            joinsymbol = '\n'
+            attrs = None
+            for n in names:
+                realname = n.strip()
+                if n.endswith('_clist'):
+                    joinsymbol = ', '
+                    realname = realname[:-6] + '_list'
+                elif n.endswith('_elist'):
+                    joinsymbol = ''
+                    realname = realname[:-6] + '_list'
+                if hasattr(self, realname):
+                    attr = getattr(self, realname)
+                elif realname.startswith('['):
+                    attr = eval(realname)
+                else:
+                    self.warning('Undefined %r attribute: %r' % (self.__class__.__name__, realname))
+                    continue
+                if attrs is None:
+                    attrs = attr
+                else:
+                    attrs += attr
+            if isinstance(attrs, list):
+                attrs = joinsymbol.join(attrs)
+            d[name] = str(attrs).replace('\n','\n'+tab)
+        return template % d
+
+class PythonWrapperModule(WrapperBase):
+
+    main_template = '''\
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+#include "Python.h"
+
+#define PY_ARRAY_UNIQUE_SYMBOL PyArray_API
+#include "numpy/arrayobject.h"
+
+%(include_list)s
+%(cppmacro_list)s
+%(typedef_list)s
+%(objdecl_list)s
+%(extern_list)s
+%(c_function_list)s
+%(capi_function_list)s
+static PyObject *f2py_module;
+static PyMethodDef f2py_module_methods[] = {
+  %(module_method_list)s
+  {NULL,NULL,0,NULL}
+};
+PyMODINIT_FUNC init%(modulename)s(void) {
+  f2py_module = Py_InitModule("%(modulename)s", f2py_module_methods);
+  %(initialize_interface_list)s
+  if (PyErr_Occurred()) {
+    PyErr_SetString(PyExc_ImportError, "can\'t initialize module %(modulename)s");
+    return;
+  }
+}
+#ifdef __cplusplus
+}
+#endif
+'''
+
+    main_fortran_template = '''\
+%(fortran_code_list)s
+'''
+    def __init__(self, modulename):
+        WrapperBase.__init__(self)
+        self.modulename = modulename
+        self.include_list = []
+        self.typedef_list = []
+        self.cppmacro_list = []
+        self.objdecl_list = []
+        self.c_function_list = []
+        self.extern_list = []
+        self.capi_function_list = []
+        self.module_method_list = []
+        self.initialize_interface_list = []
+        self.fortran_code_list = []
+
+        self.defined_types = []
+        self.defined_macros = []
+        self.defined_c_functions = []
+        self.defined_typedefs = []
+        return
+
+    def add(self, block):
+        if isinstance(block, BeginSource):
+            for name, subblock in block.a.external_subprogram.items():
+                self.add(subblock)
+        elif isinstance(block, (Subroutine, Function)):
+            self.info('Generating interface for %s' % (block.name))
+            f = PythonCAPIFunction(self, block)
+            f.fill()            
+        else:
+            raise NotImplementedError,`block.__class__.__name__`
+        return
+    
+    def c_code(self):
+        return self.apply_attributes(self.main_template)
+    def fortran_code(self):
+        return self.apply_attributes(self.main_fortran_template)
+
+    def add_c_function(self, name):
+        if name not in self.defined_c_functions:
+            body = self.get_resource_content(name,'.c')
+            if body is None:
+                self.warning('Failed to get C function %r content.' % (name))
+                return
+            for d in self.get_dependencies(body):
+                if d.endswith('.cpp'):
+                    self.add_cppmacro(d[:-4])
+                elif d.endswith('.c'):
+                    self.add_c_function(d[:-2])
+                else:
+                    self.warning('Unknown dependence: %r.' % (d))
+            self.defined_c_functions.append(name)
+            self.c_function_list.append(body)
+        return
+
+    def add_cppmacro(self, name):
+        if name not in self.defined_macros:
+            body = self.get_resource_content(name,'.cpp')
+            if body is None:
+                self.warning('Failed to get CPP macro %r content.' % (name))
+                return
+            for d in self.get_dependencies(body):
+                if d.endswith('.cpp'):
+                    self.add_cppmacro(d[:-4])
+                elif d.endswith('.c'):
+                    self.add_c_function(d[:-2])
+                else:
+                    self.warning('Unknown dependence: %r.' % (d))
+            self.defined_macros.append(name)
+            self.cppmacro_list.append(body)
+        return
+
+    def add_type(self, typedecl):
+        typewrap = TypeDecl(self, typedecl)
+        typename = typewrap.typename
+        if typename not in self.defined_types:
+            self.defined_types.append(typename)
+            typewrap.fill()
+        return typename
+
+    def add_typedef(self, name, code):
+        if name not in self.defined_typedefs:
+            self.typedef_list.append(code)
+            self.defined_types.append(name)
+        return
+
+    def add_include(self, include):
+        if include not in self.include_list:
+            self.include_list.append(include)
+        return
+
+    def add_subroutine(self, block):
+        f = PythonCAPIFunction(self, block)
+        f.fill()
+        return
+
+    def generate_pyobj_to_ctype_c(self, ctype):
+        if ctype.startswith('npy_int'):
+            ctype_bits = int(ctype[7:])
+            return '''
+/* depends: pyobj_to_long.c, pyobj_to_npy_longlong.c */
+#if NPY_BITSOF_LONG == %(ctype_bits)s
+#define pyobj_to_%(ctype)s pyobj_to_long
+#else
+#if NPY_BITSOF_LONG > %(ctype_bits)s
+static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
+  long tmp;
+  if (pyobj_to_long(obj,&tmp)) {
+    *value = (%(ctype)s)tmp;
+    return 1;
+  }
+  return 0;
+}
+#else
+static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
+  npy_longlong tmp;
+  if (pyobj_to_npy_longlong(obj,&tmp)) {
+    *value = (%(ctype)s)tmp;
+    return 1;
+  }
+  return 0;
+}
+#endif
+#endif
+''' % (locals())
+        elif ctype.startswith('npy_float'):
+            ctype_bits = int(ctype[9:])
+            return '''
+/* depends: pyobj_to_double.c */
+#if NPY_BITSOF_DOUBLE == %(ctype_bits)s
+#define pyobj_to_%(ctype)s pyobj_to_double
+#else
+#if NPY_BITSOF_DOUBLE > %(ctype_bits)s
+static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
+  double tmp;
+  if (pyobj_to_double(obj,&tmp)) {
+    *value = (%(ctype)s)tmp;
+    return 1;
+  }
+  return 0;
+}
+#else
+#error, "NOTIMPLEMENTED pyobj_to_%(ctype)s"
+#endif
+#endif
+''' % (locals())
+        elif ctype.startswith('npy_complex'):
+            ctype_bits = int(ctype[11:])
+            cfloat_bits = ctype_bits/2
+            return '''
+/* depends: pyobj_to_Py_complex.c */
+#if NPY_BITSOF_DOUBLE >= %(cfloat_bits)s
+static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
+  Py_complex c;
+  if (pyobj_to_Py_complex(obj,&c)) {
+    (*value).real = (npy_float%(cfloat_bits)s)c.real;
+    (*value).imag = (npy_float%(cfloat_bits)s)c.imag; 
+    return 1;
+  }
+  return 0;
+}
+#else
+#error, "NOTIMPLEMENTED pyobj_to_%(ctype)s"
+#endif
+''' % (locals())
+        elif ctype.startswith('f2py_string'):
+            ctype_bits = int(ctype[11:])
+            ctype_bytes = ctype_bits / CHAR_BIT
+            self.add_typedef('f2py_string','typedef char * f2py_string;')
+            self.add_typedef(ctype,'typedef struct { char data[%s]; } %s;' % (ctype_bytes,ctype))
+            self.add_include('#include <string.h>')
+            return '''
+/* depends: pyobj_to_string_len.c */
+static int pyobj_to_%(ctype)s(PyObject *obj, %(ctype)s* value) {
+  return pyobj_to_string_len(obj, (f2py_string*)value, %(ctype_bytes)s);
+}
+''' % (locals())
+
+class PythonCAPIFunction(WrapperBase):
+    capi_function_template = '''
+static char f2py_doc_%(function_name)s[] = "%(function_doc)s";
+static PyObject* f2py_%(function_name)s(PyObject *capi_self, PyObject *capi_args, PyObject *capi_keywds) {
+  PyObject * volatile capi_buildvalue = NULL;
+  volatile int f2py_success = 1;
+  %(decl_list)s
+  static char *capi_kwlist[] = {%(keyword_clist+optkw_clist+extrakw_clist+["NULL"])s};
+  if (!PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,
+                                   "%(pyarg_format_elist)s",
+                                   %(["capi_kwlist"]+pyarg_obj_clist)s))
+     return NULL;
+  %(frompyobj_list)s
+  %(call_list)s
+  f2py_success = !PyErr_Occurred();
+  if (f2py_success) {
+    %(pyobjfrom_list)s
+    capi_buildvalue = Py_BuildValue(%(buildvalue_clist)s);
+    %(clean_pyobjfrom_list)s
+  }
+  %(clean_frompyobj_list)s
+  return capi_buildvalue;
+}
+'''    
+
+    pymethoddef_template = '''\
+{"%(function_name)s", (PyCFunction)f2py_%(function_name)s, METH_VARARGS | METH_KEYWORDS, f2py_doc_%(function_name)s},\
+'''
+
+    cppmacro_template = '''\
+#define %(function_name)s_f F_FUNC(%(function_name)s,%(FUNCTION_NAME)s)
+'''
+
+    extdef_template = '''\
+extern void %(function_name)s_f();\
+'''
+
+    def __init__(self, parent, block):
+        WrapperBase.__init__(self)
+        self.parent = parent
+        self.block = block
+        self.function_name = block.name
+        self.FUNCTION_NAME = self.function_name.upper()
+        self.function_doc = ''
+        self.args_list = block.args
+        self.decl_list = []
+        self.keyword_list = []
+        self.optkw_list = []
+        self.extrakw_list = []
+        self.frompyobj_list = []
+        self.call_list = []
+        self.pyobjfrom_list = []
+        self.buildvalue_list = []
+        self.clean_pyobjfrom_list = []
+        self.clean_frompyobj_list = []
+        self.pyarg_format_list = []
+        self.pyarg_obj_list = []
+        return
+
+    def fill(self):
+        for argname in self.args_list:
+            var = self.block.a.variables[argname]
+            argwrap = ArgumentWrapper(self, var)
+            argwrap.fill()
+        self.call_list.append('%s_f(%s);' % (self.function_name, ', '.join(['&'+a for a in self.args_list])))
+        if not self.buildvalue_list:
+            self.buildvalue_list.append('""')
+        self.parent.capi_function_list.append(self.apply_attributes(self.capi_function_template))
+        self.parent.module_method_list.append(self.apply_attributes(self.pymethoddef_template))
+        self.parent.extern_list.append(self.apply_attributes(self.extdef_template))
+        self.parent.add_cppmacro('F_FUNC')
+        self.parent.cppmacro_list.append(self.apply_attributes(self.cppmacro_template))
+        return
+
+class ArgumentWrapper(WrapperBase):
+
+    objdecl_template = '%(ctype)s %(name)s;'
+    pyarg_obj_template = '\npyobj_to_%(ctype)s, &%(name)s'
+
+    def __init__(self, parent, variable):
+        WrapperBase.__init__(self)
+        self.parent = parent
+        self.grand_parent = parent.parent
+        self.variable = variable
+        self.typedecl = variable.typedecl
+        self.name = variable.name
+        self.ctype = self.typedecl.get_c_type()
+        
+    def fill(self):
+        typename = self.grand_parent.add_type(self.typedecl)
+        self.parent.decl_list.append(self.apply_attributes(self.objdecl_template))
+        
+        self.parent.pyarg_obj_list.append(self.apply_attributes(self.pyarg_obj_template))
+        self.parent.pyarg_format_list.append('O&')
+        self.parent.keyword_list.append('"%s"' % (self.name))
+
+        self.grand_parent.add_c_function('pyobj_to_%s' % (self.ctype))
+        return
+
+class TypeDecl(WrapperBase):
+    cppmacro_template = '''\
+#define initialize_%(typename)s_interface F_FUNC(initialize_%(typename)s_interface_f,INITIALIZE_%(TYPENAME)s_INTERFACE_F)\
+'''
+    typedef_template = '''\
+typedef struct { char data[%(byte_size)s] } %(ctype)s;
+typedef %(ctype)s (*create_%(typename)s_functype)(void);
+typedef void (*initialize_%(typename)s_interface_functype)(create_%(typename)s_functype);\
+'''
+    objdecl_template = '''\
+static create_%(typename)s_functype create_%(typename)s_object;
+'''
+    funcdef_template = '''\
+static void initialize_%(typename)s_interface_c(create_%(typename)s_functype create_object_f) {
+  create_%(typename)s_object = create_object_f;
+}
+'''
+    extdef_template = '''\
+extern void initialize_%(typename)s_interface(initialize_%(typename)s_interface_functype);\
+'''
+    initcall_template = '''\
+initialize_%(typename)s_interface(initialize_%(typename)s_interface_c);\
+'''
+    fortran_code_template = '''\
+       function create_%(typename)s_object_f() result (obj)
+         %(typedecl)s obj
+!         %(initexpr)s
+       end
+       subroutine initialize_%(typename)s_interface_f(init_c)
+         external create_%(typename)s_object_f
+         call init_c(create_%(typename)s_object_f)
+       end
+'''
+
+    def __init__(self, parent, typedecl):
+        WrapperBase.__init__(self)
+        self.parent = parent
+        self.typedecl = typedecl.astypedecl()
+        self.ctype = self.typedecl.get_c_type()
+        self.byte_size = self.typedecl.get_byte_size()
+        self.typename = self.typedecl.name.lower()
+        self.TYPENAME = self.typedecl.name.upper()
+        self.initexpr = self.typedecl.assign_expression('obj',self.typedecl.get_zero_value())
+        return
+
+    def fill(self):
+        ctype =self.typedecl.get_c_type()
+        if ctype.startswith('npy_'):
+            pass
+        elif ctype.startswith('f2py_string'):
+            pass
+        else:
+            self.parent.typedef_list.append(self.apply_attributes(self.typedef_template))
+            self.parent.objdecl_list.append(self.apply_attributes(self.objdecl_template))
+            self.parent.c_function_list.append(self.apply_attributes(self.funcdef_template))
+            self.parent.extern_list.append(self.apply_attributes(self.extdef_template))
+            self.parent.initialize_interface_list.append(self.apply_attributes(self.initcall_template))
+            self.parent.fortran_code_list.append(self.apply_attributes(self.fortran_code_template))
+            self.parent.add_cppmacro('F_FUNC')
+            self.parent.cppmacro_list.append(self.apply_attributes(self.cppmacro_template))
+        return
+
+
+
+
+if __name__ == '__main__':
+    from utils import str2stmt, get_char_bit
+
+    stmt = str2stmt("""
+    module rat
+      integer :: i
+      type rational
+        integer n
+        integer*8 d
+      end type rational
+    end module rat
+    subroutine foo(a)
+    use rat
+    type(rational) a
+    end
+    """)
+    #stmt = stmt.content[-1].content[1]
+    #print stmt
+    #wrapgen = TypeWrapper(stmt)
+    #print wrapgen.fortran_code()
+    #print wrapgen.c_code()
+
+    foo_code = """! -*- f90 -*-
+      module rat
+        type rational
+          integer d,n
+        end type rational
+      end module rat
+      subroutine foo(a,b)
+        use rat
+        integer a
+        character*5 b
+        type(rational) c
+        print*,'a=',a,b,c
+      end
+"""
+
+    wm = PythonWrapperModule('foo')
+    wm.add(str2stmt(foo_code))
+    #wm.add_fortran_code(foo_code)
+    #wm.add_subroutine(str2stmt(foo_code))
+    #print wm.c_code()
+
+    c_code = wm.c_code()
+    f_code = wm.fortran_code()
+
+    f = open('foomodule.c','w')
+    f.write(c_code)
+    f.close()
+    f = open('foo.f','w')
+    f.write(foo_code)
+    f.close()
+    f = open('foo_wrap.f','w')
+    f.write(f_code)
+    f.close()
+    f = open('foo_setup.py','w')
+    f.write('''\
+def configuration(parent_package='',top_path=None):
+    from numpy.distutils.misc_util import Configuration
+    config = Configuration('foopack',parent_package,top_path)
+    config.add_library('foolib',
+                       sources = ['foo.f','foo_wrap.f'])
+    config.add_extension('foo',
+                         sources=['foomodule.c'],
+                         libraries = ['foolib'],
+                         )
+    return config
+if __name__ == '__main__':
+    from numpy.distutils.core import setup
+    setup(configuration=configuration)
+''')
+    f.close()
+    print get_char_bit()
+    os.system('python foo_setup.py config_fc --fcompiler=gnu95 build build_ext --inplace')
+    import foo
+    print dir(foo)
+    foo.foo(2,"abcdefg")

Added: trunk/numpy/f2py/lib/research/pointers/pointer_size.c
===================================================================
--- trunk/numpy/f2py/lib/research/pointers/pointer_size.c	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/research/pointers/pointer_size.c	2006-09-16 05:56:18 UTC (rev 3170)
@@ -0,0 +1,30 @@
+#include <stdio.h>
+
+#define settypeinfo settypeinfo_
+
+void settypeinfo(int*);
+
+int main(int argc, char* argv[])
+{
+  int i;
+  int a[512];
+  for(i=0;i<512;i++) a[i] = 0;
+
+  settypeinfo(a);  
+
+  if (a[0] != 333331) {
+    printf("FAILED, start flag is incorrect = %d\n", a[0]);
+    return 1;
+  }
+
+  for (i = 0; i < 512; i++) {
+    if (a[i] == 333332) {
+      printf("SUCCESSFULLY found Fortran pointer length of %d bytes\n",
+	     (i-1)*sizeof(int));
+      return 0;
+    }
+  }
+
+  printf("FAILED to find end flag\n");
+  return 1;
+}

Added: trunk/numpy/f2py/lib/research/pointers/settypeinfo.f90
===================================================================
--- trunk/numpy/f2py/lib/research/pointers/settypeinfo.f90	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/research/pointers/settypeinfo.f90	2006-09-16 05:56:18 UTC (rev 3170)
@@ -0,0 +1,13 @@
+! Author: Pearu Peterson
+! Got idea from https://www.cca-forum.org/pipermail/cca-fortran/2003-February/000123.html
+
+subroutine settypeinfo(wrapper)
+  type data_wrapper
+    integer :: ibegin
+    character*20 :: p_data*10
+    integer :: iend
+  end type data_wrapper
+  type(data_wrapper), intent(out) :: wrapper
+  wrapper%ibegin        = 333331
+  wrapper%iend          = 333332
+end subroutine settypeinfo

Added: trunk/numpy/f2py/lib/src/F_FUNC.cpp
===================================================================
--- trunk/numpy/f2py/lib/src/F_FUNC.cpp	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/src/F_FUNC.cpp	2006-09-16 05:56:18 UTC (rev 3170)
@@ -0,0 +1,34 @@
+#if defined(PREPEND_FORTRAN)
+#if defined(NO_APPEND_FORTRAN)
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) _##F
+#else
+#define F_FUNC(f,F) _##f
+#endif
+#else
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) _##F##_
+#else
+#define F_FUNC(f,F) _##f##_
+#endif
+#endif
+#else
+#if defined(NO_APPEND_FORTRAN)
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) F
+#else
+#define F_FUNC(f,F) f
+#endif
+#else
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) F##_
+#else
+#define F_FUNC(f,F) f##_
+#endif
+#endif
+#endif
+#if defined(UNDERSCORE_G77)
+#define F_FUNC_US(f,F) F_FUNC(f##_,F##_)
+#else
+#define F_FUNC_US(f,F) F_FUNC(f,F)
+#endif

Added: trunk/numpy/f2py/lib/src/pyobj_to_Py_complex.c
===================================================================
--- trunk/numpy/f2py/lib/src/pyobj_to_Py_complex.c	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/src/pyobj_to_Py_complex.c	2006-09-16 05:56:18 UTC (rev 3170)
@@ -0,0 +1,39 @@
+int pyobj_to_Py_complex(PyObject* obj, Py_complex* value) {
+  if (PyComplex_Check(obj)) {
+    *value =PyComplex_AsCComplex(obj);
+    return 1;
+  }
+  /* Python does not provide PyNumber_Complex function :-( */
+  (*value).imag=0.0;
+  if (PyFloat_Check(obj)) {
+#ifdef __sgi
+    (*value).real = PyFloat_AsDouble(obj);
+    return (!PyErr_Occurred());
+#else
+    (*value).real = PyFloat_AS_DOUBLE(obj);
+    return 1;
+#endif
+  }
+  if (PyInt_Check(obj)) {
+    (*value).real = (double)PyInt_AS_LONG(obj);
+    return 1;
+  }
+  if (PyLong_Check(obj)) {
+    (*value).real = PyLong_AsDouble(obj);
+    return (!PyErr_Occurred());
+  }
+  if (PySequence_Check(obj) && (!PyString_Check(obj))) {
+    PyObject *tmp = PySequence_GetItem(obj,0);
+    if (tmp) {
+      if (pyobj_to_Py_complex(tmp,value)) {
+        Py_DECREF(tmp);
+        return 1;
+      }
+      Py_DECREF(tmp);
+    }
+  }
+  if (!PyErr_Occurred()) {
+    PyErr_SetString(PyExc_TypeError, "Failed to convert python object to C Py_complex.");
+  }
+  return 0;
+}

Added: trunk/numpy/f2py/lib/src/pyobj_to_double.c
===================================================================
--- trunk/numpy/f2py/lib/src/pyobj_to_double.c	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/src/pyobj_to_double.c	2006-09-16 05:56:18 UTC (rev 3170)
@@ -0,0 +1,39 @@
+int pyobj_to_double(PyObject* obj, double* value) {
+  PyObject* tmp = NULL;
+  if (PyFloat_Check(obj)) {
+#ifdef __sgi
+    *value = PyFloat_AsDouble(obj);
+    return (!PyErr_Occurred());
+#else
+    *value = PyFloat_AS_DOUBLE(obj);
+    return 1;
+#endif
+  }
+  tmp = PyNumber_Float(obj);
+  if (tmp) {
+#ifdef __sgi
+    *value = PyFloat_AsDouble(tmp);
+    Py_DECREF(tmp);
+    return (!PyErr_Occurred());
+#else
+    *value = PyFloat_AS_DOUBLE(tmp);
+    Py_DECREF(tmp);
+    return 1;
+#endif
+  }
+  if (PyComplex_Check(obj))
+    tmp = PyObject_GetAttrString(obj,"real");
+  else if (PyString_Check(obj))
+    /*pass*/;
+  else if (PySequence_Check(obj))
+    tmp = PySequence_GetItem(obj,0);
+  if (tmp) {
+    PyErr_Clear();
+    if (pyobj_to_double(tmp, value)) {Py_DECREF(tmp); return 1;}
+    Py_DECREF(tmp);
+  }
+  if (!PyErr_Occurred()) {
+    PyErr_SetString(PyExc_TypeError, "Failed to convert python object to C double.");
+  }
+  return 0;
+}

Added: trunk/numpy/f2py/lib/src/pyobj_to_long.c
===================================================================
--- trunk/numpy/f2py/lib/src/pyobj_to_long.c	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/src/pyobj_to_long.c	2006-09-16 05:56:18 UTC (rev 3170)
@@ -0,0 +1,31 @@
+int pyobj_to_long(PyObject *obj, long* value) {
+  PyObject* tmp = NULL;
+  if (PyInt_Check(obj)) {
+    *value = PyInt_AS_LONG(obj);
+    return 1;
+  }
+  tmp = PyNumber_Int(obj);
+  if (tmp) {
+    *value = PyInt_AS_LONG(tmp);
+    Py_DECREF(tmp);
+    return 1;
+  }
+  if (PyComplex_Check(obj))
+    tmp = PyObject_GetAttrString(obj,"real");
+  else if (PyString_Check(obj))
+    /*pass*/;
+  else if (PySequence_Check(obj))
+    tmp = PySequence_GetItem(obj,0);
+  if (tmp) {
+    PyErr_Clear();
+    if (pyobj_to_long(tmp, value)) {
+      Py_DECREF(tmp);
+      return 1;
+    }
+    Py_DECREF(tmp);
+  }
+  if (!PyErr_Occurred()) {
+    PyErr_SetString(PyExc_TypeError, "Failed to convert python object to C long.");
+  }
+  return 0;
+}

Added: trunk/numpy/f2py/lib/src/pyobj_to_npy_longlong.c
===================================================================
--- trunk/numpy/f2py/lib/src/pyobj_to_npy_longlong.c	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/src/pyobj_to_npy_longlong.c	2006-09-16 05:56:18 UTC (rev 3170)
@@ -0,0 +1,36 @@
+int pyobj_to_npy_longlong(PyObject *obj, npy_longlong* value) {
+  PyObject* tmp = NULL;
+  if (PyLong_Check(obj)) {
+    *value = PyLong_AsLongLong(obj);
+    return (!PyErr_Occurred());
+  }
+  if (PyInt_Check(obj)) {
+    *value = (npy_longlong)PyInt_AS_LONG(obj);
+    return 1;
+  }
+  tmp = PyNumber_Long(obj);
+  if (tmp) {
+    *value = PyLong_AsLongLong(tmp);
+    Py_DECREF(tmp);
+    return (!PyErr_Occurred());
+  }
+  if (PyComplex_Check(obj))
+    tmp = PyObject_GetAttrString(obj,"real");
+  else if (PyString_Check(obj))
+    /*pass*/;
+  else if (PySequence_Check(obj))
+    tmp = PySequence_GetItem(obj,0);
+  if (tmp) {
+    PyErr_Clear();
+    if (pyobj_to_npy_longlong(tmp, value)) {
+      Py_DECREF(tmp);
+      return 1;
+    }
+    Py_DECREF(tmp);
+  }
+  if (!PyErr_Occurred()) {
+    PyErr_SetString(PyExc_TypeError, "Failed to convert python object to C npy_longlong.");
+  }
+  return 0;
+}
+

Added: trunk/numpy/f2py/lib/src/pyobj_to_string_len.c
===================================================================
--- trunk/numpy/f2py/lib/src/pyobj_to_string_len.c	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/src/pyobj_to_string_len.c	2006-09-16 05:56:18 UTC (rev 3170)
@@ -0,0 +1,10 @@
+int pyobj_to_string_len(PyObject* obj, f2py_string* value, size_t length) {
+  if (PyString_Check(obj)) {
+    if (strncpy((char*)value,PyString_AS_STRING(obj), length))
+      return 1;
+  }
+  if (!PyErr_Occurred()) {
+    PyErr_SetString(PyExc_TypeError, "Failed to convert python object to C f2py_string.");
+  }
+  return 0;
+}

Modified: trunk/numpy/f2py/lib/statements.py
===================================================================
--- trunk/numpy/f2py/lib/statements.py	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/statements.py	2006-09-16 05:56:18 UTC (rev 3170)
@@ -52,6 +52,7 @@
 
     match = re.compile(r'\w[^=]*\s*=\>?').match
     item_re = re.compile(r'(?P<variable>\w[^=]*)\s*(?P<sign>=\>?)\s*(?P<expr>.*)\Z',re.I).match
+    _repr_attr_names = ['variable','sign','expr'] + Statement._repr_attr_names
 
     def process_item(self):
         m = self.item_re(self.item.get_line())
@@ -525,6 +526,7 @@
     def analyze(self):
         module_procedures = self.parent.a.module_procedures
         module_procedures.extend(self.items)
+        # XXX: add names to parent_provides
         return
 
 class Access(Statement):
@@ -560,7 +562,7 @@
                 var = self.get_variable(name)
                 var.update(clsname)
         else:
-            self.parent.a.attributes.append(clsname)
+            self.parent.update_attributes(clsname)
         return
 
 class Public(Access):
@@ -847,8 +849,11 @@
         return tab + s
 
     def analyze(self):
+        use = self.parent.a.use
+        if use.has_key(self.name):
+            return
+
         modules = self.top.a.module
-
         if not modules.has_key(self.name):
             fn = None
             for d in self.reader.include_dirs:
@@ -867,9 +872,10 @@
                 modules.update(parser.block.a.module)
 
         if not modules.has_key(self.name):
-            self.warning('no information about the use module %r' % (self.name))
+            self.warning('no information about the module %r in use statement' % (self.name))
             return
 
+        module = modules[self.name]
         use_provides = self.parent.a.use_provides
         
         
@@ -1111,7 +1117,7 @@
         return
     def __str__(self): return self.get_indent_tab() + 'SEQUENCE'
     def analyze(self):
-        self.parent.a.attributes.append('SEQUENCE')
+        self.parent.update_attributes('SEQUENCE')
         return
 
 class External(StatementWithNamelist):
@@ -1218,6 +1224,7 @@
                 var = self.get_variable(name)
                 if shape is not None:
                     var.set_bounds(shape)
+            # XXX: add name,var to parent_provides
         return
 
 class Optional(StatementWithNamelist):

Modified: trunk/numpy/f2py/lib/typedecl_statements.py
===================================================================
--- trunk/numpy/f2py/lib/typedecl_statements.py	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/typedecl_statements.py	2006-09-16 05:56:18 UTC (rev 3170)
@@ -1,9 +1,14 @@
 
+__all__ = ['Integer', 'Real', 'DoublePrecision', 'Complex', 'DoubleComplex',
+           'Character', 'Logical', 'Byte', 'TypeStmt','Class',
+           'intrinsic_type_spec', 'declaration_type_spec',
+           'Implicit']
+
 import re
 import string
 from base_classes import Statement, BeginStatement, EndStatement,\
      AttributeHolder, Variable
-from utils import split_comma, AnalyzeError, name_re, is_entity_decl
+from utils import split_comma, AnalyzeError, name_re, is_entity_decl, is_name, CHAR_BIT
 
 # Intrinsic type specification statements
 
@@ -27,6 +32,10 @@
                             | LOGICAL [<kind-selector>]
 
     <kind-selector> = ( [ KIND = ] <scalar-int-initialization-expr> )
+    EXTENSION:
+      <kind-selector> = ( [ KIND = ] <scalar-int-initialization-expr> )
+                        | * <length>
+    
     <char-selector> = <length-selector>
                       | ( LEN = <type-param-value>, KIND = <scalar-int-initialization-expr> )
                       | ( <type-param-value>, [ KIND = ] <scalar-int-initialization-expr> )
@@ -61,6 +70,7 @@
     <digit-string> = <digit> [ <digit> ]..
     <kind-param> = <digit-string> | <scalar-int-constant-name>
     """
+    _repr_attr_names = ['selector','attrspec','entity_decls'] + Statement._repr_attr_names
 
     def process_item(self):
         item = self.item
@@ -146,13 +156,19 @@
             assert self.parent.typedecl is None,`self.parent.typedecl`
             self.parent.typedecl = self
             self.ignore = True
+        if isinstance(self, Type):
+            self.name = self.selector[1].lower()
+            assert is_name(self.name),`self.name`
+        else:
+            self.name = clsname
         return
 
     def _parse_kind_selector(self, selector):
         if not selector:
-            return ''
+            return '',''
+        length,kind = '',''
         if selector.startswith('*'):
-            kind = selector[1:].lstrip()
+            length = selector[1:].lstrip()
         else:
             assert selector[0]+selector[-1]=='()',`selector`
             l = selector[1:-1].strip()
@@ -162,7 +178,7 @@
                 kind = l[1:].lstrip()
             else:
                 kind = l
-        return kind
+        return length,kind
 
     def _parse_char_selector(self, selector):
         if not selector:
@@ -213,8 +229,8 @@
     def tostr(self):
         clsname = self.__class__.__name__.upper()
         s = ''
+        length, kind = self.selector
         if isinstance(self, Character):
-            length, kind = self.selector
             if length and kind:
                 s += '(LEN=%s, KIND=%s)' % (length,kind)
             elif length:
@@ -222,9 +238,14 @@
             elif kind:
                 s += '(KIND=%s)' % (kind)
         else:
-            kind = self.selector
-            if kind:
-                s += '(KIND=%s)' % (kind)
+            if isinstance(self, Type):
+                s += '(%s)' % (kind)
+            else:
+                if length:
+                    s += '*%s' % (length)
+                if kind:
+                    s += '(KIND=%s)' % (kind)
+                
         return clsname + s
 
     def __str__(self):
@@ -244,7 +265,9 @@
         return self.selector==other.selector
 
     def astypedecl(self):
-        return self.__class__(self.parent, self.item.copy(self.tostr()))
+        if self.entity_decls or self.attrspec:
+            return self.__class__(self.parent, self.item.copy(self.tostr()))
+        return self
 
     def analyze(self):
         if not self.entity_decls:
@@ -253,11 +276,8 @@
         typedecl = self.astypedecl()
         for item in self.entity_decls:
             name, array_spec, char_length, value = self._parse_entity(item)
-            if not variables.has_key(name):
-                variables[name] = var = Variable(self, name)
-            else:
-                var = variables[name]
-                var.add_parent(self)
+            var = self.parent.get_variable(name)
+            var.add_parent(self)
             if char_length:
                 var.set_length(char_length)
             else:
@@ -267,6 +287,7 @@
                 var.set_bounds(array_spec)
             if value:
                 var.set_init(value)
+            var.analyze()
         return
 
     def _parse_entity(self, line):
@@ -296,34 +317,170 @@
             value = item.apply_map(line[1:].lstrip())
         return name, array_spec, char_length, value
 
+    def get_zero_value(self):
+        raise NotImplementedError,`self.__class__.__name__`
+
+    def assign_expression(self, name, value):
+        return '%s = %s' % (name, value)
+
+    def get_kind(self):
+        return self.selector[1] or self.default_kind
+
+    def get_length(self):
+        return self.selector[0] or 1
+
+    def get_bit_size(self):
+        return CHAR_BIT * int(self.get_kind())
+
+    def get_byte_size(self):
+        return self.get_bit_size() / CHAR_BIT
+
+    def is_intrinsic(self): return not isinstance(self,(Type,Class))
+    def is_derived(self): return isinstance(self,Type)
+
+    def is_numeric(self): return isinstance(self,(Integer,Real, DoublePrecision,Complex,DoubleComplex,Byte))
+    def is_nonnumeric(self): return isinstance(self,(Character,Logical))
+
+
 class Integer(TypeDeclarationStatement):
     match = re.compile(r'integer\b',re.I).match
+    default_kind = 4
 
+    def get_c_type(self):
+        return 'npy_int%s' % (self.get_bit_size())
+
+    def get_zero_value(self):
+        kind = self.get_kind()
+        if kind==self.default_kind: return '0'
+        return '0_%s' % (kind)
+
 class Real(TypeDeclarationStatement):
     match = re.compile(r'real\b',re.I).match
+    default_kind = 4
 
+    def get_c_type(self):
+        return 'npy_float%s' % (self.get_bit_size())
+
+    def get_zero_value(self):
+        kind = self.get_kind()
+        if kind==self.default_kind: return '0.0'
+        return '0_%s' % (kind)
+
 class DoublePrecision(TypeDeclarationStatement):
     match = re.compile(r'double\s*precision\b',re.I).match
+    default_kind = 8
+    
+    def get_zero_value(self):
+        return '0.0D0'
 
+    def get_c_type(self):
+        return 'npy_float%s' % (self.get_bit_size())
+
 class Complex(TypeDeclarationStatement):
     match = re.compile(r'complex\b',re.I).match
+    default_kind = 4
 
+    def get_kind(self):
+        length, kind = self.selector
+        if kind:
+            return kind
+        if length:
+            return int(length)/2
+        return self.default_kind
+
+    def get_length(self):
+        return 2 * int(self.get_kind())
+
+    def get_bit_size(self):
+        return CHAR_BIT * self.get_length()
+
+    def get_zero_value(self):
+        kind = self.get_kind()
+        if kind==self.default_kind: return '(0.0, 0.0)'
+        return '(0.0_%s, 0.0_%s)' % (kind, kind)
+
+    def get_c_type(self):
+        return 'npy_complex%s' % (self.get_bit_size())
+
 class DoubleComplex(TypeDeclarationStatement):
     # not in standard
     match = re.compile(r'double\s*complex\b',re.I).match
+    default_kind = 8
 
+    def get_kind(self): return self.default_kind
+    def get_length(self): return 2 * self.get_kind()
+    def get_bit_size(self):
+        return CHAR_BIT * self.get_length()
+
+    def get_zero_value(self):
+        return '(0.0D0,0.0D0)'
+
+    def get_c_type(self):
+        return 'npy_complex%s' % (self.get_bit_size())
+
 class Logical(TypeDeclarationStatement):
     match = re.compile(r'logical\b',re.I).match
+    default_kind = 4
 
+    def get_zero_value(self):
+        return ".FALSE."
+
+    def get_c_type(self):
+        return 'npy_int%s' % (self.get_bit_size())
+
 class Character(TypeDeclarationStatement):
     match = re.compile(r'character\b',re.I).match
+    default_kind = 1
 
+    def get_bit_size(self):
+        return CHAR_BIT * int(self.get_length()) * int(self.get_kind())
+
+    def get_c_type(self):
+        return 'f2py_string%s' % (self.get_bit_size())
+
+    def get_zero_value(self):
+        return "''"
+
 class Byte(TypeDeclarationStatement):
     # not in standard
     match = re.compile(r'byte\b',re.I).match
+    default_kind = 1
 
+    def get_zero_value(self):
+        return '0'
+
+    def get_c_type(self):
+        return 'npy_int%s' % (self.get_bit_size())
+
 class Type(TypeDeclarationStatement):
     match = re.compile(r'type\s*\(', re.I).match
+
+    def get_zero_value(self):
+        kind = self.selector
+        assert is_name(kind),`kind`
+        type_decl = self.get_type_decl(kind)
+        component_names = type_decl.a.component_names
+        components = type_decl.a.components
+        l = []
+        for name in component_names:
+            var = components[name]
+            l.append(var.typedecl.get_zero_value())
+        return '%s(%s)' % (type_decl.name, ', '.join(l))
+
+    def get_kind(self):
+        # See 4.5.2, page 48
+        raise NotImplementedError,`self.__class__.__name__`
+
+    def get_bit_size(self):
+        type_decl = self.get_type_decl(self.name)
+        s = 0
+        for name,var in type_decl.a.components.items():
+            s += var.get_bit_size()
+        return s
+
+    def get_c_type(self):
+        return 'f2py_type_%s_%s' % (self.name, self.get_bit_size())
+    
 TypeStmt = Type
 
 class Class(TypeDeclarationStatement):

Modified: trunk/numpy/f2py/lib/utils.py
===================================================================
--- trunk/numpy/f2py/lib/utils.py	2006-09-16 02:08:59 UTC (rev 3169)
+++ trunk/numpy/f2py/lib/utils.py	2006-09-16 05:56:18 UTC (rev 3170)
@@ -74,6 +74,8 @@
     return name, line[i+1:].lstrip()
 
 def filter_stmts(content, classes):
+    """ Pop and return classes instances from content.
+    """
     stmts = []
     indices = []
     for i in range(len(content)):
@@ -123,3 +125,30 @@
                 return fn
         f.close()
     return
+
+def str2stmt(string, isfree=True, isstrict=False):
+    """ Convert Fortran code to Statement tree.
+    """
+    from readfortran import Line, FortranStringReader
+    from parsefortran import FortranParser
+    reader = FortranStringReader(string, isfree, isstrict)
+    parser = FortranParser(reader)
+    parser.parse()
+    parser.analyze()
+    block = parser.block
+    while len(block.content)==1:
+        block = block.content[0]
+    return block
+
+def get_char_bit():
+    import numpy
+    one = numpy.ubyte(1)
+    two = numpy.ubyte(2)
+    n = numpy.ubyte(2)
+    i = 1
+    while n>=two:
+        n <<= one
+        i += 1
+    return i
+
+CHAR_BIT = get_char_bit()




More information about the Numpy-svn mailing list