1: /*
2: ================================================================================
3: RPL/2 (R) version 4.1.0.prerelease.0
4: Copyright (C) 1989-2011 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 création d'une nouvelle variable
29: Entrée : autorisation_creation_variable_statique vaut 'V' ou 'S'.
30: Dans le cas 'V', la variable est volatile.
31: Dans le cas 'S', elle est statique.
32: Entrée : autorisation_creation_variable_partagee vaut 'P' ou 'S'.
33: Dans le cas 'P', la variable est privée.
34: Dans le cas 'S', elle est partagée.
35: --------------------------------------------------------------------------------
36: Sortie :
37: --------------------------------------------------------------------------------
38: Effets de bords : néant
39: ================================================================================
40: */
41:
42: static logical1
43: ajout_variable(struct_processus *s_etat_processus, struct_variable *s_variable)
44: {
45: int i;
46:
47: struct_liste_variables *l_nouvelle_variable;
48: struct_liste_variables *l_variable_candidate;
49: struct_arbre_variables *l_variable_courante;
50: struct_arbre_variables *l_variable_precedente;
51:
52: struct_liste_chainee *l_nouvel_element;
53:
54: unsigned char *ptr;
55:
56: void *pointeur_variable_cree;
57:
58: if ((*s_etat_processus).s_arbre_variables == NULL)
59: {
60: if (((*s_etat_processus).s_arbre_variables =
61: malloc(sizeof(struct_arbre_variables))) == NULL)
62: {
63: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
64: return(d_erreur);
65: }
66:
67: (*(*s_etat_processus).s_arbre_variables).feuille = NULL;
68: (*(*s_etat_processus).s_arbre_variables).noeuds_utilises = 0;
69: (*(*s_etat_processus).s_arbre_variables).indice_tableau_pere = -1;
70: (*(*s_etat_processus).s_arbre_variables).noeud_pere = NULL;
71:
72: if (((*(*s_etat_processus).s_arbre_variables).noeuds =
73: malloc((*s_etat_processus).nombre_caracteres_variables
74: * sizeof(struct_arbre_variables))) == NULL)
75: {
76: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
77: return(d_erreur);
78: }
79:
80: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
81: {
82: (*(*s_etat_processus).s_arbre_variables).noeuds[i] = NULL;
83: }
84: }
85:
86: l_variable_precedente = NULL;
87: l_variable_courante = (*s_etat_processus).s_arbre_variables;
88: ptr = (*s_variable).nom;
89:
90: while((*ptr) != d_code_fin_chaine)
91: {
92: BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0,
93: printf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom,
94: *ptr));
95:
96: if ((*l_variable_courante).noeuds[(*s_etat_processus)
97: .pointeurs_caracteres_variables[*ptr]] == NULL)
98: {
99: // Le noeud n'existe pas encore, on le crée et on le marque
100: // comme utilisé dans la structure parente.
101:
102: if (((*l_variable_courante).noeuds[(*s_etat_processus)
103: .pointeurs_caracteres_variables[*ptr]] =
104: malloc(sizeof(struct_arbre_variables))) == NULL)
105: {
106: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
107: return(d_erreur);
108: }
109:
110: (*l_variable_courante).noeuds_utilises++;
111:
112: // La feuille est par défaut vide et aucun élément du tableau noeuds
113: // (les branches qui peuvent être issues de ce nouveau noeud)
114: // n'est encore utilisée.
115:
116: (*(*l_variable_courante).noeuds[(*s_etat_processus)
117: .pointeurs_caracteres_variables[*ptr]]).feuille = NULL;
118: (*(*l_variable_courante).noeuds[(*s_etat_processus)
119: .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises = 0;
120:
121: // Le champ noeud_pere de la structure créée pointe sur
122: // la structure parente et l'indice tableau_pere correspond à la
123: // position réelle dans le tableau noeuds[] de la structure parente
124: // du noeud courant. Cette valeur sera utilisée lors de la
125: // destruction du noeud pour annuler le pointeur contenu dans
126: // le tableau noeuds[] de la structure parente.
127:
128: (*(*l_variable_courante).noeuds[(*s_etat_processus)
129: .pointeurs_caracteres_variables[*ptr]]).noeud_pere =
130: l_variable_courante;
131: (*(*l_variable_courante).noeuds[(*s_etat_processus)
132: .pointeurs_caracteres_variables[*ptr]])
133: .indice_tableau_pere = (*s_etat_processus)
134: .pointeurs_caracteres_variables[*ptr];
135:
136: // Allocation du tableau noeuds[] et initialisation à zéro de
137: // tous les pointeurs.
138:
139: if (((*(*l_variable_courante).noeuds[(*s_etat_processus)
140: .pointeurs_caracteres_variables[*ptr]]).noeuds =
141: malloc((*s_etat_processus).nombre_caracteres_variables
142: * sizeof(struct_arbre_variables))) == NULL)
143: {
144: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
145: return(d_erreur);
146: }
147:
148: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
149: {
150: (*(*l_variable_courante).noeuds[(*s_etat_processus)
151: .pointeurs_caracteres_variables[*ptr]]).noeuds[i]
152: = NULL;
153: }
154: }
155:
156: l_variable_precedente = l_variable_courante;
157: l_variable_courante = (*l_variable_courante).noeuds
158: [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]];
159: ptr++;
160: }
161:
162: if ((*l_variable_courante).feuille == NULL)
163: {
164: // Aucune variable de même nom préexiste. On alloue le premier
165: // élément de la liste doublement chaînée contenant toutes les
166: // variables de même nom. Cette liste boucle en premier lieu sur
167: // elle-même.
168:
169: if (((*l_variable_courante).feuille = malloc(
170: sizeof(struct_liste_variables))) == NULL)
171: {
172: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
173: return(d_erreur);
174: }
175:
176: (*(*l_variable_courante).feuille).suivant =
177: (*l_variable_courante).feuille;
178: (*(*l_variable_courante).feuille).precedent =
179: (*l_variable_courante).feuille;
180: (*(*l_variable_courante).feuille).noeud_pere = l_variable_precedente;
181: (*(*l_variable_courante).feuille).noeud = l_variable_courante;
182:
183: // Allocation de la variable sur l'élément de la liste.
184:
185: if (((*(*l_variable_courante).feuille).variable =
186: malloc(sizeof(struct_variable))) == NULL)
187: {
188: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
189: return(d_erreur);
190: }
191:
192: (*((struct_variable *) (*(*l_variable_courante).feuille).variable)) =
193: (*s_variable);
194: pointeur_variable_cree = (*(*l_variable_courante).feuille).variable;
195: }
196: else
197: {
198: if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables)))
199: == NULL)
200: {
201: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
202: return(d_erreur);
203: }
204:
205: if ((*s_variable).niveau > 1)
206: {
207: // Cas d'une variable locale
208:
209: // Si le niveau de la dernière variable de même nom est
210: // supérieur au niveau de la variable locale que l'on veut
211: // enregistrer dans la liste, cette liste est incohérente.
212:
213: BUG((*(*(*l_variable_courante).feuille).variable).niveau >=
214: (*s_variable).niveau,
215: printf("Variable=\"%s\"\n", (*s_variable).nom));
216:
217: // On ajoute la variable à la liste existante.
218:
219: (*l_nouvelle_variable).suivant = (*l_variable_courante).feuille;
220: (*l_nouvelle_variable).precedent = (*(*l_variable_courante).feuille)
221: .precedent;
222: (*l_nouvelle_variable).noeud_pere = l_variable_precedente;
223: (*(*(*l_variable_courante).feuille).precedent).suivant =
224: l_nouvelle_variable;
225: (*(*l_variable_courante).feuille).precedent =
226: l_nouvelle_variable;
227: (*l_variable_courante).feuille = l_nouvelle_variable;
228:
229: if (((*(*l_variable_courante).feuille).variable =
230: malloc(sizeof(struct_variable))) == NULL)
231: {
232: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
233: return(d_erreur);
234: }
235:
236: (*((struct_variable *) (*(*l_variable_courante).feuille).variable))
237: = (*s_variable);
238: pointeur_variable_cree = (*(*l_variable_courante).feuille).variable;
239: }
240: else
241: {
242: // Cas d'une variable globale (niveau 0 [définitions] ou 1
243: // [variables globales])
244:
245: l_variable_candidate = (*l_variable_courante).feuille;
246:
247: do
248: {
249: // S'il y a déjà une variable de même niveau, la pile
250: // est incohérente.
251:
252: BUG((*(*l_variable_candidate).variable).niveau ==
253: (*s_variable).niveau,
254: printf("Variable=\"%s\"\n", (*s_variable).nom));
255:
256: l_variable_candidate = (*l_variable_candidate).precedent;
257: } while((l_variable_candidate != (*l_variable_courante).feuille) &&
258: ((*(*l_variable_candidate).variable).niveau <= 1));
259:
260: if ((*(*(*(*l_variable_courante).feuille).precedent).variable)
261: .niveau > 1)
262: {
263: // Ajout inconditionnel des variables de niveaux 0 et 1
264: }
265: else
266: {
267: l_variable_candidate = (*(*l_variable_courante).feuille)
268: .precedent;
269: }
270:
271: (*l_nouvelle_variable).suivant = l_variable_candidate;
272: (*l_nouvelle_variable).precedent = (*l_variable_candidate)
273: .precedent;
274: (*l_nouvelle_variable).noeud_pere = l_variable_precedente;
275: (*(*l_variable_candidate).precedent).suivant = l_nouvelle_variable;
276: (*l_variable_candidate).precedent = l_nouvelle_variable;
277:
278: if (((*l_nouvelle_variable).variable =
279: malloc(sizeof(struct_variable))) == NULL)
280: {
281: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
282: return(d_erreur);
283: }
284:
285: (*(*l_nouvelle_variable).variable) = (*s_variable);
286: pointeur_variable_cree = (*l_nouvelle_variable).variable;
287: }
288: }
289:
290: // Ajout de la variable nouvellement créée à la liste par niveaux.
291: // Le pointeur contenu dans la structure de description du processus indique
292: // toujours le plus haut niveau utilisé.
293:
294: if ((*s_etat_processus).l_liste_variables_par_niveau == NULL)
295: {
296: // Le niveau courant n'existe pas. Il est créé.
297:
298: if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables)))
299: == NULL)
300: {
301: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
302: return(d_erreur);
303: }
304:
305: (*l_nouvelle_variable).suivant = l_nouvelle_variable;
306: (*l_nouvelle_variable).precedent = l_nouvelle_variable;
307: (*l_nouvelle_variable).noeud_pere = NULL;
308: (*l_nouvelle_variable).liste = NULL;
309:
310: (*s_etat_processus).l_liste_variables_par_niveau = l_nouvelle_variable;
311: }
312: else if ((*s_variable).niveau > (*((struct_variable *)
313: (*(*(*s_etat_processus).l_liste_variables_par_niveau).liste)
314: .donnee)).niveau)
315: {
316: // Le niveau courant n'existe pas. Il est créé.
317:
318: if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables)))
319: == NULL)
320: {
321: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
322: return(d_erreur);
323: }
324:
325: (*l_nouvelle_variable).suivant = (*s_etat_processus)
326: .l_liste_variables_par_niveau;
327: (*l_nouvelle_variable).precedent = (*(*s_etat_processus)
328: .l_liste_variables_par_niveau).precedent;
329: (*l_nouvelle_variable).noeud_pere = NULL;
330: (*l_nouvelle_variable).liste = NULL;
331: (*(*(*s_etat_processus).l_liste_variables_par_niveau).precedent)
332: .suivant = l_nouvelle_variable;
333: (*(*s_etat_processus).l_liste_variables_par_niveau).precedent =
334: l_nouvelle_variable;
335:
336: (*s_etat_processus).l_liste_variables_par_niveau = l_nouvelle_variable;
337: }
338: else if ((*s_variable).niveau <= 1)
339: {
340: // Création d'une variable de niveau 0 ou 1
341:
342: if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables)))
343: == NULL)
344: {
345: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
346: return(d_erreur);
347: }
348:
349: l_variable_candidate = (*s_etat_processus).l_liste_variables_par_niveau;
350:
351: if ((*((struct_variable *) (*(*(*(*s_etat_processus)
352: .l_liste_variables_par_niveau).precedent).liste).donnee))
353: .niveau <= 1)
354: {
355: l_variable_candidate = (*(*s_etat_processus)
356: .l_liste_variables_par_niveau).precedent;
357: }
358:
359: (*l_nouvelle_variable).suivant = l_variable_candidate;
360: (*l_nouvelle_variable).precedent = (*l_variable_candidate)
361: .precedent;
362: (*l_nouvelle_variable).noeud_pere = NULL;
363: (*l_nouvelle_variable).liste = NULL;
364: (*(*l_variable_candidate).precedent).suivant = l_nouvelle_variable;
365: (*l_variable_candidate).precedent = l_nouvelle_variable;
366: }
367:
368: // Ajout de la variable en tête de la liste
369:
370: if ((l_nouvel_element = malloc(sizeof(struct_liste_chainee))) == NULL)
371: {
372: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
373: return(d_erreur);
374: }
375:
376: (*l_nouvel_element).suivant = (*(*s_etat_processus)
377: .l_liste_variables_par_niveau).liste;
378: (*l_nouvel_element).donnee = pointeur_variable_cree;
379: (*(*s_etat_processus).l_liste_variables_par_niveau).liste =
380: l_nouvel_element;
381:
382: return(d_absence_erreur);
383: }
384:
385:
386: logical1
387: creation_variable(struct_processus *s_etat_processus,
388: struct_variable *s_variable,
389: unsigned char autorisation_creation_variable_statique,
390: unsigned char autorisation_creation_variable_partagee)
391: {
392: if ((*s_etat_processus).mode_execution_programme == 'Y')
393: {
394: (*s_variable).origine = 'P';
395: }
396: else
397: {
398: (*s_variable).origine = 'E';
399: }
400:
401: if ((*s_variable).niveau == 0)
402: {
403: // Un point d'entrée de définition est verrouillé.
404:
405: if ((*s_variable).origine == 'P')
406: {
407: (*s_variable).variable_statique.adresse = 0;
408: (*s_variable).variable_partagee.adresse = 0;
409: }
410: else
411: {
412: (*s_variable).variable_statique.pointeur = NULL;
413: (*s_variable).variable_partagee.pointeur = NULL;
414: }
415:
416: (*s_variable).variable_verrouillee = d_vrai;
417: }
418: else if ((*s_variable).niveau == 1)
419: {
420: // Une variable globale ne peut être statique.
421:
422: if ((*s_variable).origine == 'P')
423: {
424: (*s_variable).variable_statique.adresse = 0;
425: (*s_variable).variable_partagee.adresse = 0;
426: }
427: else
428: {
429: (*s_variable).variable_statique.pointeur = NULL;
430: (*s_variable).variable_partagee.pointeur = NULL;
431: }
432:
433: (*s_variable).variable_verrouillee = d_faux;
434: }
435: else
436: {
437: // 0 -> variable volatile
438: // adresse de création -> variable statique
439:
440: if (autorisation_creation_variable_statique == 'V')
441: {
442: if (autorisation_creation_variable_partagee == 'S')
443: {
444: // On force la création d'une variable partagée
445:
446: if ((*s_variable).origine == 'P')
447: {
448: (*s_variable).variable_statique.adresse = 0;
449: (*s_variable).variable_partagee.adresse =
450: (*s_etat_processus).position_courante;
451: }
452: else
453: {
454: (*s_variable).variable_statique.pointeur = NULL;
455: (*s_variable).variable_partagee.pointeur =
456: (*s_etat_processus).objet_courant;
457: }
458: }
459: else
460: {
461: // On force la création d'une variable volatile
462:
463: if ((*s_variable).origine == 'P')
464: {
465: (*s_variable).variable_statique.adresse = 0;
466: (*s_variable).variable_partagee.adresse = 0;
467: }
468: else
469: {
470: (*s_variable).variable_statique.pointeur = NULL;
471: (*s_variable).variable_partagee.pointeur = NULL;
472: }
473: }
474: }
475: else
476: {
477: // On force la création d'une variable statique.
478:
479: if ((*s_variable).origine == 'P')
480: {
481: (*s_variable).variable_statique.adresse =
482: (*s_etat_processus).position_courante;
483: (*s_variable).variable_partagee.adresse = 0;
484: }
485: else
486: {
487: (*s_variable).variable_statique.pointeur =
488: (*s_etat_processus).objet_courant;
489: (*s_variable).variable_partagee.pointeur = 0;
490: }
491: }
492:
493: (*s_variable).variable_verrouillee = d_faux;
494: }
495:
496: /*
497: * Recherche de la feuille correspondante dans l'arbre des variables.
498: * Si cette feuille n'existe pas, elle est créée.
499: */
500:
501: if (ajout_variable(s_etat_processus, s_variable) == d_erreur)
502: {
503: return(d_erreur);
504: }
505:
506: return(d_absence_erreur);
507: }
508:
509:
510: /*
511: ================================================================================
512: Procédure de recherche d'une variable par son nom dans la base
513: ================================================================================
514: Entrée :
515: --------------------------------------------------------------------------------
516: Sortie :
517: --------------------------------------------------------------------------------
518: Effets de bord : néant
519: ================================================================================
520: */
521:
522: logical1
523: recherche_variable(struct_processus *s_etat_processus,
524: unsigned char *nom_variable)
525: {
526: int pointeur;
527:
528: struct_arbre_variables *l_variable_courante;
529: struct_liste_pile_systeme *l_element_courant;
530:
531: unsigned char *ptr;
532:
533: unsigned long niveau_appel;
534:
535: if ((*s_etat_processus).s_arbre_variables == NULL)
536: {
537: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
538: return(d_faux);
539: }
540:
541: l_variable_courante = (*s_etat_processus).s_arbre_variables;
542: ptr = nom_variable;
543:
544: while((*ptr) != d_code_fin_chaine)
545: {
546: pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr];
547:
548: if (pointeur < 0)
549: {
550: // Caractère hors de l'alphabet des variables
551:
552: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
553: return(d_faux);
554: }
555:
556: if ((*l_variable_courante).noeuds[pointeur] == NULL)
557: {
558: // Le chemin de la variable candidate n'existe pas.
559: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
560: return(d_faux);
561: }
562:
563: l_variable_courante = (*l_variable_courante).noeuds[pointeur];
564: ptr++;
565: }
566:
567: if ((*l_variable_courante).feuille != NULL)
568: {
569: // Il existe une pile de variables de même nom. Le sommet de la
570: // pile est la variable de niveau le plus haut.
571:
572: l_element_courant = (*s_etat_processus).l_base_pile_systeme;
573:
574: if (l_element_courant == NULL)
575: {
576: // Problème : la pile système est vide !
577: (*s_etat_processus).erreur_systeme = d_es_pile_vide;
578: return(d_faux);
579: }
580:
581: while((*l_element_courant).retour_definition != 'Y')
582: {
583: l_element_courant = (*l_element_courant).suivant;
584:
585: if (l_element_courant == NULL)
586: {
587: (*s_etat_processus).erreur_systeme = d_es_pile_vide;
588: return(d_faux);
589: }
590: }
591:
592: niveau_appel = (*l_element_courant).niveau_courant;
593:
594: if (niveau_appel < (*(*(*l_variable_courante).feuille).variable).niveau)
595: {
596: // Une variable locale est accessible puisque créée dans la
597: // fonction courante.
598:
599: (*s_etat_processus).pointeur_variable_courante =
600: (*(*l_variable_courante).feuille).variable;
601: (*s_etat_processus).pointeur_feuille_courante =
602: (*l_variable_courante).feuille;
603: return(d_vrai);
604: }
605: else
606: {
607: // Aucune variable locale n'est accessible depuis la fonction.
608: // Dans ce cas, on prend la variable de niveau le plus bas
609: // si ce niveau est inférieur ou égal à 1 (variable globale
610: // ou fonction définie par l'utilisateur). Si le niveau de la
611: // plus ancienne variable est strictement supérieur à 1, il
612: // s'agit d'une variable locale inaccessible.
613:
614: if ((*(*(*(*l_variable_courante).feuille).precedent).variable)
615: .niveau <= 1)
616: {
617: (*s_etat_processus).pointeur_variable_courante =
618: (*(*(*l_variable_courante).feuille).precedent).variable;
619: (*s_etat_processus).pointeur_feuille_courante =
620: (*l_variable_courante).feuille;
621:
622: // S'il existe une variable de niveau 0 et une seconde de
623: // niveau 1, la variable de niveau 0 (fonction) est masquée
624: // par celle de niveau 1.
625:
626: if (((*(*(*l_variable_courante).feuille).variable).niveau == 0)
627: && ((*(*(*(*l_variable_courante).feuille).precedent)
628: .variable).niveau == 1))
629: {
630: (*s_etat_processus).pointeur_variable_courante =
631: (*(*(*l_variable_courante).feuille).precedent)
632: .variable;
633: (*s_etat_processus).pointeur_feuille_courante =
634: (*l_variable_courante).feuille;
635: }
636:
637: return(d_vrai);
638: }
639: }
640: }
641:
642: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
643: return(d_faux);
644: }
645:
646:
647: logical1
648: recherche_variable_globale(struct_processus *s_etat_processus,
649: unsigned char *nom)
650: {
651: logical1 presence_variable;
652:
653: presence_variable = recherche_variable(s_etat_processus, nom);
654:
655: if (presence_variable == d_vrai)
656: {
657: switch((*(*s_etat_processus).pointeur_variable_courante).niveau)
658: {
659: case 0:
660: {
661: // Nous sommes en présence d'une définition et non d'une
662: // variable.
663:
664: presence_variable = d_faux;
665: break;
666: }
667:
668: case 1:
669: {
670: break;
671: }
672:
673: default:
674: {
675: if ((*(*(*(*s_etat_processus).pointeur_feuille_courante)
676: .precedent).variable).niveau == 1)
677: {
678: (*s_etat_processus).pointeur_feuille_courante =
679: (*(*s_etat_processus).pointeur_feuille_courante)
680: .precedent;
681: (*s_etat_processus).pointeur_variable_courante =
682: (*(*s_etat_processus).pointeur_feuille_courante)
683: .variable;
684: }
685: else if ((*(*(*(*(*s_etat_processus).pointeur_feuille_courante)
686: .precedent).precedent).variable).niveau == 1)
687: {
688: (*s_etat_processus).pointeur_feuille_courante =
689: (*(*(*s_etat_processus).pointeur_feuille_courante)
690: .precedent).precedent;
691: (*s_etat_processus).pointeur_variable_courante =
692: (*(*s_etat_processus).pointeur_feuille_courante)
693: .variable;
694: }
695: else
696: {
697: presence_variable = d_faux;
698: }
699:
700: break;
701: }
702: }
703: }
704:
705: if (presence_variable == d_vrai)
706: {
707: if ((*(*s_etat_processus).pointeur_variable_courante).objet == NULL)
708: {
709: // La variable n'est pas globale, elle est partagée.
710: presence_variable = d_faux;
711: (*s_etat_processus).erreur_execution = d_ex_variable_partagee;
712: }
713: }
714:
715: return(presence_variable);
716: }
717:
718:
719: /*
720: ================================================================================
721: Procédure de retrait d'une variable de la base
722: ================================================================================
723: Entrée : type 'G' ou 'L' selon que l'on retire une variable locale (incluant
724: les globales) ou strictement globale.
725: --------------------------------------------------------------------------------
726: Sortie :
727: --------------------------------------------------------------------------------
728: Effets de bord : néant
729: ================================================================================
730: */
731:
732: logical1
733: retrait_variable(struct_processus *s_etat_processus,
734: unsigned char *nom_variable, unsigned char type)
735: {
736: logical1 erreur;
737:
738: struct_arbre_variables *s_arbre_a_supprimer;
739: struct_arbre_variables *s_arbre_courant;
740: struct_arbre_variables *noeud_courant;
741:
742: struct_liste_chainee *l_element_courant;
743: struct_liste_chainee *l_element_precedent;
744:
745: struct_liste_variables *variable_a_supprimer;
746: struct_liste_variables *variables_par_niveau;
747:
748: unsigned long niveau;
749:
750: if (recherche_variable(s_etat_processus, nom_variable) == d_vrai)
751: {
752: // Une variable correspondant au nom recherché est accessible.
753:
754: if (type == 'G')
755: {
756: if ((*(*s_etat_processus).pointeur_variable_courante).niveau > 1)
757: {
758: // La variable obtenue est une variable locale. il faut
759: // s'assurer qu'il existe une variable de niveau 1 de même
760: // nom sur la feuille.
761:
762: if ((*(*(*(*s_etat_processus).pointeur_feuille_courante)
763: .precedent).variable).niveau <= 1)
764: {
765: (*s_etat_processus).pointeur_feuille_courante =
766: (*(*s_etat_processus).pointeur_feuille_courante)
767: .precedent;
768: (*s_etat_processus).pointeur_variable_courante =
769: (*(*s_etat_processus).pointeur_feuille_courante)
770: .variable;
771:
772: // Si la variable retournée est de niveau 0, on regarde
773: // un peu plus loin si une variable de niveau 1 existe.
774:
775: if (((*(*(*s_etat_processus).pointeur_feuille_courante)
776: .variable).niveau == 0) &&
777: ((*(*(*(*s_etat_processus)
778: .pointeur_feuille_courante).precedent).variable)
779: .niveau == 1))
780: {
781: (*s_etat_processus).pointeur_feuille_courante =
782: (*(*s_etat_processus).pointeur_feuille_courante)
783: .precedent;
784: (*s_etat_processus).pointeur_variable_courante =
785: (*(*s_etat_processus).pointeur_feuille_courante)
786: .variable;
787: }
788: }
789: else
790: {
791: // Aucune variable globale (niveau 1) n'existe.
792:
793: erreur = d_erreur;
794: (*s_etat_processus).erreur_execution =
795: d_ex_variable_non_definie;
796: return(erreur);
797: }
798: }
799:
800: if ((*(*s_etat_processus).pointeur_variable_courante)
801: .variable_verrouillee == d_vrai)
802: {
803: erreur = d_erreur;
804: (*s_etat_processus).erreur_execution =
805: d_ex_variable_verrouillee;
806: return(erreur);
807: }
808: }
809:
810: // Suppression de la variable de la liste.
811: // Deux cas peuvent survenir :
812: // 1/ les pointeurs sur la variable et la variable suivante
813: // sont identiques et on supprime la variable ainsi que la feuille
814: // associée ;
815: // 2/ ces deux pointeurs sont différents et se contente de retirer
816: // la structure décrivant la variable.
817:
818: if ((*s_etat_processus).pointeur_feuille_courante ==
819: (*(*s_etat_processus).pointeur_feuille_courante).suivant)
820: {
821: // Cas 1 :
822: // On retire la variable du noeud en décrémentant le nombre
823: // de feuilles de ce noeud. Si le nombre de feuilles du noeud
824: // est nul, on retire les noeuds récursivement jusqu'à obtenir
825: // un nombre non nul de feuilles utilisées (ou la racine des
826: // variables).
827:
828: variable_a_supprimer = (*s_etat_processus)
829: .pointeur_feuille_courante;
830: s_arbre_courant = (*variable_a_supprimer).noeud_pere;
831: noeud_courant = (*variable_a_supprimer).noeud;
832:
833: BUG((*s_arbre_courant).noeuds_utilises == 0,
834: uprintf("Freed node !\n"));
835: (*s_arbre_courant).noeuds_utilises--;
836:
837: while((*s_arbre_courant).noeuds_utilises == 0)
838: {
839: s_arbre_a_supprimer = s_arbre_courant;
840: s_arbre_courant = (*s_arbre_courant).noeud_pere;
841:
842: if (s_arbre_courant == NULL)
843: {
844: free((*s_arbre_a_supprimer).noeuds);
845: free(s_arbre_a_supprimer);
846: break;
847: }
848:
849: // s_arbre_a_supprimer contient la structure de feuille qui
850: // vient d'être libérée. Il s'agit maintenant
851: // d'annuler le pointeur dans le tableau noeuds de la structure
852: // pointée par noeud_pere, soit s_arbre_courant.
853:
854: BUG((*s_arbre_a_supprimer).indice_tableau_pere < 0,
855: uprintf("Invalid pointer !\n"));
856: (*s_arbre_courant).noeuds[(*s_arbre_a_supprimer)
857: .indice_tableau_pere] = NULL;
858:
859: free((*s_arbre_a_supprimer).noeuds);
860: free(s_arbre_a_supprimer);
861:
862: BUG((*s_arbre_courant).noeuds_utilises == 0,
863: uprintf("Freed node !\n"));
864: (*s_arbre_courant).noeuds_utilises--;
865: }
866: }
867: else
868: {
869: // Cas 2 :
870: // On retire la variable de la liste.
871:
872: variable_a_supprimer = (*s_etat_processus)
873: .pointeur_feuille_courante;
874:
875: (*(*(*s_etat_processus).pointeur_feuille_courante).precedent)
876: .suivant = (*(*s_etat_processus).pointeur_feuille_courante)
877: .suivant;
878: (*(*(*s_etat_processus).pointeur_feuille_courante).suivant)
879: .precedent = (*(*s_etat_processus)
880: .pointeur_feuille_courante).precedent;
881:
882: noeud_courant = NULL;
883: }
884:
885: // Dans tous les cas, on retire la variable de la liste des variables
886: // par niveau.
887:
888: niveau = (*(*variable_a_supprimer).variable).niveau;
889: variables_par_niveau = (*s_etat_processus).l_liste_variables_par_niveau;
890:
891: if (variables_par_niveau != NULL)
892: {
893: do
894: {
895: l_element_courant = (*variables_par_niveau).liste;
896:
897: if (l_element_courant != NULL)
898: {
899: if ((*((struct_variable *) (*l_element_courant).donnee))
900: .niveau == niveau)
901: {
902: // On parcourt le bon niveau.
903:
904: l_element_precedent = NULL;
905:
906: while(l_element_courant != NULL)
907: {
908: // Tant que l_element_courant est non nul, il reste
909: // des variables à explorer dans le niveau courant.
910:
911: if ((*l_element_courant).donnee ==
912: (void *) (*variable_a_supprimer).variable)
913: {
914: // On a trouvé la variable à supprimer.
915:
916: if (l_element_precedent == NULL)
917: {
918: (*variables_par_niveau).liste =
919: (*l_element_courant).suivant;
920: }
921: else
922: {
923: (*l_element_precedent).suivant =
924: (*l_element_courant).suivant;
925: }
926:
927: free(l_element_courant);
928: break;
929: }
930:
931: l_element_precedent = l_element_courant;
932: l_element_courant = (*l_element_courant).suivant;
933: }
934: }
935: }
936:
937: variables_par_niveau = (*variables_par_niveau).suivant;
938:
939: } while(variables_par_niveau != (*s_etat_processus)
940: .l_liste_variables_par_niveau);
941: }
942:
943: // Puis on libère le contenu de la variable.
944:
945: free((*(*variable_a_supprimer).variable).nom);
946: liberation(s_etat_processus, (*(*variable_a_supprimer).variable).objet);
947: free((*variable_a_supprimer).variable);
948:
949: erreur = d_absence_erreur;
950:
951: if (noeud_courant != NULL)
952: {
953: free((*noeud_courant).feuille);
954: free((*noeud_courant).noeuds);
955: free(noeud_courant);
956: }
957: }
958: else
959: {
960: // Aucune variable n'est accessible depuis le point courant du
961: // programme.
962:
963: erreur = d_erreur;
964: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
965: }
966:
967: return(erreur);
968: }
969:
970:
971: /*
972: ================================================================================
973: Procédure de retrait des variables de niveau strictement supérieur au
974: niveau courant
975: ================================================================================
976: Entrée :
977: --------------------------------------------------------------------------------
978: Sortie :
979: --------------------------------------------------------------------------------
980: Effets de bord : néant
981: ================================================================================
982: */
983:
984: logical1
985: retrait_variable_par_niveau(struct_processus *s_etat_processus)
986: {
987: struct_liste_variables *l_element_a_supprimer;
988:
989: // Utilisation du champ (*s_etat_processus).liste_variables_par_niveau.
990: // La tête de la pile contient toujours les variables de plus haut niveau
991: // créées.
992:
993: while((*s_etat_processus).l_liste_variables_par_niveau != NULL)
994: {
995: if ((*(*s_etat_processus).l_liste_variables_par_niveau).liste == NULL)
996: {
997: // Si le niveau ne contient aucune variable, on le détruit.
998: // Le pointeur sur la chaîne est déjà nul et il ne reste rien à
999: // faire.
1000: }
1001: else
1002: {
1003: // Le niveau contient des variables.
1004:
1005: if ((*((struct_variable *) (*(*(*s_etat_processus)
1006: .l_liste_variables_par_niveau).liste).donnee)).niveau
1007: <= (*s_etat_processus).niveau_courant)
1008: {
1009: // On a retiré de l'arbre des variables toutes les
1010: // variables de niveau strictement supérieur au niveau
1011: // courant.
1012:
1013: break;
1014: }
1015:
1016: while((*(*s_etat_processus).l_liste_variables_par_niveau).liste
1017: != NULL)
1018: {
1019: // Sauvegarde des variables statiques.
1020:
1021: if ((*((struct_variable *) (*(*(*s_etat_processus)
1022: .l_liste_variables_par_niveau).liste).donnee)).origine
1023: == 'P')
1024: {
1025: if ((*((struct_variable *) (*(*(*s_etat_processus)
1026: .l_liste_variables_par_niveau).liste).donnee))
1027: .variable_statique.adresse != 0)
1028: {
1029: if (recherche_variable_statique(s_etat_processus,
1030: (*((struct_variable *) (*(*(*s_etat_processus)
1031: .l_liste_variables_par_niveau).liste).donnee))
1032: .nom, (*((struct_variable *)
1033: (*(*(*s_etat_processus)
1034: .l_liste_variables_par_niveau).liste).donnee))
1035: .variable_statique, ((*s_etat_processus)
1036: .mode_execution_programme
1037: == 'Y') ? 'P' : 'E') == d_vrai)
1038: {
1039: (*s_etat_processus).s_liste_variables_statiques
1040: [(*s_etat_processus)
1041: .position_variable_statique_courante]
1042: .objet = (*((struct_variable *)
1043: (*(*(*s_etat_processus)
1044: .l_liste_variables_par_niveau).liste)
1045: .donnee)).objet;
1046: }
1047: else
1048: {
1049: (*s_etat_processus).erreur_systeme =
1050: d_es_variable_introuvable;
1051: }
1052:
1053: (*((struct_variable *) (*(*(*s_etat_processus)
1054: .l_liste_variables_par_niveau).liste).donnee))
1055: .objet = NULL;
1056: }
1057: }
1058: else
1059: {
1060: if ((*((struct_variable *) (*(*(*s_etat_processus)
1061: .l_liste_variables_par_niveau).liste).donnee))
1062: .variable_statique.pointeur != NULL)
1063: {
1064: /*
1065: * Gestion des variables statiques
1066: */
1067:
1068: if (recherche_variable_statique(s_etat_processus,
1069: (*((struct_variable *) (*(*(*s_etat_processus)
1070: .l_liste_variables_par_niveau).liste).donnee))
1071: .nom, (*((struct_variable *)
1072: (*(*(*s_etat_processus)
1073: .l_liste_variables_par_niveau).liste).donnee))
1074: .variable_statique, ((*s_etat_processus)
1075: .mode_execution_programme
1076: == 'Y') ? 'P' : 'E') == d_vrai)
1077: {
1078: (*s_etat_processus).s_liste_variables_statiques
1079: [(*s_etat_processus)
1080: .position_variable_statique_courante]
1081: .objet = (*((struct_variable *)
1082: (*(*(*s_etat_processus)
1083: .l_liste_variables_par_niveau).liste)
1084: .donnee)).objet;
1085: }
1086: else
1087: {
1088: (*s_etat_processus).erreur_systeme =
1089: d_es_variable_introuvable;
1090: return(d_erreur);
1091: }
1092:
1093: (*((struct_variable *) (*(*(*s_etat_processus)
1094: .l_liste_variables_par_niveau).liste).donnee))
1095: .objet = NULL;
1096: }
1097: }
1098:
1099: if (retrait_variable(s_etat_processus,
1100: (*((struct_variable *) (*(*(*s_etat_processus)
1101: .l_liste_variables_par_niveau).liste).donnee)).nom,
1102: 'L') == d_erreur)
1103: {
1104: return(d_erreur);
1105: }
1106: }
1107: }
1108:
1109: // On retire l'élément de la liste doublement chaînée et circulaire.
1110:
1111: (*(*(*s_etat_processus).l_liste_variables_par_niveau).precedent).suivant
1112: = (*(*s_etat_processus).l_liste_variables_par_niveau).suivant;
1113: (*(*(*s_etat_processus).l_liste_variables_par_niveau).suivant).precedent
1114: = (*(*s_etat_processus).l_liste_variables_par_niveau).precedent;
1115:
1116: l_element_a_supprimer = (*s_etat_processus)
1117: .l_liste_variables_par_niveau;
1118: (*s_etat_processus).l_liste_variables_par_niveau =
1119: (*l_element_a_supprimer).suivant;
1120: free(l_element_a_supprimer);
1121: }
1122:
1123: return(d_absence_erreur);
1124: }
1125:
1126:
1127: /*
1128: ================================================================================
1129: Procédure de retrait des toutes les variables locales et globales
1130: ================================================================================
1131: Entrée : drapeau indiquant s'il faut retirer les définitions (variables
1132: de niveau 0)
1133: --------------------------------------------------------------------------------
1134: Sortie :
1135: --------------------------------------------------------------------------------
1136: Effets de bord : néant
1137: ================================================================================
1138: */
1139:
1140: void
1141: liberation_arbre_variables(struct_processus *s_etat_processus,
1142: struct_arbre_variables *arbre, logical1 retrait_definitions)
1143: {
1144: int i;
1145:
1146: struct_liste_chainee *l_element_courant_liste;
1147: struct_liste_chainee *l_element_suivant_liste;
1148:
1149: struct_liste_variables *l_element_courant;
1150: struct_liste_variables *l_element_suivant;
1151:
1152: // Libération de l'arbre des variables. Le contenu des variables n'est
1153: // pas détruit par cette opération, il sera détruit lors de la libération
1154: // de la liste des variables par niveau.
1155:
1156: l_element_courant = (*arbre).feuille;
1157:
1158: if (l_element_courant != NULL)
1159: {
1160: do
1161: {
1162: l_element_suivant = (*l_element_courant).suivant;
1163: free(l_element_courant);
1164: l_element_courant = l_element_suivant;
1165: } while(l_element_courant != (*arbre).feuille);
1166: }
1167:
1168: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
1169: {
1170: if ((*arbre).noeuds[i] != NULL)
1171: {
1172: liberation_arbre_variables(s_etat_processus, (*arbre).noeuds[i],
1173: retrait_definitions);
1174: }
1175: }
1176:
1177: // Suppression de la liste des variables par niveau.
1178:
1179: if (arbre == (*s_etat_processus).s_arbre_variables)
1180: {
1181: l_element_courant = (*s_etat_processus).l_liste_variables_par_niveau;
1182:
1183: if (l_element_courant != NULL)
1184: {
1185: do
1186: {
1187: l_element_courant_liste = (*l_element_courant).liste;
1188:
1189: while(l_element_courant_liste != NULL)
1190: {
1191: if ((retrait_definitions == d_vrai) ||
1192: ((*((struct_variable *) (*l_element_courant_liste)
1193: .donnee)).niveau >= 1))
1194: {
1195: liberation(s_etat_processus, (*((struct_variable *)
1196: (*l_element_courant_liste).donnee)).objet);
1197: free((*((struct_variable *) (*l_element_courant_liste)
1198: .donnee)).nom);
1199: free((*l_element_courant_liste).donnee);
1200: }
1201:
1202: l_element_suivant_liste =
1203: (*l_element_courant_liste).suivant;
1204: free(l_element_courant_liste);
1205: l_element_courant_liste = l_element_suivant_liste;
1206: }
1207:
1208: l_element_suivant = (*l_element_courant).suivant;
1209: free(l_element_courant);
1210: l_element_courant = l_element_suivant;
1211: } while(l_element_courant != (*s_etat_processus)
1212: .l_liste_variables_par_niveau);
1213: }
1214: }
1215:
1216: free((*arbre).noeuds);
1217: free(arbre);
1218:
1219: return;
1220: }
1221:
1222:
1223: /*
1224: ================================================================================
1225: Procédure de copie de l'arbre des variables
1226: ================================================================================
1227: Entrée :
1228: --------------------------------------------------------------------------------
1229: Sortie :
1230: --------------------------------------------------------------------------------
1231: Effets de bord : néant
1232: ================================================================================
1233: */
1234:
1235: struct_arbre_variables *
1236: copie_arbre_variables(struct_processus *s_etat_processus)
1237: {
1238: // Les définitions sont partagées entre tous les threads et ne sont pas
1239: // copiées.
1240: //
1241: // NB : on ne copie que les variables de niveaux 0 et 1, les autres
1242: // variables locales étant masquées par le processus de création de thread
1243: // ou de processus, elles sont inaccessibles.
1244:
1245: BUG(1, uprintf("Oops !\n"));
1246:
1247: return(d_absence_erreur);
1248: }
1249:
1250:
1251: /*
1252: ================================================================================
1253: Procédure d'initialisation de la table de correspondance des variables
1254: ================================================================================
1255: Entrée :
1256: --------------------------------------------------------------------------------
1257: Sortie :
1258: --------------------------------------------------------------------------------
1259: Effets de bord : néant
1260: ================================================================================
1261: */
1262:
1263: /*
1264: * Caractères autorisés dans les instructions
1265: *
1266: * A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
1267: * a b c d e f g h i j k l m n o p q r s t u v w x y z
1268: * _
1269: * 1 2 3 4 5 6 7 8 9 0
1270: */
1271:
1272: void
1273: initialisation_variables(struct_processus *s_etat_processus)
1274: {
1275: int decalage;
1276: int i;
1277: int longueur_tableau;
1278:
1279: unsigned char caractere;
1280:
1281: // Récupération de la longueur d'un unsigned char
1282:
1283: longueur_tableau = 1;
1284: decalage = 0;
1285: caractere = 1;
1286:
1287: while((1L << decalage) == (long) ((unsigned char) (caractere << decalage)))
1288: {
1289: decalage++;
1290: longueur_tableau *= 2;
1291: }
1292:
1293: if (((*s_etat_processus).pointeurs_caracteres_variables =
1294: malloc(longueur_tableau * sizeof(int))) == NULL)
1295: {
1296: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
1297: return;
1298: }
1299:
1300: for(i = 0; i < longueur_tableau; i++)
1301: {
1302: (*s_etat_processus).pointeurs_caracteres_variables[i] = -1;
1303: }
1304:
1305: (*s_etat_processus).nombre_caracteres_variables = 0;
1306:
1307: #define DECLARATION_CARACTERE(c) \
1308: do { (*s_etat_processus).pointeurs_caracteres_variables[c] = \
1309: (*s_etat_processus).nombre_caracteres_variables++; } while(0)
1310:
1311: DECLARATION_CARACTERE('A');
1312: DECLARATION_CARACTERE('B');
1313: DECLARATION_CARACTERE('C');
1314: DECLARATION_CARACTERE('D');
1315: DECLARATION_CARACTERE('E');
1316: DECLARATION_CARACTERE('F');
1317: DECLARATION_CARACTERE('G');
1318: DECLARATION_CARACTERE('H');
1319: DECLARATION_CARACTERE('I');
1320: DECLARATION_CARACTERE('J');
1321: DECLARATION_CARACTERE('K');
1322: DECLARATION_CARACTERE('L');
1323: DECLARATION_CARACTERE('M');
1324: DECLARATION_CARACTERE('N');
1325: DECLARATION_CARACTERE('O');
1326: DECLARATION_CARACTERE('P');
1327: DECLARATION_CARACTERE('Q');
1328: DECLARATION_CARACTERE('R');
1329: DECLARATION_CARACTERE('S');
1330: DECLARATION_CARACTERE('T');
1331: DECLARATION_CARACTERE('U');
1332: DECLARATION_CARACTERE('V');
1333: DECLARATION_CARACTERE('W');
1334: DECLARATION_CARACTERE('X');
1335: DECLARATION_CARACTERE('Y');
1336: DECLARATION_CARACTERE('Z');
1337:
1338: DECLARATION_CARACTERE('a');
1339: DECLARATION_CARACTERE('b');
1340: DECLARATION_CARACTERE('c');
1341: DECLARATION_CARACTERE('d');
1342: DECLARATION_CARACTERE('e');
1343: DECLARATION_CARACTERE('f');
1344: DECLARATION_CARACTERE('g');
1345: DECLARATION_CARACTERE('h');
1346: DECLARATION_CARACTERE('i');
1347: DECLARATION_CARACTERE('j');
1348: DECLARATION_CARACTERE('k');
1349: DECLARATION_CARACTERE('l');
1350: DECLARATION_CARACTERE('m');
1351: DECLARATION_CARACTERE('n');
1352: DECLARATION_CARACTERE('o');
1353: DECLARATION_CARACTERE('p');
1354: DECLARATION_CARACTERE('q');
1355: DECLARATION_CARACTERE('r');
1356: DECLARATION_CARACTERE('s');
1357: DECLARATION_CARACTERE('t');
1358: DECLARATION_CARACTERE('u');
1359: DECLARATION_CARACTERE('v');
1360: DECLARATION_CARACTERE('w');
1361: DECLARATION_CARACTERE('x');
1362: DECLARATION_CARACTERE('y');
1363: DECLARATION_CARACTERE('z');
1364:
1365: DECLARATION_CARACTERE('_');
1366:
1367: DECLARATION_CARACTERE('1');
1368: DECLARATION_CARACTERE('2');
1369: DECLARATION_CARACTERE('3');
1370: DECLARATION_CARACTERE('4');
1371: DECLARATION_CARACTERE('5');
1372: DECLARATION_CARACTERE('6');
1373: DECLARATION_CARACTERE('7');
1374: DECLARATION_CARACTERE('8');
1375: DECLARATION_CARACTERE('9');
1376: DECLARATION_CARACTERE('0');
1377: #undef DECLARATION_CARACTERE
1378:
1379: return;
1380: }
1381:
1382: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>