1: /*
2: ================================================================================
3: RPL/2 (R) version 4.1.11
4: Copyright (C) 1989-2012 Dr. BERTRAND Joël
5:
6: This file is part of RPL/2.
7:
8: RPL/2 is free software; you can redistribute it and/or modify it
9: under the terms of the CeCILL V2 License as published by the french
10: CEA, CNRS and INRIA.
11:
12: RPL/2 is distributed in the hope that it will be useful, but WITHOUT
13: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14: FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License
15: for more details.
16:
17: You should have received a copy of the CeCILL License
18: along with RPL/2. If not, write to info@cecill.info.
19: ================================================================================
20: */
21:
22:
23: #include "rpl-conv.h"
24:
25:
26: /*
27: ================================================================================
28: Routine d'ajout d'un bouchon dans la liste des variables statiques
29: ================================================================================
30: Entrée :
31: --------------------------------------------------------------------------------
32: Sortie :
33: --------------------------------------------------------------------------------
34: Effets de bords : néant
35: ================================================================================
36: */
37:
38: // Routine ajoutant à la liste des variables statiques créées un 'bouchon'
39: // qui est un enregistrement dont la variable est NULL. Cela permet
40: // d'effacer les variables statiques créées dans une expression évaluées car,
41: // l'adresse de ces variables changeant à chaque évaluation, elles ne sont
42: // pas utilisables et constituent une fuite de mémoire
43:
44: logical1
45: ajout_bouchon_variable_statique(struct_processus *s_etat_processus)
46: {
47: struct_liste_variables_statiques *l_tete_liste;
48:
49: l_tete_liste = (*s_etat_processus).l_liste_variables_statiques;
50:
51: if (((*s_etat_processus).l_liste_variables_statiques =
52: malloc(sizeof(struct_liste_variables_statiques))) == NULL)
53: {
54: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
55: return(d_erreur);
56: }
57:
58: (*(*s_etat_processus).l_liste_variables_statiques).variable = NULL;
59: (*(*s_etat_processus).l_liste_variables_statiques).suivant = l_tete_liste;
60: (*(*s_etat_processus).l_liste_variables_statiques).precedent = NULL;
61: (*l_tete_liste).precedent = (*s_etat_processus).l_liste_variables_statiques;
62:
63: return(d_absence_erreur);
64: }
65:
66:
67: /*
68: ================================================================================
69: Routine de retrait des variables statiques
70: ================================================================================
71: Entrée :
72: --------------------------------------------------------------------------------
73: Sortie :
74: --------------------------------------------------------------------------------
75: Effets de bords : néant
76: ================================================================================
77: */
78:
79: // Cette routine libère toutes les variables statiques jusqu'au prochain
80: // bouchon ou jusqu'à la fin de la liste si aucun bouchon n'est rencontré.
81:
82: logical1
83: retrait_variables_statiques(struct_processus *s_etat_processus)
84: {
85: unsigned char registre_mode_execution;
86:
87: registre_mode_execution = (*s_etat_processus).mode_execution_programme;
88:
89: while((*s_etat_processus).l_liste_variables_statiques != NULL)
90: {
91: (*s_etat_processus).mode_execution_programme =
92: ((*(*(*s_etat_processus).l_liste_variables_statiques)
93: .variable).origine == 'P') ? 'Y' : 'N';
94:
95: if ((*(*s_etat_processus).l_liste_variables_statiques).variable == NULL)
96: {
97: // On vient de tomber sur un bouchon...
98: (*s_etat_processus).l_liste_variables_statiques =
99: (*(*s_etat_processus).l_liste_variables_statiques).suivant;
100: free((*(*s_etat_processus).l_liste_variables_statiques).precedent);
101: (*(*s_etat_processus).l_liste_variables_statiques).precedent = NULL;
102: break;
103: }
104:
105: if (retrait_variable_statique(s_etat_processus, (*(*(*s_etat_processus)
106: .l_liste_variables_statiques).variable).nom,
107: (*(*(*s_etat_processus).l_liste_variables_statiques).variable)
108: .variable_statique) == d_erreur)
109: {
110: (*s_etat_processus).mode_execution_programme =
111: registre_mode_execution;
112: return(d_erreur);
113: }
114: }
115:
116: (*s_etat_processus).mode_execution_programme = registre_mode_execution;
117: return(d_absence_erreur);
118: }
119:
120:
121: /*
122: ================================================================================
123: Routine de création d'une nouvelle variable statique
124: ================================================================================
125: Entrée :
126: --------------------------------------------------------------------------------
127: Sortie :
128: --------------------------------------------------------------------------------
129: Effets de bords : néant
130: ================================================================================
131: */
132:
133: logical1
134: creation_variable_statique(struct_processus *s_etat_processus,
135: struct_variable_statique *s_variable)
136: {
137: struct_arbre_variables *l_variable_courante;
138:
139: struct_liste_variables_statiques *l_nouvel_element;
140:
141: unsigned char *ptr;
142:
143: // Ajout de la variable en tête de la liste des variables statiques
144:
145: if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
146: == NULL)
147: {
148: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
149: return(d_erreur);
150: }
151:
152: if (((*l_nouvel_element).variable = malloc(sizeof(
153: struct_variable_statique))) == NULL)
154: {
155: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
156: return(d_erreur);
157: }
158:
159: (*(*l_nouvel_element).variable) = (*s_variable);
160: (*l_nouvel_element).suivant = (*s_etat_processus)
161: .l_liste_variables_statiques;
162: (*(*s_etat_processus).l_liste_variables_statiques).precedent
163: = l_nouvel_element;
164: (*l_nouvel_element).precedent = NULL;
165: (*s_etat_processus).l_liste_variables_statiques = l_nouvel_element;
166:
167: // Ajout de la variable à la feuille statique de l'arbre des variables
168:
169: BUG((*s_etat_processus).s_arbre_variables == NULL,
170: uprintf("(*s_etat_processus).s_arbre_variables=NULL\n"));
171:
172: l_variable_courante = (*s_etat_processus).s_arbre_variables;
173: ptr = (*s_variable).nom;
174:
175: while((*ptr) != d_code_fin_chaine)
176: {
177: BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0,
178: uprintf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom,
179: *ptr));
180:
181: // La feuille doit préexister car la variable statique est toujours
182: // créée depuis une variable locale.
183:
184: BUG((*l_variable_courante).noeuds[(*s_etat_processus)
185: .pointeurs_caracteres_variables[*ptr]] == NULL,
186: uprintf("Variable=\"%s\", (*ptr)='%c', nullified folder\n"));
187:
188: l_variable_courante = (*l_variable_courante).noeuds
189: [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]];
190: ptr++;
191: }
192:
193: if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
194: == NULL)
195: {
196: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
197: return(d_erreur);
198: }
199:
200: // Dans la feuille statique de l'arbre des variables, on ne balaie
201: // les variables que dans l'ordre. Le champ 'reference' est alors utilisé
202: // pour sauvegarder une référence vers la liste des variables statiques
203: // pour pouvoir purger l'élément en cas de besoin.
204:
205: (*l_nouvel_element).suivant = (*l_variable_courante).feuille_statique;
206: (*l_nouvel_element).precedent = NULL;
207: (*(*l_nouvel_element).suivant).precedent = l_nouvel_element;
208:
209: (*l_nouvel_element).reference =
210: (*s_etat_processus).l_liste_variables_statiques;
211: (*l_nouvel_element).variable = (*(*s_etat_processus)
212: .l_liste_variables_statiques).variable;
213: (*l_variable_courante).feuille_statique = l_nouvel_element;
214: return(d_absence_erreur);
215: }
216:
217:
218: /*
219: ================================================================================
220: Procédure de retrait d'une variable statique de la base
221: ================================================================================
222: Entrée :
223: --------------------------------------------------------------------------------
224: Sortie :
225: --------------------------------------------------------------------------------
226: Effets de bord : néant
227: ================================================================================
228: */
229:
230: logical1
231: retrait_variable_statique(struct_processus *s_etat_processus,
232: unsigned char *nom_variable, union_position_variable position)
233: {
234: struct_liste_variables_statiques *l_element_a_supprimer;
235: struct_liste_variables_statiques *l_element_liste_a_supprimer;
236:
237: logical1 erreur;
238:
239: if ((l_element_a_supprimer = recherche_variable_statique(s_etat_processus,
240: nom_variable, position, ((*s_etat_processus)
241: .mode_execution_programme == 'Y') ? 'P' : 'E')) != NULL)
242: {
243: // (*s_etat_processus).pointeur_variable_statique_courante
244: // pointe sur la variable à éliminer. Cette variable est celle qui
245: // est présente dans l'une des feuilles statiques de l'arbre des
246: // variables.
247:
248: l_element_liste_a_supprimer = (*l_element_a_supprimer).reference;
249:
250: // Suppression de la liste des variables statiques
251:
252: if ((*l_element_liste_a_supprimer).precedent != NULL)
253: {
254: (*(*l_element_liste_a_supprimer).precedent).suivant =
255: (*l_element_liste_a_supprimer).suivant;
256: }
257: else
258: {
259: (*(*l_element_liste_a_supprimer).suivant).precedent = NULL;
260: }
261:
262: if ((*l_element_liste_a_supprimer).suivant != NULL)
263: {
264: (*(*l_element_liste_a_supprimer).suivant).precedent =
265: (*l_element_liste_a_supprimer).precedent;
266: }
267: else
268: {
269: (*(*l_element_liste_a_supprimer).precedent).suivant = NULL;
270: }
271:
272: free(l_element_liste_a_supprimer);
273:
274: // Suppression depuis la feuille statique. Le champ 'precedent' ne sert
275: // pas car la liste est simplement chaînée.
276:
277: if ((*l_element_a_supprimer).precedent != NULL)
278: {
279: (*(*l_element_a_supprimer).precedent).suivant =
280: (*l_element_a_supprimer).suivant;
281: }
282: else
283: {
284: (*(*l_element_a_supprimer).suivant).precedent = NULL;
285: }
286:
287: if ((*l_element_a_supprimer).suivant != NULL)
288: {
289: (*(*l_element_a_supprimer).suivant).precedent =
290: (*l_element_a_supprimer).precedent;
291: }
292: else
293: {
294: (*(*l_element_a_supprimer).precedent).suivant = NULL;
295: }
296:
297: liberation(s_etat_processus, (*(*l_element_a_supprimer).variable)
298: .objet);
299: free((*(*l_element_a_supprimer).variable).nom);
300: free((*l_element_a_supprimer).variable);
301: free(l_element_a_supprimer);
302:
303: erreur = d_absence_erreur;
304: }
305: else
306: {
307: erreur = d_erreur;
308: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
309: }
310:
311: return erreur;
312: }
313:
314:
315: /*
316: ================================================================================
317: Procédure de recherche d'une variable statique par son nom dans la base
318: ================================================================================
319: Entrée :
320: --------------------------------------------------------------------------------
321: Sortie :
322: --------------------------------------------------------------------------------
323: Effets de bord : néant
324: ================================================================================
325: */
326:
327: struct_liste_variables_statiques *
328: recherche_variable_statique(struct_processus *s_etat_processus,
329: unsigned char *nom_variable, union_position_variable position,
330: unsigned char origine)
331: {
332: int pointeur;
333:
334: struct_arbre_variables *l_variable_courante;
335: struct_liste_variables_statiques *l_element_courant;
336:
337: unsigned char *ptr;
338:
339: l_variable_courante = (*s_etat_processus).s_arbre_variables;
340: ptr = nom_variable;
341:
342: while((*ptr) != d_code_fin_chaine)
343: {
344: pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr];
345:
346: if (pointeur < 0)
347: {
348: // Caractère hors de l'alphabet des variables
349:
350: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
351: return(NULL);
352: }
353:
354: if ((*l_variable_courante).noeuds[pointeur] == NULL)
355: {
356: // Le chemin de la variable candidate n'existe pas.
357: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
358: return(NULL);
359: }
360:
361: l_variable_courante = (*l_variable_courante).noeuds[pointeur];
362: ptr++;
363: }
364:
365: if ((*l_variable_courante).feuille_statique != NULL)
366: {
367: // Il existe au moins une variable statique du nom requis.
368:
369: l_element_courant = (*l_variable_courante).feuille_statique;
370:
371: while(l_element_courant != NULL)
372: {
373: if ((*(*l_element_courant).variable).origine == 'P')
374: {
375: if (((*(*l_element_courant).variable).variable_statique.adresse
376: == position.adresse) &&
377: ((*(*l_element_courant).variable).origine == origine))
378: {
379: (*s_etat_processus).pointeur_variable_statique_courante
380: = (*l_element_courant).variable;
381: return(l_element_courant);
382: }
383: }
384: else
385: {
386: if (((*(*l_element_courant).variable).variable_statique.pointeur
387: == position.pointeur) &&
388: ((*(*l_element_courant).variable).origine == origine))
389: {
390: (*s_etat_processus).pointeur_variable_statique_courante
391: = (*l_element_courant).variable;
392: return(l_element_courant);
393: }
394: }
395: }
396: }
397:
398: (*s_etat_processus).pointeur_variable_statique_courante = NULL;
399: return(NULL);
400: }
401:
402: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>