#!/usr/bin/env python
"""
Copyright 1999,2000 Pearu Peterson all rights reserved,
Pearu Peterson <pearu@ioc.ee>
Permission to use, modify, and distribute this software is given under the
terms of the NumPy License.
NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
$Date: 2005/05/06 10:57:33 $
Pearu Peterson
"""
from __future__ import division, absolute_import, print_function
__version__ = "$Revision: 1.60 $"[10:-1]
from . import __version__
f2py_version = __version__.version
import copy
import re
import os
import sys
from .crackfortran import markoutercomma
from . import cb_rules
# The eviroment provided by auxfuncs.py is needed for some calls to eval.
# As the needed functions cannot be determined by static inspection of the
# code, it is safest to use import * pending a major refactoring of f2py.
from .auxfuncs import *
__all__ = [
'getctype', 'getstrlength', 'getarrdims', 'getpydocsign',
'getarrdocsign', 'getinit', 'sign2map', 'routsign2map', 'modsign2map',
'cb_sign2map', 'cb_routsign2map', 'common_sign2map'
]
# Numarray and Numeric users should set this False
using_newcore = True
depargs = []
lcb_map = {}
lcb2_map = {}
# forced casting: mainly caused by the fact that Python or Numeric
# C/APIs do not support the corresponding C types.
c2py_map = {'double': 'float',
'float': 'float', # forced casting
'long_double': 'float', # forced casting
'char': 'int', # forced casting
'signed_char': 'int', # forced casting
'unsigned_char': 'int', # forced casting
'short': 'int', # forced casting
'unsigned_short': 'int', # forced casting
'int': 'int', # (forced casting)
'long': 'int',
'long_long': 'long',
'unsigned': 'int', # forced casting
'complex_float': 'complex', # forced casting
'complex_double': 'complex',
'complex_long_double': 'complex', # forced casting
'string': 'string',
}
c2capi_map = {'double': 'NPY_DOUBLE',
'float': 'NPY_FLOAT',
'long_double': 'NPY_DOUBLE', # forced casting
'char': 'NPY_STRING',
'unsigned_char': 'NPY_UBYTE',
'signed_char': 'NPY_BYTE',
'short': 'NPY_SHORT',
'unsigned_short': 'NPY_USHORT',
'int': 'NPY_INT',
'unsigned': 'NPY_UINT',
'long': 'NPY_LONG',
'long_long': 'NPY_LONG', # forced casting
'complex_float': 'NPY_CFLOAT',
'complex_double': 'NPY_CDOUBLE',
'complex_long_double': 'NPY_CDOUBLE', # forced casting
'string': 'NPY_STRING'}
# These new maps aren't used anyhere yet, but should be by default
# unless building numeric or numarray extensions.
if using_newcore:
c2capi_map = {'double': 'NPY_DOUBLE',
'float': 'NPY_FLOAT',
'long_double': 'NPY_LONGDOUBLE',
'char': 'NPY_BYTE',
'unsigned_char': 'NPY_UBYTE',
'signed_char': 'NPY_BYTE',
'short': 'NPY_SHORT',
'unsigned_short': 'NPY_USHORT',
'int': 'NPY_INT',
'unsigned': 'NPY_UINT',
'long': 'NPY_LONG',
'unsigned_long': 'NPY_ULONG',
'long_long': 'NPY_LONGLONG',
'unsigned_long_long': 'NPY_ULONGLONG',
'complex_float': 'NPY_CFLOAT',
'complex_double': 'NPY_CDOUBLE',
'complex_long_double': 'NPY_CDOUBLE',
'string':'NPY_STRING'
}
c2pycode_map = {'double': 'd',
'float': 'f',
'long_double': 'd', # forced casting
'char': '1',
'signed_char': '1',
'unsigned_char': 'b',
'short': 's',
'unsigned_short': 'w',
'int': 'i',
'unsigned': 'u',
'long': 'l',
'long_long': 'L',
'complex_float': 'F',
'complex_double': 'D',
'complex_long_double': 'D', # forced casting
'string': 'c'
}
if using_newcore:
c2pycode_map = {'double': 'd',
'float': 'f',
'long_double': 'g',
'char': 'b',
'unsigned_char': 'B',
'signed_char': 'b',
'short': 'h',
'unsigned_short': 'H',
'int': 'i',
'unsigned': 'I',
'long': 'l',
'unsigned_long': 'L',
'long_long': 'q',
'unsigned_long_long': 'Q',
'complex_float': 'F',
'complex_double': 'D',
'complex_long_double': 'G',
'string': 'S'}
c2buildvalue_map = {'double': 'd',
'float': 'f',
'char': 'b',
'signed_char': 'b',
'short': 'h',
'int': 'i',
'long': 'l',
'long_long': 'L',
'complex_float': 'N',
'complex_double': 'N',
'complex_long_double': 'N',
'string': 'z'}
if sys.version_info[0] >= 3:
# Bytes, not Unicode strings
c2buildvalue_map['string'] = 'y'
if using_newcore:
# c2buildvalue_map=???
pass
f2cmap_all = {'real': {'': 'float', '4': 'float', '8': 'double',
'12': 'long_double', '16': 'long_double'},
'integer': {'': 'int', '1': 'signed_char', '2': 'short',
'4': 'int', '8': 'long_long',
'-1': 'unsigned_char', '-2': 'unsigned_short',
'-4': 'unsigned', '-8': 'unsigned_long_long'},
'complex': {'': 'complex_float', '8': 'complex_float',
'16': 'complex_double', '24': 'complex_long_double',
'32': 'complex_long_double'},
'complexkind': {'': 'complex_float', '4': 'complex_float',
'8': 'complex_double', '12': 'complex_long_double',
'16': 'complex_long_double'},
'logical': {'': 'int', '1': 'char', '2': 'short', '4': 'int',
'8': 'long_long'},
'double complex': {'': 'complex_double'},
'double precision': {'': 'double'},
'byte': {'': 'char'},
'character': {'': 'string'}
}
if os.path.isfile('.f2py_f2cmap'):
# User defined additions to f2cmap_all.
# .f2py_f2cmap must contain a dictionary of dictionaries, only. For
# example, {'real':{'low':'float'}} means that Fortran 'real(low)' is
# interpreted as C 'float'. This feature is useful for F90/95 users if
# they use PARAMETERSs in type specifications.
try:
outmess('Reading .f2py_f2cmap ...\n')
f = open('.f2py_f2cmap', 'r')
d = eval(f.read(), {}, {})
f.close()
for k, d1 in list(d.items()):
for k1 in list(d1.keys()):
d1[k1.lower()] = d1[k1]
d[k.lower()] = d[k]
for k in list(d.keys()):
if k not in f2cmap_all:
f2cmap_all[k] = {}
for k1 in list(d[k].keys()):
if d[k][k1] in c2py_map:
if k1 in f2cmap_all[k]:
outmess(
"\tWarning: redefinition of {'%s':{'%s':'%s'->'%s'}}\n" % (k, k1, f2cmap_all[k][k1], d[k][k1]))
f2cmap_all[k][k1] = d[k][k1]
outmess('\tMapping "%s(kind=%s)" to "%s"\n' %
(k, k1, d[k][k1]))
else:
errmess("\tIgnoring map {'%s':{'%s':'%s'}}: '%s' must be in %s\n" % (
k, k1, d[k][k1], d[k][k1], list(c2py_map.keys())))
outmess('Successfully applied user defined changes from .f2py_f2cmap\n')
except Exception as msg:
errmess(
'Failed to apply user defined changes from .f2py_f2cmap: %s. Skipping.\n' % (msg))
cformat_map = {'double': '%g',
'float': '%g',
'long_double': '%Lg',
'char': '%d',
'signed_char': '%d',
'unsigned_char': '%hhu',
'short': '%hd',
'unsigned_short': '%hu',
'int': '%d',
'unsigned': '%u',
'long': '%ld',
'unsigned_long': '%lu',
'long_long': '%ld',
'complex_float': '(%g,%g)',
'complex_double': '(%g,%g)',
'complex_long_double': '(%Lg,%Lg)',
'string': '%s',
}
# Auxiliary functions
def getctype(var):
"""
Determines C type
"""
ctype = 'void'
if isfunction(var):
if 'result' in var:
a = var['result']
else:
a = var['name']
if a in var['vars']:
return getctype(var['vars'][a])
else:
errmess('getctype: function %s has no return value?!\n' % a)
elif issubroutine(var):
return ctype
elif 'typespec' in var and var['typespec'].lower() in f2cmap_all:
typespec = var['typespec'].lower()
f2cmap = f2cmap_all[typespec]
ctype = f2cmap[''] # default type
if 'kindselector' in var:
if '*' in var['kindselector']:
try:
ctype = f2cmap[var['kindselector']['*']]
except KeyError:
errmess('getctype: "%s %s %s" not supported.\n' %
(var['typespec'], '*', var['kindselector']['*']))
elif 'kind' in var['kindselector']:
if typespec + 'kind' in f2cmap_all:
f2cmap = f2cmap_all[typespec + 'kind']
try:
ctype = f2cmap[var['kindselector']['kind']]
except KeyError:
if typespec in f2cmap_all:
f2cmap = f2cmap_all[typespec]
try:
ctype = f2cmap[str(var['kindselector']['kind'])]
except KeyError:
errmess('getctype: "%s(kind=%s)" is mapped to C "%s" (to override define dict(%s = dict(%s="<C typespec>")) in %s/.f2py_f2cmap file).\n'
% (typespec, var['kindselector']['kind'], ctype,
typespec, var['kindselector']['kind'], os.getcwd()))
else:
if not isexternal(var):
errmess(
'getctype: No C-type found in "%s", assuming void.\n' % var)
return ctype
def getstrlength(var):
if isstringfunction(var):
if 'result' in var:
a = var['result']
else:
a = var['name']
if a in var['vars']:
return getstrlength(var['vars'][a])
else:
errmess('getstrlength: function %s has no return value?!\n' % a)
if not isstring(var):
errmess(
'getstrlength: expected a signature of a string but got: %s\n' % (repr(var)))
len = '1'
if 'charselector' in var:
a = var['charselector']
if '*' in a:
len = a['*']
elif 'len' in a:
len = a['len']
if re.match(r'\(\s*([*]|[:])\s*\)', len) or re.match(r'([*]|[:])', len):
if isintent_hide(var):
errmess('getstrlength:intent(hide): expected a string with defined length but got: %s\n' % (
repr(var)))
len = '-1'
return len
def getarrdims(a, var, verbose=0):
global depargs
ret = {}
if isstring(var) and not isarray(var):
ret['dims'] = getstrlength(var)
ret['size'] = ret['dims']
ret['rank'] = '1'
elif isscalar(var):
ret['size'] = '1'
ret['rank'] = '0'
ret['dims'] = ''
elif isarray(var):
dim = copy.copy(var['dimension'])
ret['size'] = '*'.join(dim)
try:
ret['size'] = repr(eval(ret['size']))
except Exception:
pass
ret['dims'] = ','.join(dim)
ret['rank'] = repr(len(dim))
ret['rank*[-1]'] = repr(len(dim) * [-1])[1:-1]
for i in range(len(dim)): # solve dim for dependencies
v = []
if dim[i] in depargs:
v = [dim[i]]
else:
for va in depargs:
if re.match(r'.*?\b%s\b.*' % va, dim[i]):
v.append(va)
for va in v:
if depargs.index(va) > depargs.index(a):
Loading ...