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 de retrait des variables statiques
29: ================================================================================
30: Entrée :
31: --------------------------------------------------------------------------------
32: Sortie :
33: --------------------------------------------------------------------------------
34: Effets de bords : néant
35: ================================================================================
36: */
37:
38: // Cette routine libère toutes les variables statiques de niveau non
39: // nul, donc attachées à une expression et non un programme.
40:
41: logical1
42: retrait_variables_statiques_locales(struct_processus *s_etat_processus)
43: {
44: struct_liste_variables_statiques *l_element_courant;
45: struct_liste_variables_statiques *l_element_suivant;
46:
47: unsigned char registre_mode_execution;
48:
49: registre_mode_execution = (*s_etat_processus).mode_execution_programme;
50: l_element_courant = (*s_etat_processus).l_liste_variables_statiques;
51:
52: while(l_element_courant != NULL)
53: {
54: l_element_suivant = (*l_element_courant).suivant;
55:
56: (*s_etat_processus).mode_execution_programme =
57: ((*(*l_element_courant).variable).origine == 'P') ? 'Y' : 'N';
58:
59: if ((*(*l_element_courant).variable).niveau > 0)
60: {
61: if (retrait_variable_statique(s_etat_processus,
62: (*(*l_element_courant).variable).nom,
63: (*(*l_element_courant).variable).variable_statique)
64: == d_erreur)
65: {
66: (*s_etat_processus).mode_execution_programme =
67: registre_mode_execution;
68: return(d_erreur);
69: }
70: }
71:
72: l_element_courant = l_element_suivant;
73: }
74:
75: (*s_etat_processus).mode_execution_programme = registre_mode_execution;
76: return(d_absence_erreur);
77: }
78:
79:
80: /*
81: ================================================================================
82: Routine de création d'une nouvelle variable statique
83: ================================================================================
84: Entrée :
85: --------------------------------------------------------------------------------
86: Sortie :
87: --------------------------------------------------------------------------------
88: Effets de bords : néant
89: ================================================================================
90: */
91:
92: logical1
93: creation_variable_statique(struct_processus *s_etat_processus,
94: struct_variable_statique *s_variable)
95: {
96: int i;
97:
98: struct_arbre_variables *l_variable_courante;
99:
100: struct_liste_variables_statiques *l_nouvel_element;
101:
102: unsigned char *ptr;
103:
104: // Ajout de la variable en tête de la liste des variables statiques
105:
106: if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
107: == NULL)
108: {
109: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
110: return(d_erreur);
111: }
112:
113: if (((*l_nouvel_element).variable = malloc(sizeof(
114: struct_variable_statique))) == NULL)
115: {
116: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
117: return(d_erreur);
118: }
119:
120: (*(*l_nouvel_element).variable) = (*s_variable);
121:
122: (*l_nouvel_element).suivant = (*s_etat_processus)
123: .l_liste_variables_statiques;
124: (*l_nouvel_element).precedent = NULL;
125:
126: if ((*s_etat_processus).l_liste_variables_statiques != NULL)
127: {
128: (*(*s_etat_processus).l_liste_variables_statiques).precedent
129: = l_nouvel_element;
130: }
131:
132: (*s_etat_processus).l_liste_variables_statiques = l_nouvel_element;
133:
134: // Ajout de la variable à la feuille statique de l'arbre des variables
135:
136: if ((*s_etat_processus).s_arbre_variables == NULL)
137: {
138: if (((*s_etat_processus).s_arbre_variables =
139: allocation_noeud(s_etat_processus)) == NULL)
140: {
141: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
142: return(d_erreur);
143: }
144:
145: (*(*s_etat_processus).s_arbre_variables).feuille = NULL;
146: (*(*s_etat_processus).s_arbre_variables).feuille_statique = NULL;
147: (*(*s_etat_processus).s_arbre_variables).feuille_partagee = NULL;
148: (*(*s_etat_processus).s_arbre_variables).noeuds_utilises = 0;
149: (*(*s_etat_processus).s_arbre_variables).indice_tableau_pere = -1;
150: (*(*s_etat_processus).s_arbre_variables).noeud_pere = NULL;
151: INITIALISATION_MUTEX((*(*s_etat_processus).s_arbre_variables)
152: .mutex_feuille_partagee);
153:
154: if (((*(*s_etat_processus).s_arbre_variables).noeuds =
155: allocation_tableau_noeuds(s_etat_processus)) == NULL)
156: {
157: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
158: return(d_erreur);
159: }
160:
161: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
162: {
163: (*(*s_etat_processus).s_arbre_variables).noeuds[i] = NULL;
164: }
165: }
166:
167: l_variable_courante = (*s_etat_processus).s_arbre_variables;
168: ptr = (*s_variable).nom;
169:
170: while((*ptr) != d_code_fin_chaine)
171: {
172: BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0,
173: uprintf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom,
174: *ptr));
175:
176: if ((*l_variable_courante).noeuds[(*s_etat_processus)
177: .pointeurs_caracteres_variables[*ptr]] == NULL)
178: {
179: // Le noeud n'existe pas encore, on le crée et on le marque
180: // comme utilisé dans la structure parente.
181:
182: if (((*l_variable_courante).noeuds[(*s_etat_processus)
183: .pointeurs_caracteres_variables[*ptr]] =
184: allocation_noeud(s_etat_processus)) == NULL)
185: {
186: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
187: return(d_erreur);
188: }
189:
190: (*l_variable_courante).noeuds_utilises++;
191:
192: // La feuille est par défaut vide et aucun élément du tableau noeuds
193: // (les branches qui peuvent être issues de ce nouveau noeud)
194: // n'est encore utilisée.
195:
196: (*(*l_variable_courante).noeuds[(*s_etat_processus)
197: .pointeurs_caracteres_variables[*ptr]]).feuille = NULL;
198: (*(*l_variable_courante).noeuds[(*s_etat_processus)
199: .pointeurs_caracteres_variables[*ptr]]).feuille_statique
200: = NULL;
201: (*(*l_variable_courante).noeuds[(*s_etat_processus)
202: .pointeurs_caracteres_variables[*ptr]]).feuille_partagee
203: = NULL;
204: (*(*l_variable_courante).noeuds[(*s_etat_processus)
205: .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises = 0;
206: INITIALISATION_MUTEX((*(*l_variable_courante).noeuds
207: [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]])
208: .mutex_feuille_partagee);
209:
210: // Le champ noeud_pere de la structure créée pointe sur
211: // la structure parente et l'indice tableau_pere correspond à la
212: // position réelle dans le tableau noeuds[] de la structure parente
213: // du noeud courant. Cette valeur sera utilisée lors de la
214: // destruction du noeud pour annuler le pointeur contenu dans
215: // le tableau noeuds[] de la structure parente.
216:
217: (*(*l_variable_courante).noeuds[(*s_etat_processus)
218: .pointeurs_caracteres_variables[*ptr]]).noeud_pere =
219: l_variable_courante;
220: (*(*l_variable_courante).noeuds[(*s_etat_processus)
221: .pointeurs_caracteres_variables[*ptr]])
222: .indice_tableau_pere = (*s_etat_processus)
223: .pointeurs_caracteres_variables[*ptr];
224:
225: // Allocation du tableau noeuds[] et initialisation à zéro de
226: // tous les pointeurs.
227:
228: if (((*(*l_variable_courante).noeuds[(*s_etat_processus)
229: .pointeurs_caracteres_variables[*ptr]]).noeuds =
230: allocation_tableau_noeuds(s_etat_processus)) == NULL)
231: {
232: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
233: return(d_erreur);
234: }
235:
236: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
237: {
238: (*(*l_variable_courante).noeuds[(*s_etat_processus)
239: .pointeurs_caracteres_variables[*ptr]]).noeuds[i]
240: = NULL;
241: }
242: }
243:
244: l_variable_courante = (*l_variable_courante).noeuds
245: [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]];
246: ptr++;
247: }
248:
249: if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
250: == NULL)
251: {
252: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
253: return(d_erreur);
254: }
255:
256: // Dans la feuille statique de l'arbre des variables, on ne balaie
257: // les variables que dans l'ordre. Le champ 'reference' est alors utilisé
258: // pour sauvegarder une référence vers la liste des variables statiques
259: // pour pouvoir purger l'élément en cas de besoin.
260:
261: (*l_nouvel_element).suivant = (*l_variable_courante).feuille_statique;
262: (*l_nouvel_element).precedent = NULL;
263:
264: if ((*l_nouvel_element).suivant != NULL)
265: {
266: (*(*l_nouvel_element).suivant).precedent = l_nouvel_element;
267: }
268:
269: (*l_nouvel_element).reference =
270: (*s_etat_processus).l_liste_variables_statiques;
271: (*l_nouvel_element).variable = (*(*s_etat_processus)
272: .l_liste_variables_statiques).variable;
273: (*l_variable_courante).feuille_statique = l_nouvel_element;
274: (*l_nouvel_element).feuille = l_variable_courante;
275:
276: return(d_absence_erreur);
277: }
278:
279:
280: /*
281: ================================================================================
282: Procédure de retrait d'une variable statique de la base
283: ================================================================================
284: Entrée :
285: --------------------------------------------------------------------------------
286: Sortie :
287: --------------------------------------------------------------------------------
288: Effets de bord : néant
289: ================================================================================
290: */
291:
292: logical1
293: retrait_variable_statique(struct_processus *s_etat_processus,
294: unsigned char *nom_variable, union_position_variable position)
295: {
296: struct_liste_variables_statiques *l_element_a_supprimer;
297: struct_liste_variables_statiques *l_element_liste_a_supprimer;
298:
299: logical1 erreur;
300:
301: if ((l_element_a_supprimer = recherche_variable_statique(s_etat_processus,
302: nom_variable, position, ((*s_etat_processus)
303: .mode_execution_programme == 'Y') ? 'P' : 'E')) != NULL)
304: {
305: // (*s_etat_processus).pointeur_variable_statique_courante
306: // pointe sur la variable à éliminer. Cette variable est celle qui
307: // est présente dans l'une des feuilles statiques de l'arbre des
308: // variables.
309:
310: l_element_liste_a_supprimer = (*l_element_a_supprimer).reference;
311:
312: // Suppression de la liste des variables statiques
313:
314: if ((*l_element_liste_a_supprimer).precedent != NULL)
315: {
316: // L'élément à supprimer n'est pas le premier de la liste.
317:
318: (*(*l_element_liste_a_supprimer).precedent).suivant =
319: (*l_element_liste_a_supprimer).suivant;
320:
321: if ((*l_element_liste_a_supprimer).suivant != NULL)
322: {
323: // Il y a un élément suivant. On le chaîne.
324: (*(*l_element_liste_a_supprimer).suivant).precedent = NULL;
325: }
326: }
327: else
328: {
329: // L'élement est le premier de la liste. S'il y a un élément
330: // suivant, on le chaîne.
331:
332: if ((*l_element_liste_a_supprimer).suivant != NULL)
333: {
334: (*(*l_element_liste_a_supprimer).suivant).precedent = NULL;
335: }
336:
337: (*s_etat_processus).l_liste_variables_statiques =
338: (*l_element_liste_a_supprimer).suivant;
339: }
340:
341: free(l_element_liste_a_supprimer);
342:
343: // Suppression depuis la feuille statique. Le champ 'precedent' ne sert
344: // pas car la liste est simplement chaînée.
345:
346: if ((*l_element_a_supprimer).precedent != NULL)
347: {
348: // L'élément n'est pas le premier de la liste.
349:
350: (*(*l_element_a_supprimer).precedent).suivant =
351: (*l_element_a_supprimer).suivant;
352:
353: if ((*l_element_a_supprimer).suivant != NULL)
354: {
355: (*(*l_element_a_supprimer).suivant).precedent =
356: (*l_element_a_supprimer).precedent;
357: }
358: else
359: {
360: (*(*l_element_a_supprimer).precedent).suivant = NULL;
361: }
362: }
363: else
364: {
365: // L'élément est le premier de la liste.
366:
367: if ((*l_element_a_supprimer).suivant != NULL)
368: {
369: (*(*l_element_a_supprimer).suivant).precedent = NULL;
370: }
371:
372: (*(*l_element_a_supprimer).feuille).feuille_statique
373: = (*l_element_a_supprimer).suivant;
374: }
375:
376: liberation(s_etat_processus, (*(*l_element_a_supprimer).variable)
377: .objet);
378: free((*(*l_element_a_supprimer).variable).nom);
379: free((*l_element_a_supprimer).variable);
380: free(l_element_a_supprimer);
381:
382: erreur = d_absence_erreur;
383: }
384: else
385: {
386: erreur = d_erreur;
387: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
388: }
389:
390: return erreur;
391: }
392:
393:
394: /*
395: ================================================================================
396: Procédure de recherche d'une variable statique par son nom dans la base
397: ================================================================================
398: Entrée :
399: --------------------------------------------------------------------------------
400: Sortie :
401: --------------------------------------------------------------------------------
402: Effets de bord : néant
403: ================================================================================
404: */
405:
406: struct_liste_variables_statiques *
407: recherche_variable_statique(struct_processus *s_etat_processus,
408: unsigned char *nom_variable, union_position_variable position,
409: unsigned char origine)
410: {
411: int pointeur;
412:
413: struct_arbre_variables *l_variable_courante;
414: struct_liste_variables_statiques *l_element_courant;
415:
416: unsigned char *ptr;
417:
418: l_variable_courante = (*s_etat_processus).s_arbre_variables;
419: ptr = nom_variable;
420:
421: while((*ptr) != d_code_fin_chaine)
422: {
423: pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr];
424:
425: if (pointeur < 0)
426: {
427: // Caractère hors de l'alphabet des variables
428:
429: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
430: return(NULL);
431: }
432:
433: if ((*l_variable_courante).noeuds[pointeur] == NULL)
434: {
435: // Le chemin de la variable candidate n'existe pas.
436: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
437: return(NULL);
438: }
439:
440: l_variable_courante = (*l_variable_courante).noeuds[pointeur];
441: ptr++;
442: }
443:
444: if ((*l_variable_courante).feuille_statique != NULL)
445: {
446: // Il existe au moins une variable statique du nom requis.
447:
448: l_element_courant = (*l_variable_courante).feuille_statique;
449:
450: while(l_element_courant != NULL)
451: {
452: if ((*(*l_element_courant).variable).origine == 'P')
453: {
454: if (((*(*l_element_courant).variable).variable_statique.adresse
455: == position.adresse) &&
456: ((*(*l_element_courant).variable).origine == origine))
457: {
458: (*s_etat_processus).pointeur_variable_statique_courante
459: = (*l_element_courant).variable;
460: return(l_element_courant);
461: }
462: }
463: else
464: {
465: if (((*(*l_element_courant).variable).variable_statique.pointeur
466: == position.pointeur) &&
467: ((*(*l_element_courant).variable).origine == origine))
468: {
469: (*s_etat_processus).pointeur_variable_statique_courante
470: = (*l_element_courant).variable;
471: return(l_element_courant);
472: }
473: }
474:
475: l_element_courant = (*l_element_courant).suivant;
476: }
477: }
478:
479: (*s_etat_processus).pointeur_variable_statique_courante = NULL;
480: return(NULL);
481: }
482:
483: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>