Salome HOME
CCAR: merge de la version de developpement V1_12a2 dans la branche principale
[tools/eficas.git] / Noyau / nommage.py
1 #@ MODIF nommage Noyau  DATE 16/05/2007   AUTEUR COURTOIS M.COURTOIS 
2 # -*- coding: iso-8859-1 -*-
3 #            CONFIGURATION MANAGEMENT OF EDF VERSION
4 # ======================================================================
5 # COPYRIGHT (C) 1991 - 2002  EDF R&D                  WWW.CODE-ASTER.ORG
6 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
7 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
8 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR   
9 # (AT YOUR OPTION) ANY LATER VERSION.                                 
10 #
11 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT 
12 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF          
13 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU    
14 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.                            
15 #
16 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE   
17 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,       
18 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.      
19 #                                                                       
20 #                                                                       
21 # ======================================================================
22
23
24 """
25    Ce module sert à nommer les concepts produits par les commandes.
26    Le nom du concept est obtenu en appelant la fonction GetNomConceptResultat
27    du module avec le nom de la commande en argument.
28    
29    Cette fonction parcourt le source dans lequel la commande se trouve, parse le
30    fichier et retrouve le nom du concept qui se trouve à gauche du signe = précédant
31    le nom de la commande.
32
33    Cette fonction utilise la fonction cur_frame du module N_utils qui retourne la frame
34    d'exécution Python située 2 niveaux au-dessus. C'est à partir de cette frame que
35    l'on retrouve le fichier source et le numéro de ligne où se trouve l'appel à la commande.
36
37 """
38
39 # Modules Python
40 import re,string
41 import linecache
42
43 # Modules EFICAS
44 import N_utils
45
46 regex1='=?\s*%s\s*\('
47 #commentaire standard precede d'un nombre quelconque de blancs (pas multiligne)
48 pattern_comment   = re.compile(r"^\s*#.*")
49
50 def GetNomConceptResultat(ope):
51   """
52      Cette fonction recherche dans la pile des appels, l'appel à la commande
53      qui doit etre situé à 2 niveaux au-dessus (cur_frame(2)).
54      On retrouve d'abord la frame d'exécution f. Puis le numéro de la ligne
55      dans le source f.f_lineno et le nom du fichier source (f.f_code.co_filename).
56      A partir de là, on récupère la ligne de source avec linecache.getline
57      et on vérifie que cette ligne correspond véritablement à l'appel.
58
59      En effet, lorsque les commandes tiennent sur plusieurs lignes, on retrouve
60      la dernière ligne. Il faut donc remonter dans le source jusqu'à la première 
61      ligne.
62
63      Enfin la fonction evalnom forme un nom acceptable lorsque le concept est un
64      élément d'une liste, par exemple.
65
66   """
67   f=N_utils.cur_frame(2)
68   lineno = f.f_lineno     # XXX Too bad if -O is used
69   #lineno = f_lineno(f)  # Ne marche pas toujours
70   co = f.f_code
71   filename = co.co_filename
72   name = co.co_name
73   #print "NOMOP,FICHIER, LIGNE ",ope,filename,lineno
74   #pattern pour identifier le debut de la commande
75   pattern_oper=re.compile(regex1 % ope)
76
77   list=[]
78   while lineno > 0:
79     line = linecache.getline(filename, lineno)
80     lineno=lineno-1
81     if pattern_comment.match(line):continue
82     #print "LIGNE ",line
83     list.append(line)
84     if pattern_oper.search(line):
85       l=pattern_oper.split(line)
86       list.reverse()
87       #print "COMMANDE ",string.join(list)
88       #print "SPLIT ",l
89       # On suppose que le concept resultat a bien ete
90       # isole en tete de la ligne de source
91       m=evalnom(string.strip(l[0]),f.f_locals)
92       #print "NOMS ",m
93       if m!=[] :  return m[-1]
94       else : return ''
95   #print "appel inconnu"
96   return ""
97
98 def evalnom(text,d):
99   """
100    Retourne un nom pour le concept resultat identifie par text
101    Pour obtenir ce nom il y a plusieurs possibilites :
102     1. text est un identificateur python c'est le nom du concept
103     2. text est un element d'une liste on construit le nom en
104       evaluant la partie indice dans le contexte de l'appelant d
105   """
106   l=re.split('([\[\]]+)',text)
107   #print l
108   if l[-1] == '' :l=l[:-1]
109   lll=[]
110   i=0
111   while i<len(l):
112     s=l[i]
113     ll=string.split(s,',')
114     ll=re.split('[ ,]+',s)
115     if ll[0] == '' :ll=ll[1:]
116     if len(ll) == 1:
117       id0=ll[0]
118     else:
119       lll=lll+ll[0:-1]
120       id0=ll[-1]
121     if i+1<len(l) and l[i+1] == '[': # le nom est suivi d un subscript
122       sub=l[i+2]
123       nom=id0+'_'+str(eval(sub,d))
124       i=i+4
125     else:
126       nom=id0
127       i=i+1
128     lll.append(nom)
129   return lll
130
131 def f_lineno(f):
132    """
133       Calcule le numero de ligne courant
134       Devrait marcher meme avec -O
135       Semble ne pas marcher en présence de tuples longs
136    """
137    c=f.f_code
138    if not hasattr(c, 'co_lnotab'):return f.f_lineno
139    tab=c.co_lnotab
140    line = c.co_firstlineno
141    stopat = f.f_lasti
142    addr = 0
143    for i in range(0, len(tab), 2):
144        addr = addr + ord(tab[i])
145        if addr > stopat:
146            break
147        line = line + ord(tab[i+1])
148    return line
149