#!/usr/bin/env python
"""

Build common block mechanism for f2py2e.

Copyright 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
"""

__version__ = "$Revision: 1.19 $"[10:-1]

from . import __version__
f2py_version = __version__.version

import pprint
import sys
errmess=sys.stderr.write
outmess=sys.stdout.write
show=pprint.pprint

from .auxfuncs import *
from . import capi_maps
from . import func2subr
from .crackfortran import rmbadname
##############

def findcommonblocks(block,top=1):
    ret = []
    if hascommon(block):
        for n in list(block['common'].keys()):
            vars={}
            for v in block['common'][n]:
                vars[v]=block['vars'][v]
            ret.append((n,block['common'][n],vars))
    elif hasbody(block):
        for b in block['body']:
            ret=ret+findcommonblocks(b,0)
    if top:
        tret=[]
        names=[]
        for t in ret:
            if t[0] not in names:
                names.append(t[0])
                tret.append(t)
        return tret
    return ret

def buildhooks(m):
    ret = {'commonhooks':[],'initcommonhooks':[],'docs':['"COMMON blocks:\\n"']}
    fwrap = ['']
    def fadd(line,s=fwrap): s[0] = '%s\n      %s'%(s[0],line)
    chooks = ['']
    def cadd(line,s=chooks): s[0] = '%s\n%s'%(s[0],line)
    ihooks = ['']
    def iadd(line,s=ihooks): s[0] = '%s\n%s'%(s[0],line)
    doc = ['']
    def dadd(line,s=doc): s[0] = '%s\n%s'%(s[0],line)
    for (name,vnames,vars) in findcommonblocks(m):
        lower_name = name.lower()
        hnames,inames = [],[]
        for n in vnames:
            if isintent_hide(vars[n]): hnames.append(n)
            else: inames.append(n)
        if hnames:
            outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t  %s\n\t\t  Hidden: %s\n'%(name,','.join(inames),','.join(hnames)))
        else:
            outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t  %s\n'%(name,','.join(inames)))
        fadd('subroutine f2pyinit%s(setupfunc)'%name)
        fadd('external setupfunc')
        for n in vnames:
            fadd(func2subr.var2fixfortran(vars,n))
        if name=='_BLNK_':
            fadd('common %s'%(','.join(vnames)))
        else:
            fadd('common /%s/ %s'%(name,','.join(vnames)))
        fadd('call setupfunc(%s)'%(','.join(inames)))
        fadd('end\n')
        cadd('static FortranDataDef f2py_%s_def[] = {'%(name))
        idims=[]
        for n in inames:
            ct = capi_maps.getctype(vars[n])
            at = capi_maps.c2capi_map[ct]
            dm = capi_maps.getarrdims(n,vars[n])
            if dm['dims']: idims.append('(%s)'%(dm['dims']))
            else: idims.append('')
            dms=dm['dims'].strip()
            if not dms: dms='-1'
            cadd('\t{\"%s\",%s,{{%s}},%s},'%(n,dm['rank'],dms,at))
        cadd('\t{NULL}\n};')
        inames1 = rmbadname(inames)
        inames1_tps = ','.join(['char *'+s for s in inames1])
        cadd('static void f2py_setup_%s(%s) {'%(name,inames1_tps))
        cadd('\tint i_f2py=0;')
        for n in inames1:
            cadd('\tf2py_%s_def[i_f2py++].data = %s;'%(name,n))
        cadd('}')
        if '_' in lower_name:
            F_FUNC='F_FUNC_US'
        else:
            F_FUNC='F_FUNC'
        cadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void(*)(%s));'\
             %(F_FUNC,lower_name,name.upper(),
               ','.join(['char*']*len(inames1))))
        cadd('static void f2py_init_%s(void) {'%name)
        cadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);'\
             %(F_FUNC,lower_name,name.upper(),name))
        cadd('}\n')
        iadd('\tF2PyDict_SetItemString(d, \"%s\", PyFortranObject_New(f2py_%s_def,f2py_init_%s));'%(name,name,name))
        tname = name.replace('_','\\_')
        dadd('\\subsection{Common block \\texttt{%s}}\n'%(tname))
        dadd('\\begin{description}')
        for n in inames:
            dadd('\\item[]{{}\\verb@%s@{}}'%(capi_maps.getarrdocsign(n,vars[n])))
            if hasnote(vars[n]):
                note = vars[n]['note']
                if type(note) is type([]): note='\n'.join(note)
                dadd('--- %s'%(note))
        dadd('\\end{description}')
        ret['docs'].append('"\t/%s/ %s\\n"'%(name,','.join(map(lambda v,d:v+d,inames,idims))))
    ret['commonhooks']=chooks
    ret['initcommonhooks']=ihooks
    ret['latexdoc']=doc[0]
    if len(ret['docs'])<=1: ret['docs']=''
    return ret,fwrap[0]
