1: /*
2: ================================================================================
3: RPL/2 (R) version 4.1.36
4: Copyright (C) 1989-2025 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).noeuds_utilises = 0;
148: (*(*s_etat_processus).s_arbre_variables).indice_tableau_pere = -1;
149: (*(*s_etat_processus).s_arbre_variables).noeud_pere = NULL;
150:
151: if (((*(*s_etat_processus).s_arbre_variables).noeuds =
152: allocation_tableau_noeuds(s_etat_processus)) == NULL)
153: {
154: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
155: return(d_erreur);
156: }
157:
158: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
159: {
160: (*(*s_etat_processus).s_arbre_variables).noeuds[i] = NULL;
161: }
162: }
163:
164: l_variable_courante = (*s_etat_processus).s_arbre_variables;
165: ptr = (*s_variable).nom;
166:
167: while((*ptr) != d_code_fin_chaine)
168: {
169: BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0,
170: uprintf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom,
171: *ptr));
172:
173: if ((*l_variable_courante).noeuds[(*s_etat_processus)
174: .pointeurs_caracteres_variables[*ptr]] == NULL)
175: {
176: // Le noeud n'existe pas encore, on le crée et on le marque
177: // comme utilisé dans la structure parente.
178:
179: if (((*l_variable_courante).noeuds[(*s_etat_processus)
180: .pointeurs_caracteres_variables[*ptr]] =
181: allocation_noeud(s_etat_processus)) == NULL)
182: {
183: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
184: return(d_erreur);
185: }
186:
187: (*l_variable_courante).noeuds_utilises++;
188:
189: // La feuille est par défaut vide et aucun élément du tableau noeuds
190: // (les branches qui peuvent être issues de ce nouveau noeud)
191: // n'est encore utilisée.
192:
193: (*(*l_variable_courante).noeuds[(*s_etat_processus)
194: .pointeurs_caracteres_variables[*ptr]]).feuille = NULL;
195: (*(*l_variable_courante).noeuds[(*s_etat_processus)
196: .pointeurs_caracteres_variables[*ptr]]).feuille_statique
197: = NULL;
198: (*(*l_variable_courante).noeuds[(*s_etat_processus)
199: .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises = 0;
200:
201: // Le champ noeud_pere de la structure créée pointe sur
202: // la structure parente et l'indice tableau_pere correspond à la
203: // position réelle dans le tableau noeuds[] de la structure parente
204: // du noeud courant. Cette valeur sera utilisée lors de la
205: // destruction du noeud pour annuler le pointeur contenu dans
206: // le tableau noeuds[] de la structure parente.
207:
208: (*(*l_variable_courante).noeuds[(*s_etat_processus)
209: .pointeurs_caracteres_variables[*ptr]]).noeud_pere =
210: l_variable_courante;
211: (*(*l_variable_courante).noeuds[(*s_etat_processus)
212: .pointeurs_caracteres_variables[*ptr]])
213: .indice_tableau_pere = (*s_etat_processus)
214: .pointeurs_caracteres_variables[*ptr];
215:
216: // Allocation du tableau noeuds[] et initialisation à zéro de
217: // tous les pointeurs.
218:
219: if (((*(*l_variable_courante).noeuds[(*s_etat_processus)
220: .pointeurs_caracteres_variables[*ptr]]).noeuds =
221: allocation_tableau_noeuds(s_etat_processus)) == NULL)
222: {
223: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
224: return(d_erreur);
225: }
226:
227: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
228: {
229: (*(*l_variable_courante).noeuds[(*s_etat_processus)
230: .pointeurs_caracteres_variables[*ptr]]).noeuds[i]
231: = NULL;
232: }
233: }
234:
235: l_variable_courante = (*l_variable_courante).noeuds
236: [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]];
237: ptr++;
238: }
239:
240: if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
241: == NULL)
242: {
243: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
244: return(d_erreur);
245: }
246:
247: // Dans la feuille statique de l'arbre des variables, on ne balaie
248: // les variables que dans l'ordre. Le champ 'reference' est alors utilisé
249: // pour sauvegarder une référence vers la liste des variables statiques
250: // pour pouvoir purger l'élément en cas de besoin.
251:
252: (*l_nouvel_element).suivant = (*l_variable_courante).feuille_statique;
253: (*l_nouvel_element).precedent = NULL;
254:
255: if ((*l_nouvel_element).suivant != NULL)
256: {
257: (*(*l_nouvel_element).suivant).precedent = l_nouvel_element;
258: }
259:
260: (*l_nouvel_element).reference =
261: (*s_etat_processus).l_liste_variables_statiques;
262: (*l_nouvel_element).variable = (*(*s_etat_processus)
263: .l_liste_variables_statiques).variable;
264: (*l_variable_courante).feuille_statique = l_nouvel_element;
265: (*l_nouvel_element).feuille = l_variable_courante;
266:
267: return(d_absence_erreur);
268: }
269:
270:
271: /*
272: ================================================================================
273: Procédure de retrait d'une variable statique de la base
274: ================================================================================
275: Entrée :
276: --------------------------------------------------------------------------------
277: Sortie :
278: --------------------------------------------------------------------------------
279: Effets de bord : néant
280: ================================================================================
281: */
282:
283: logical1
284: retrait_variable_statique(struct_processus *s_etat_processus,
285: unsigned char *nom_variable, union_position_variable position)
286: {
287: struct_liste_variables_statiques *l_element_a_supprimer;
288: struct_liste_variables_statiques *l_element_liste_a_supprimer;
289:
290: logical1 erreur;
291:
292: if ((l_element_a_supprimer = recherche_variable_statique(s_etat_processus,
293: nom_variable, position, ((*s_etat_processus)
294: .mode_execution_programme == 'Y') ? 'P' : 'E')) != NULL)
295: {
296: // (*s_etat_processus).pointeur_variable_statique_courante
297: // pointe sur la variable à éliminer. Cette variable est celle qui
298: // est présente dans l'une des feuilles statiques de l'arbre des
299: // variables.
300:
301: l_element_liste_a_supprimer = (*l_element_a_supprimer).reference;
302:
303: // Suppression de la liste des variables statiques
304:
305: if ((*l_element_liste_a_supprimer).precedent != NULL)
306: {
307: // L'élément à supprimer n'est pas le premier de la liste.
308:
309: (*(*l_element_liste_a_supprimer).precedent).suivant =
310: (*l_element_liste_a_supprimer).suivant;
311:
312: if ((*l_element_liste_a_supprimer).suivant != NULL)
313: {
314: // Il y a un élément suivant. On le chaîne.
315: (*(*l_element_liste_a_supprimer).suivant).precedent = NULL;
316: }
317: }
318: else
319: {
320: // L'élement est le premier de la liste. S'il y a un élément
321: // suivant, on le chaîne.
322:
323: if ((*l_element_liste_a_supprimer).suivant != NULL)
324: {
325: (*(*l_element_liste_a_supprimer).suivant).precedent = NULL;
326: }
327:
328: (*s_etat_processus).l_liste_variables_statiques =
329: (*l_element_liste_a_supprimer).suivant;
330: }
331:
332: free(l_element_liste_a_supprimer);
333:
334: // Suppression depuis la feuille statique. Le champ 'precedent' ne sert
335: // pas car la liste est simplement chaînée.
336:
337: if ((*l_element_a_supprimer).precedent != NULL)
338: {
339: // L'élément n'est pas le premier de la liste.
340:
341: (*(*l_element_a_supprimer).precedent).suivant =
342: (*l_element_a_supprimer).suivant;
343:
344: if ((*l_element_a_supprimer).suivant != NULL)
345: {
346: (*(*l_element_a_supprimer).suivant).precedent =
347: (*l_element_a_supprimer).precedent;
348: }
349: else
350: {
351: (*(*l_element_a_supprimer).precedent).suivant = NULL;
352: }
353: }
354: else
355: {
356: // L'élément est le premier de la liste.
357:
358: if ((*l_element_a_supprimer).suivant != NULL)
359: {
360: (*(*l_element_a_supprimer).suivant).precedent = NULL;
361: }
362:
363: (*(*l_element_a_supprimer).feuille).feuille_statique
364: = (*l_element_a_supprimer).suivant;
365: }
366:
367: liberation(s_etat_processus, (*(*l_element_a_supprimer).variable)
368: .objet);
369: free((*(*l_element_a_supprimer).variable).nom);
370: free((*l_element_a_supprimer).variable);
371: free(l_element_a_supprimer);
372:
373: erreur = d_absence_erreur;
374: }
375: else
376: {
377: erreur = d_erreur;
378: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
379: }
380:
381: return(erreur);
382: }
383:
384:
385: /*
386: ================================================================================
387: Procédure de recherche d'une variable statique par son nom dans la base
388: ================================================================================
389: Entrée :
390: --------------------------------------------------------------------------------
391: Sortie :
392: --------------------------------------------------------------------------------
393: Effets de bord : néant
394: ================================================================================
395: */
396:
397: struct_liste_variables_statiques *
398: recherche_variable_statique(struct_processus *s_etat_processus,
399: unsigned char *nom_variable, union_position_variable position,
400: unsigned char origine)
401: {
402: int pointeur;
403:
404: struct_arbre_variables *l_variable_courante;
405: struct_liste_variables_statiques *l_element_courant;
406:
407: unsigned char *ptr;
408:
409: l_variable_courante = (*s_etat_processus).s_arbre_variables;
410: ptr = nom_variable;
411:
412: while((*ptr) != d_code_fin_chaine)
413: {
414: pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr];
415:
416: if (pointeur < 0)
417: {
418: // Caractère hors de l'alphabet des variables
419:
420: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
421: return(NULL);
422: }
423:
424: if ((*l_variable_courante).noeuds[pointeur] == NULL)
425: {
426: // Le chemin de la variable candidate n'existe pas.
427: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
428: return(NULL);
429: }
430:
431: l_variable_courante = (*l_variable_courante).noeuds[pointeur];
432: ptr++;
433: }
434:
435: if ((*l_variable_courante).feuille_statique != NULL)
436: {
437: // Il existe au moins une variable statique du nom requis.
438:
439: l_element_courant = (*l_variable_courante).feuille_statique;
440:
441: while(l_element_courant != NULL)
442: {
443: if ((*(*l_element_courant).variable).origine == 'P')
444: {
445: if (((*(*l_element_courant).variable).variable_statique.adresse
446: == position.adresse) &&
447: ((*(*l_element_courant).variable).origine == origine))
448: {
449: (*s_etat_processus).pointeur_variable_statique_courante
450: = (*l_element_courant).variable;
451: return(l_element_courant);
452: }
453: }
454: else
455: {
456: if (((*(*l_element_courant).variable).variable_statique.pointeur
457: == position.pointeur) &&
458: ((*(*l_element_courant).variable).origine == origine))
459: {
460: (*s_etat_processus).pointeur_variable_statique_courante
461: = (*l_element_courant).variable;
462: return(l_element_courant);
463: }
464: }
465:
466: l_element_courant = (*l_element_courant).suivant;
467: }
468: }
469:
470: (*s_etat_processus).pointeur_variable_statique_courante = NULL;
471: return(NULL);
472: }
473:
474: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>