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