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: Fonction de debug
29: ================================================================================
30: Entrée :
31: --------------------------------------------------------------------------------
32: Sortie :
33: --------------------------------------------------------------------------------
34: Effets de bords : néant
35: ================================================================================
36: */
37:
38: static void
39: liste_variables_par_niveaux(struct_processus *s_etat_processus)
40: {
41: int c;
42:
43: logical1 fin;
44:
45: struct_liste_variables *l;
46:
47: struct_liste_chainee *e;
48:
49: printf("=========================================================="
50: "======================\n");
51: printf(" Liste des variables par niveaux\n");
52: printf("=========================================================="
53: "======================\n");
54:
55: if ((*s_etat_processus).l_liste_variables_par_niveau == NULL)
56: {
57: printf("=========================================================="
58: "======================\n");
59: return;
60: }
61:
62: printf("Backward\n");
63: l = (*s_etat_processus).l_liste_variables_par_niveau;
64: c = 0;
65: fin = d_faux;
66:
67: do
68: {
69: l = l->precedent;
70: e = l->liste;
71:
72: while(e != NULL)
73: {
74: printf("%s (%p->%p, %d) ", ((struct_variable *) e->donnee)->nom,
75: e, e->donnee, ((struct_variable *) e->donnee)->niveau);
76: e = e->suivant;
77: c++;
78: if (c > 100)
79: {
80: fin = d_vrai;
81: break;
82: }
83: }
84:
85: printf("\n");
86:
87: } while(l != (*s_etat_processus).l_liste_variables_par_niveau);
88:
89: printf("Forward\n");
90: l = (*s_etat_processus).l_liste_variables_par_niveau;
91: c = 0;
92:
93: do
94: {
95: e = l->liste;
96:
97: while(e != NULL)
98: {
99: printf("%s (%p->%p, %d) ", ((struct_variable *) e->donnee)->nom,
100: e, e->donnee, ((struct_variable *) e->donnee)->niveau);
101: e = e->suivant;
102: c++;
103: if (c > 100) exit(0);
104: }
105:
106: printf("\n");
107:
108: l = l->suivant;
109: } while(l != (*s_etat_processus).l_liste_variables_par_niveau);
110:
111: printf("=========================================================="
112: "======================\n");
113:
114: if (fin == d_vrai) exit(0);
115:
116: return;
117: }
118:
119: static void
120: liste_variables_tas(struct_processus *s_etat_processus,
121: struct_arbre_variables *arbre)
122: {
123: int c;
124: int i;
125:
126: logical1 fin;
127:
128: struct_liste_variables *l;
129:
130: fin = d_faux;
131:
132: if (arbre == NULL)
133: {
134: return;
135: }
136:
137: printf(">>> Position : %d\n",
138: (*arbre).indice_tableau_pere);
139: printf(">>> Nombre de noeuds utilisés : %u\n",
140: (*arbre).noeuds_utilises);
141: printf(">>> Noeuds fils : ");
142:
143: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
144: {
145: if ((*arbre).noeuds[i] != NULL)
146: {
147: printf("%d ", i);
148: }
149: }
150:
151: printf("\b\n");
152:
153: if ((*arbre).feuille != NULL)
154: {
155: printf("Feuille %p [%d]\n", (*arbre).feuille, (*arbre).noeuds_utilises);
156:
157: printf(" Backward\n");
158:
159: l = (*arbre).feuille;
160: c = 0;
161: fin = d_faux;
162:
163: do
164: {
165: l = l->precedent;
166: c++;
167: if (c > 100)
168: {
169: fin = d_vrai;
170: break;
171: }
172: printf(" %s (%p, %d)\n", l->variable->nom, l->variable,
173: l->variable->niveau);
174: } while((*arbre).feuille != l);
175:
176: printf(" Forward\n");
177:
178: l = (*arbre).feuille;
179: c = 0;
180:
181: do
182: {
183: c++;
184: if (c > 100) exit(0);
185: printf(" %s (%p, %d)\n", l->variable->nom, l->variable,
186: l->variable->niveau);
187: l = l->suivant;
188: } while((*arbre).feuille != l);
189: }
190:
191: printf("----------------------------------------------------------"
192: "----------------------\n");
193:
194: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
195: {
196: if ((*arbre).noeuds[i] != NULL)
197: {
198:
199: liste_variables_tas(s_etat_processus, (*arbre).noeuds[i]);
200: }
201: }
202:
203: if (fin == d_vrai) exit(0);
204:
205: return;
206: }
207:
208:
209: static void
210: liste_variables_par_feuilles(struct_processus *s_etat_processus)
211: {
212: printf("=========================================================="
213: "======================\n");
214: printf(" Liste des variables sur le tas\n");
215: printf("=========================================================="
216: "======================\n");
217:
218: liste_variables_tas(s_etat_processus,
219: (*s_etat_processus).s_arbre_variables);
220:
221: printf("=========================================================="
222: "======================\n");
223:
224: return;
225: }
226:
227:
228: /*
229: ================================================================================
230: Routine de gestion du cache mémoire sur l'arbre des variables
231: ================================================================================
232: Entrée :
233: --------------------------------------------------------------------------------
234: Sortie :
235: --------------------------------------------------------------------------------
236: Effets de bords : néant
237: ================================================================================
238: */
239:
240: struct_arbre_variables *
241: allocation_noeud(struct_processus *s_etat_processus)
242: {
243: struct_arbre_variables *objet;
244:
245: if ((*s_etat_processus).pointeur_variables_noeud > 0)
246: {
247: objet = (*s_etat_processus).variables_noeud
248: [--(*s_etat_processus).pointeur_variables_noeud];
249: }
250: else
251: {
252: objet = malloc(sizeof(struct_arbre_variables));
253: }
254:
255: return(objet);
256: }
257:
258: static inline void
259: liberation_noeud(struct_processus *s_etat_processus,
260: struct_arbre_variables *objet)
261: {
262: if ((*s_etat_processus).pointeur_variables_noeud < TAILLE_CACHE)
263: {
264: (*s_etat_processus).variables_noeud
265: [(*s_etat_processus).pointeur_variables_noeud++] = objet;
266: }
267: else
268: {
269: free(objet);
270: }
271:
272: return;
273: }
274:
275: struct_arbre_variables **
276: allocation_tableau_noeuds(struct_processus *s_etat_processus)
277: {
278: struct_arbre_variables **objet;
279:
280: if ((*s_etat_processus).pointeur_variables_tableau_noeuds > 0)
281: {
282: objet = (*s_etat_processus).variables_tableau_noeuds
283: [--(*s_etat_processus).pointeur_variables_tableau_noeuds];
284: }
285: else
286: {
287: objet = malloc(((size_t) (*s_etat_processus)
288: .nombre_caracteres_variables)
289: * sizeof(struct_arbre_variables *));
290: }
291:
292: return(objet);
293: }
294:
295: static inline void
296: liberation_tableau_noeuds(struct_processus *s_etat_processus,
297: struct_arbre_variables **objet)
298: {
299: if ((*s_etat_processus).pointeur_variables_tableau_noeuds < TAILLE_CACHE)
300: {
301: (*s_etat_processus).variables_tableau_noeuds
302: [(*s_etat_processus).pointeur_variables_tableau_noeuds++] =
303: objet;
304: }
305: else
306: {
307: free(objet);
308: }
309:
310: return;
311: }
312:
313: static inline struct_liste_variables *
314: allocation_feuille(struct_processus *s_etat_processus)
315: {
316: struct_liste_variables *objet;
317:
318: if ((*s_etat_processus).pointeur_variables_feuille > 0)
319: {
320: objet = (*s_etat_processus).variables_feuille
321: [--(*s_etat_processus).pointeur_variables_feuille];
322: }
323: else
324: {
325: objet = malloc(sizeof(struct_liste_variables));
326: }
327:
328: return(objet);
329: }
330:
331: static inline void
332: liberation_feuille(struct_processus *s_etat_processus,
333: struct_liste_variables *objet)
334: {
335: if ((*s_etat_processus).pointeur_variables_feuille < TAILLE_CACHE)
336: {
337: (*s_etat_processus).variables_feuille
338: [(*s_etat_processus).pointeur_variables_feuille++] = objet;
339: }
340: else
341: {
342: free(objet);
343: }
344:
345: return;
346: }
347:
348: static inline struct_variable *
349: allocation_variable(struct_processus *s_etat_processus)
350: {
351: struct_variable *objet;
352:
353: if ((*s_etat_processus).pointeur_variables_variable > 0)
354: {
355: objet = (*s_etat_processus).variables_variable
356: [--(*s_etat_processus).pointeur_variables_variable];
357: }
358: else
359: {
360: objet = malloc(sizeof(struct_variable));
361: }
362:
363: return(objet);
364: }
365:
366: static inline void
367: liberation_variable(struct_processus *s_etat_processus,
368: struct_variable *objet)
369: {
370: if ((*s_etat_processus).pointeur_variables_variable < TAILLE_CACHE)
371: {
372: (*s_etat_processus).variables_variable
373: [(*s_etat_processus).pointeur_variables_variable++] = objet;
374: }
375: else
376: {
377: free(objet);
378: }
379:
380: return;
381: }
382:
383:
384: /*
385: ================================================================================
386: Routine de création d'une nouvelle variable
387: ================================================================================
388: Entrée : autorisation_creation_variable_statique vaut 'v' ou 's'.
389: dans le cas 'v', la variable est volatile.
390: dans le cas 's', elle est statique.
391: Entrée : autorisation_creation_variable_partagee vaut 'p' ou 's'.
392: dans le cas 'p', la variable est privée.
393: dans le cas 's', elle est partagée.
394: --------------------------------------------------------------------------------
395: Sortie :
396: --------------------------------------------------------------------------------
397: Effets de bords : néant
398: ================================================================================
399: */
400:
401: static logical1
402: ajout_variable(struct_processus *s_etat_processus, struct_variable *s_variable)
403: {
404: int i;
405:
406: logical1 niveau_acceptable;
407:
408: struct_liste_variables *l_nouvelle_variable;
409: struct_liste_variables *l_variable_candidate;
410:
411: struct_arbre_variables *l_variable_courante;
412: struct_arbre_variables *l_variable_precedente;
413:
414: struct_liste_chainee *l_nouvel_element;
415:
416: unsigned char *ptr;
417:
418: void *pointeur_variable_cree;
419:
420: if ((*s_etat_processus).s_arbre_variables == NULL)
421: {
422: if (((*s_etat_processus).s_arbre_variables =
423: allocation_noeud(s_etat_processus)) == NULL)
424: {
425: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
426: return(d_erreur);
427: }
428:
429: (*(*s_etat_processus).s_arbre_variables).feuille = NULL;
430: (*(*s_etat_processus).s_arbre_variables).feuille_statique = NULL;
431: (*(*s_etat_processus).s_arbre_variables).noeuds_utilises = 0;
432: (*(*s_etat_processus).s_arbre_variables).indice_tableau_pere = -1;
433: (*(*s_etat_processus).s_arbre_variables).noeud_pere = NULL;
434:
435: if (((*(*s_etat_processus).s_arbre_variables).noeuds =
436: allocation_tableau_noeuds(s_etat_processus)) == NULL)
437: {
438: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
439: return(d_erreur);
440: }
441:
442: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
443: {
444: (*(*s_etat_processus).s_arbre_variables).noeuds[i] = NULL;
445: }
446: }
447:
448: l_variable_precedente = NULL;
449: l_variable_courante = (*s_etat_processus).s_arbre_variables;
450: ptr = (*s_variable).nom;
451:
452: while((*ptr) != d_code_fin_chaine)
453: {
454: BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0,
455: uprintf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom,
456: *ptr));
457:
458: if ((*l_variable_courante).noeuds[(*s_etat_processus)
459: .pointeurs_caracteres_variables[*ptr]] == NULL)
460: {
461: // Le noeud n'existe pas encore, on le crée et on le marque
462: // comme utilisé dans la structure parente.
463:
464: if (((*l_variable_courante).noeuds[(*s_etat_processus)
465: .pointeurs_caracteres_variables[*ptr]] =
466: allocation_noeud(s_etat_processus)) == NULL)
467: {
468: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
469: return(d_erreur);
470: }
471:
472: (*l_variable_courante).noeuds_utilises++;
473:
474: // La feuille est par défaut vide et aucun élément du tableau noeuds
475: // (les branches qui peuvent être issues de ce nouveau noeud)
476: // n'est encore utilisée.
477:
478: (*(*l_variable_courante).noeuds[(*s_etat_processus)
479: .pointeurs_caracteres_variables[*ptr]]).feuille = NULL;
480: (*(*l_variable_courante).noeuds[(*s_etat_processus)
481: .pointeurs_caracteres_variables[*ptr]]).feuille_statique
482: = NULL;
483: (*(*l_variable_courante).noeuds[(*s_etat_processus)
484: .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises = 0;
485:
486: // Le champ noeud_pere de la structure créée pointe sur
487: // la structure parente et l'indice tableau_pere correspond à la
488: // position réelle dans le tableau noeuds[] de la structure parente
489: // du noeud courant. Cette valeur sera utilisée lors de la
490: // destruction du noeud pour annuler le pointeur contenu dans
491: // le tableau noeuds[] de la structure parente.
492:
493: (*(*l_variable_courante).noeuds[(*s_etat_processus)
494: .pointeurs_caracteres_variables[*ptr]]).noeud_pere =
495: l_variable_courante;
496: (*(*l_variable_courante).noeuds[(*s_etat_processus)
497: .pointeurs_caracteres_variables[*ptr]])
498: .indice_tableau_pere = (*s_etat_processus)
499: .pointeurs_caracteres_variables[*ptr];
500:
501: // Allocation du tableau noeuds[] et initialisation à zéro de
502: // tous les pointeurs.
503:
504: if (((*(*l_variable_courante).noeuds[(*s_etat_processus)
505: .pointeurs_caracteres_variables[*ptr]]).noeuds =
506: allocation_tableau_noeuds(s_etat_processus)) == NULL)
507: {
508: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
509: return(d_erreur);
510: }
511:
512: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
513: {
514: (*(*l_variable_courante).noeuds[(*s_etat_processus)
515: .pointeurs_caracteres_variables[*ptr]]).noeuds[i]
516: = NULL;
517: }
518: }
519:
520: l_variable_precedente = l_variable_courante;
521: l_variable_courante = (*l_variable_courante).noeuds
522: [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]];
523: ptr++;
524: }
525:
526: if ((*l_variable_courante).feuille == NULL)
527: {
528: // Aucune variable de même nom préexiste. On alloue le premier
529: // élément de la liste doublement chaînée contenant toutes les
530: // variables de même nom. Cette liste boucle en premier lieu sur
531: // elle-même.
532:
533: if (((*l_variable_courante).feuille = allocation_feuille(
534: s_etat_processus)) == NULL)
535: {
536: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
537: return(d_erreur);
538: }
539:
540: (*l_variable_courante).noeuds_utilises++;
541:
542: (*(*l_variable_courante).feuille).suivant =
543: (*l_variable_courante).feuille;
544: (*(*l_variable_courante).feuille).precedent =
545: (*l_variable_courante).feuille;
546: (*(*l_variable_courante).feuille).noeud_pere = l_variable_precedente;
547: (*(*l_variable_courante).feuille).noeud = l_variable_courante;
548:
549: // Allocation de la variable sur l'élément de la liste.
550:
551: if (((*(*l_variable_courante).feuille).variable =
552: allocation_variable(s_etat_processus)) == NULL)
553: {
554: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
555: return(d_erreur);
556: }
557:
558: (*((struct_variable *) (*(*l_variable_courante).feuille).variable)) =
559: (*s_variable);
560: pointeur_variable_cree = (*(*l_variable_courante).feuille).variable;
561: }
562: else
563: {
564: if ((l_nouvelle_variable = allocation_feuille(s_etat_processus))
565: == NULL)
566: {
567: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
568: return(d_erreur);
569: }
570:
571: if ((*s_variable).niveau > 1)
572: {
573: // Cas d'une variable locale
574:
575: // Si le niveau de la dernière variable de même nom est
576: // supérieur au niveau de la variable locale que l'on veut
577: // enregistrer dans la liste, cette liste est incohérente.
578:
579: BUG((*(*(*l_variable_courante).feuille).variable).niveau >=
580: (*s_variable).niveau,
581: uprintf("Variable=\"%s\"\n", (*s_variable).nom));
582:
583: // On ajoute la variable à la liste existante.
584:
585: (*l_nouvelle_variable).suivant = (*l_variable_courante).feuille;
586: (*l_nouvelle_variable).precedent = (*(*l_variable_courante).feuille)
587: .precedent;
588: (*l_nouvelle_variable).noeud_pere = l_variable_precedente;
589: (*l_nouvelle_variable).noeud = l_variable_courante;
590: (*(*(*l_variable_courante).feuille).precedent).suivant =
591: l_nouvelle_variable;
592: (*(*l_variable_courante).feuille).precedent =
593: l_nouvelle_variable;
594: (*l_variable_courante).feuille = l_nouvelle_variable;
595:
596: if (((*(*l_variable_courante).feuille).variable =
597: allocation_variable(s_etat_processus)) == NULL)
598: {
599: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
600: return(d_erreur);
601: }
602:
603: (*((struct_variable *) (*(*l_variable_courante).feuille).variable))
604: = (*s_variable);
605: pointeur_variable_cree = (*(*l_variable_courante).feuille).variable;
606: }
607: else
608: {
609: // Cas d'une variable globale (niveau 0 [définitions] ou 1
610: // [variables globales])
611:
612: l_variable_candidate = (*l_variable_courante).feuille;
613:
614: do
615: {
616: // S'il y a déjà une variable de même niveau, la pile
617: // est incohérente.
618:
619: BUG((*(*l_variable_candidate).variable).niveau ==
620: (*s_variable).niveau,
621: uprintf("Variable=\"%s\"\n", (*s_variable).nom));
622:
623: l_variable_candidate = (*l_variable_candidate).precedent;
624: } while((l_variable_candidate != (*l_variable_courante).feuille) &&
625: ((*(*l_variable_candidate).variable).niveau <= 1));
626:
627: BUG((*s_variable).niveau == 0,
628: uprintf("Attempt to create a level-0 variable!\n"));
629:
630: if ((*(*(*(*l_variable_courante).feuille).precedent).variable)
631: .niveau > 1)
632: {
633: // La variable précédente est de niveau strictement supérieur
634: // à 1. Il ne peut donc y avoir aucune variable de niveau
635: // inférieur ou égal à 1 puisque la boucle est triée.
636: // On insère donc directement la variable en queue.
637: }
638: else
639: {
640: // Le niveau de la variable précédente dans la boucle est
641: // inférieur ou égal à 1.
642: l_variable_candidate = (*(*l_variable_courante).feuille)
643: .precedent;
644: }
645:
646: (*l_nouvelle_variable).suivant = l_variable_candidate;
647: (*l_nouvelle_variable).precedent = (*l_variable_candidate)
648: .precedent;
649: (*l_nouvelle_variable).noeud_pere = l_variable_precedente;
650: (*l_nouvelle_variable).noeud = l_variable_courante;
651: (*(*l_variable_candidate).precedent).suivant = l_nouvelle_variable;
652: (*l_variable_candidate).precedent = l_nouvelle_variable;
653:
654: // Si la variable suivant la variable que l'on vient d'insérer
655: // dans la boucle est de niveau 0, la variable insérée est par
656: // construction de niveau 1 et il convient de modifier le
657: // pointeur de feuille pointant sur l'élément de plus haut niveau
658: // de la boucle.
659:
660: if ((*(*(*l_nouvelle_variable).precedent).variable).niveau == 0)
661: {
662: (*(*l_nouvelle_variable).noeud).feuille = l_nouvelle_variable;
663: }
664:
665: if (((*l_nouvelle_variable).variable =
666: allocation_variable(s_etat_processus)) == NULL)
667: {
668: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
669: return(d_erreur);
670: }
671:
672: (*(*l_nouvelle_variable).variable) = (*s_variable);
673: pointeur_variable_cree = (*l_nouvelle_variable).variable;
674: }
675: }
676:
677: // Ajout de la variable nouvellement créée à la liste par niveaux.
678: // Le pointeur contenu dans la structure de description du processus indique
679: // toujours le plus haut niveau utilisé.
680:
681: if ((*s_etat_processus).l_liste_variables_par_niveau == NULL)
682: {
683: // Le niveau courant n'existe pas. Il est créé.
684:
685: if ((l_nouvelle_variable = allocation_feuille(s_etat_processus))
686: == NULL)
687: {
688: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
689: return(d_erreur);
690: }
691:
692: (*l_nouvelle_variable).suivant = l_nouvelle_variable;
693: (*l_nouvelle_variable).precedent = l_nouvelle_variable;
694: (*l_nouvelle_variable).noeud_pere = NULL;
695: (*l_nouvelle_variable).liste = NULL;
696:
697: (*s_etat_processus).l_liste_variables_par_niveau = l_nouvelle_variable;
698:
699: // Ajout de la variable en tête de la liste
700:
701: if ((l_nouvel_element = allocation_maillon(s_etat_processus)) == NULL)
702: {
703: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
704: return(d_erreur);
705: }
706:
707: (*l_nouvel_element).suivant = (*(*s_etat_processus)
708: .l_liste_variables_par_niveau).liste;
709: (*l_nouvel_element).donnee = pointeur_variable_cree;
710: (*(*s_etat_processus).l_liste_variables_par_niveau).liste =
711: l_nouvel_element;
712: }
713: else if ((*s_variable).niveau > (*((struct_variable *)
714: (*(*(*s_etat_processus).l_liste_variables_par_niveau).liste)
715: .donnee)).niveau)
716: {
717: // Le niveau courant n'existe pas. Il est créé.
718:
719: if ((l_nouvelle_variable = allocation_feuille(s_etat_processus))
720: == NULL)
721: {
722: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
723: return(d_erreur);
724: }
725:
726: (*l_nouvelle_variable).suivant = (*s_etat_processus)
727: .l_liste_variables_par_niveau;
728: (*l_nouvelle_variable).precedent = (*(*s_etat_processus)
729: .l_liste_variables_par_niveau).precedent;
730: (*l_nouvelle_variable).noeud_pere = NULL;
731: (*l_nouvelle_variable).liste = NULL;
732: (*(*(*s_etat_processus).l_liste_variables_par_niveau).precedent)
733: .suivant = l_nouvelle_variable;
734: (*(*s_etat_processus).l_liste_variables_par_niveau)
735: .precedent = l_nouvelle_variable;
736:
737: (*s_etat_processus).l_liste_variables_par_niveau = l_nouvelle_variable;
738:
739: // Ajout de la variable en tête de la liste
740:
741: if ((l_nouvel_element = allocation_maillon(s_etat_processus)) == NULL)
742: {
743: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
744: return(d_erreur);
745: }
746:
747: (*l_nouvel_element).suivant = (*(*s_etat_processus)
748: .l_liste_variables_par_niveau).liste;
749: (*l_nouvel_element).donnee = pointeur_variable_cree;
750: (*(*s_etat_processus).l_liste_variables_par_niveau).liste =
751: l_nouvel_element;
752: }
753: else if ((*s_variable).niveau <= 1)
754: {
755: // Création d'une variable de niveau 0 ou 1. Il convient de
756: // chercher dans la liste si un niveau 0 ou 1 préexiste. Pour cela, on
757: // regarde la position courante et les deux précédentes.
758:
759: l_variable_candidate = (*s_etat_processus).l_liste_variables_par_niveau;
760: niveau_acceptable = d_faux;
761:
762: for(i = 0; i <= 2; i++)
763: {
764: if ((*l_variable_candidate).liste == NULL)
765: {
766: continue;
767: }
768:
769: if ((*((struct_variable *) (*(*l_variable_candidate)
770: .liste).donnee)).niveau == (*s_variable).niveau)
771: {
772: niveau_acceptable = d_vrai;
773: break;
774: }
775:
776: l_variable_candidate = (*l_variable_candidate).precedent;
777: }
778:
779: if (niveau_acceptable == d_faux)
780: {
781: if ((l_nouvelle_variable = allocation_feuille(s_etat_processus))
782: == NULL)
783: {
784: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
785: return(d_erreur);
786: }
787:
788: l_variable_candidate =
789: (*(*s_etat_processus).l_liste_variables_par_niveau)
790: .precedent;
791:
792: // On ne peut créer qu'une variable de niveau supérieur ou égal à
793: // 1 lors de l'exécution normale d'un programme. Les variables
794: // de niveau 0 sont créées à l'initialisation et relèvent du
795: // cas précédent car il n'existe lors de leur création aucun
796: // niveau non nul.
797:
798: BUG((*s_variable).niveau == 0,
799: uprintf("Attempt to create a level-0 variable!\n"));
800:
801: (*l_nouvelle_variable).suivant = l_variable_candidate;
802: (*l_nouvelle_variable).precedent = (*l_variable_candidate)
803: .precedent;
804: (*l_nouvelle_variable).noeud_pere = NULL;
805: (*l_nouvelle_variable).liste = NULL;
806: (*(*l_variable_candidate).precedent).suivant = l_nouvelle_variable;
807: (*l_variable_candidate).precedent = l_nouvelle_variable;
808:
809: l_variable_candidate = l_nouvelle_variable;
810: }
811:
812: // Ajout de la variable en tête de la liste l_variable_candidate.
813:
814: if ((l_nouvel_element = allocation_maillon(s_etat_processus)) == NULL)
815: {
816: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
817: return(d_erreur);
818: }
819:
820: (*l_nouvel_element).suivant = (*l_variable_candidate).liste;
821: (*l_nouvel_element).donnee = pointeur_variable_cree;
822: (*l_variable_candidate).liste = l_nouvel_element;
823: }
824: else
825: {
826: // Ajout de la variable en tête de la liste
827:
828: if ((l_nouvel_element = allocation_maillon(s_etat_processus)) == NULL)
829: {
830: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
831: return(d_erreur);
832: }
833:
834: (*l_nouvel_element).suivant = (*(*s_etat_processus)
835: .l_liste_variables_par_niveau).liste;
836: (*l_nouvel_element).donnee = pointeur_variable_cree;
837: (*(*s_etat_processus).l_liste_variables_par_niveau).liste =
838: l_nouvel_element;
839: }
840:
841: return(d_absence_erreur);
842: }
843:
844:
845: logical1
846: creation_variable(struct_processus *s_etat_processus,
847: struct_variable *s_variable,
848: unsigned char autorisation_creation_variable_statique,
849: unsigned char autorisation_creation_variable_partagee)
850: {
851: if ((*s_etat_processus).mode_execution_programme == 'Y')
852: {
853: (*s_variable).origine = 'P';
854: }
855: else
856: {
857: (*s_variable).origine = 'E';
858: }
859:
860: if ((*s_variable).niveau == 0)
861: {
862: // Un point d'entrée de définition est verrouillé.
863:
864: if ((*s_variable).origine == 'P')
865: {
866: (*s_variable).variable_statique.adresse = 0;
867: (*s_variable).variable_partagee.adresse = 0;
868: }
869: else
870: {
871: (*s_variable).variable_statique.pointeur = NULL;
872: (*s_variable).variable_partagee.pointeur = NULL;
873: }
874:
875: (*s_variable).variable_verrouillee = d_vrai;
876: }
877: else if ((*s_variable).niveau == 1)
878: {
879: // Une variable globale ne peut être statique.
880:
881: if ((*s_variable).origine == 'P')
882: {
883: (*s_variable).variable_statique.adresse = 0;
884: (*s_variable).variable_partagee.adresse = 0;
885: }
886: else
887: {
888: (*s_variable).variable_statique.pointeur = NULL;
889: (*s_variable).variable_partagee.pointeur = NULL;
890: }
891:
892: (*s_variable).variable_verrouillee = d_faux;
893: }
894: else
895: {
896: // 0 -> variable volatile
897: // adresse de création -> variable statique
898:
899: if (autorisation_creation_variable_statique == 'V')
900: {
901: if (autorisation_creation_variable_partagee == 'S')
902: {
903: // On force la création d'une variable partagée
904:
905: if ((*s_variable).origine == 'P')
906: {
907: (*s_variable).variable_statique.adresse = 0;
908: (*s_variable).variable_partagee.adresse =
909: (*s_etat_processus).position_courante;
910: }
911: else
912: {
913: (*s_variable).variable_statique.pointeur = NULL;
914: (*s_variable).variable_partagee.pointeur =
915: (*s_etat_processus).objet_courant;
916: }
917: }
918: else
919: {
920: // On force la création d'une variable volatile
921:
922: if ((*s_variable).origine == 'P')
923: {
924: (*s_variable).variable_statique.adresse = 0;
925: (*s_variable).variable_partagee.adresse = 0;
926: }
927: else
928: {
929: (*s_variable).variable_statique.pointeur = NULL;
930: (*s_variable).variable_partagee.pointeur = NULL;
931: }
932: }
933: }
934: else
935: {
936: // On force la création d'une variable statique.
937:
938: if ((*s_variable).origine == 'P')
939: {
940: (*s_variable).variable_statique.adresse =
941: (*s_etat_processus).position_courante;
942: (*s_variable).variable_partagee.adresse = 0;
943: }
944: else
945: {
946: (*s_variable).variable_statique.pointeur =
947: (*s_etat_processus).objet_courant;
948: (*s_variable).variable_partagee.pointeur = 0;
949: }
950: }
951:
952: (*s_variable).variable_verrouillee = d_faux;
953: }
954:
955: /*
956: * Recherche de la feuille correspondante dans l'arbre des variables.
957: * Si cette feuille n'existe pas, elle est créée.
958: */
959:
960: if (ajout_variable(s_etat_processus, s_variable) == d_erreur)
961: {
962: return(d_erreur);
963: }
964:
965: return(d_absence_erreur);
966: }
967:
968:
969: /*
970: ================================================================================
971: Procédure de recherche d'une variable par son nom dans la base
972: ================================================================================
973: Entrée :
974: --------------------------------------------------------------------------------
975: Sortie :
976: --------------------------------------------------------------------------------
977: Effets de bord : néant
978: ================================================================================
979: */
980:
981: logical1
982: recherche_variable(struct_processus *s_etat_processus,
983: unsigned char *nom_variable)
984: {
985: int pointeur;
986:
987: struct_arbre_variables *l_variable_courante;
988: struct_liste_pile_systeme *l_element_courant;
989:
990: unsigned char *ptr;
991:
992: integer8 niveau_appel;
993:
994: if ((*s_etat_processus).s_arbre_variables == NULL)
995: {
996: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
997: return(d_faux);
998: }
999:
1000: l_variable_courante = (*s_etat_processus).s_arbre_variables;
1001: ptr = nom_variable;
1002:
1003: while((*ptr) != d_code_fin_chaine)
1004: {
1005: pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr];
1006:
1007: if (pointeur < 0)
1008: {
1009: // Caractère hors de l'alphabet des variables
1010:
1011: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
1012: return(d_faux);
1013: }
1014:
1015: if ((*l_variable_courante).noeuds[pointeur] == NULL)
1016: {
1017: // Le chemin de la variable candidate n'existe pas.
1018: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
1019: return(d_faux);
1020: }
1021:
1022: l_variable_courante = (*l_variable_courante).noeuds[pointeur];
1023: ptr++;
1024: }
1025:
1026: if ((*l_variable_courante).feuille != NULL)
1027: {
1028: // Il existe une pile de variables de même nom. Le sommet de la
1029: // pile est la variable de niveau le plus haut.
1030:
1031: l_element_courant = (*s_etat_processus).l_base_pile_systeme;
1032:
1033: if (l_element_courant == NULL)
1034: {
1035: // Problème : la pile système est vide !
1036: (*s_etat_processus).erreur_systeme = d_es_pile_vide;
1037: return(d_faux);
1038: }
1039:
1040: while((*l_element_courant).retour_definition != 'Y')
1041: {
1042: l_element_courant = (*l_element_courant).suivant;
1043:
1044: if (l_element_courant == NULL)
1045: {
1046: (*s_etat_processus).erreur_systeme = d_es_pile_vide;
1047: return(d_faux);
1048: }
1049: }
1050:
1051: niveau_appel = (*l_element_courant).niveau_courant;
1052:
1053: if (niveau_appel < (*(*(*l_variable_courante).feuille).variable).niveau)
1054: {
1055: // Une variable locale est accessible puisque créée dans la
1056: // fonction courante.
1057:
1058: (*s_etat_processus).pointeur_variable_courante =
1059: (*(*l_variable_courante).feuille).variable;
1060: (*s_etat_processus).pointeur_feuille_courante =
1061: (*l_variable_courante).feuille;
1062: return(d_vrai);
1063: }
1064: else
1065: {
1066: // Aucune variable locale n'est accessible depuis la fonction.
1067: // Dans ce cas, on prend la variable de niveau le plus bas
1068: // si ce niveau est inférieur ou égal à 1 (variable globale
1069: // ou fonction définie par l'utilisateur). Si le niveau de la
1070: // plus ancienne variable est strictement supérieur à 1, il
1071: // s'agit d'une variable locale inaccessible.
1072:
1073: if ((*(*(*(*l_variable_courante).feuille).precedent).variable)
1074: .niveau <= 1)
1075: {
1076: (*s_etat_processus).pointeur_variable_courante =
1077: (*(*(*l_variable_courante).feuille).precedent).variable;
1078: (*s_etat_processus).pointeur_feuille_courante =
1079: (*(*l_variable_courante).feuille).precedent;
1080:
1081: // S'il existe une variable de niveau 0 et une seconde de
1082: // niveau 1, la variable de niveau 0 (fonction) est masquée
1083: // par celle de niveau 1.
1084:
1085: if (((*(*(*(*l_variable_courante).feuille).precedent)
1086: .variable).niveau == 0) && ((*(*(*(*
1087: (*l_variable_courante).feuille).precedent).precedent)
1088: .variable).niveau == 1))
1089: {
1090: (*s_etat_processus).pointeur_variable_courante =
1091: (*(*(*(*l_variable_courante).feuille).precedent)
1092: .precedent).variable;
1093: (*s_etat_processus).pointeur_feuille_courante =
1094: (*(*(*l_variable_courante).feuille).precedent)
1095: .precedent;
1096: }
1097:
1098: return(d_vrai);
1099: }
1100: }
1101: }
1102:
1103: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
1104: return(d_faux);
1105: }
1106:
1107:
1108: logical1
1109: recherche_variable_globale(struct_processus *s_etat_processus,
1110: unsigned char *nom)
1111: {
1112: logical1 presence_variable;
1113:
1114: presence_variable = recherche_variable(s_etat_processus, nom);
1115:
1116: if (presence_variable == d_vrai)
1117: {
1118: switch((*(*s_etat_processus).pointeur_variable_courante).niveau)
1119: {
1120: case 0:
1121: {
1122: // La variable est une définition.
1123: presence_variable = d_faux;
1124: break;
1125: }
1126:
1127: case 1:
1128: {
1129: break;
1130: }
1131:
1132: default:
1133: {
1134: if ((*(*(*(*s_etat_processus).pointeur_feuille_courante)
1135: .precedent).variable).niveau == 1)
1136: {
1137: (*s_etat_processus).pointeur_feuille_courante =
1138: (*(*s_etat_processus).pointeur_feuille_courante)
1139: .precedent;
1140: (*s_etat_processus).pointeur_variable_courante =
1141: (*(*s_etat_processus).pointeur_feuille_courante)
1142: .variable;
1143: }
1144: else if ((*(*(*(*(*s_etat_processus).pointeur_feuille_courante)
1145: .precedent).precedent).variable).niveau == 1)
1146: {
1147: (*s_etat_processus).pointeur_feuille_courante =
1148: (*(*(*s_etat_processus).pointeur_feuille_courante)
1149: .precedent).precedent;
1150: (*s_etat_processus).pointeur_variable_courante =
1151: (*(*s_etat_processus).pointeur_feuille_courante)
1152: .variable;
1153: }
1154: else
1155: {
1156: presence_variable = d_faux;
1157: }
1158:
1159: break;
1160: }
1161: }
1162: }
1163:
1164: if (presence_variable == d_vrai)
1165: {
1166: if ((*(*s_etat_processus).pointeur_variable_courante).objet == NULL)
1167: {
1168: // La variable n'est pas globale, elle est partagée.
1169: presence_variable = d_faux;
1170: (*s_etat_processus).erreur_execution = d_ex_variable_partagee;
1171: }
1172: }
1173:
1174: return(presence_variable);
1175: }
1176:
1177:
1178: /*
1179: ================================================================================
1180: Procédure de retrait d'une variable de la base
1181: ================================================================================
1182: Entrée : type 'G' ou 'L' selon que l'on retire une variable locale (incluant
1183: les globales) ou strictement globale.
1184: --------------------------------------------------------------------------------
1185: Sortie :
1186: --------------------------------------------------------------------------------
1187: Effets de bord : néant
1188: ================================================================================
1189: */
1190:
1191: logical1
1192: retrait_variable(struct_processus *s_etat_processus,
1193: unsigned char *nom_variable, unsigned char type)
1194: {
1195: logical1 erreur;
1196: logical1 variable_supprimee;
1197:
1198: struct_arbre_variables *s_arbre_a_supprimer;
1199: struct_arbre_variables *s_arbre_courant;
1200:
1201: struct_liste_chainee *l_element_courant;
1202: struct_liste_chainee *l_element_precedent;
1203:
1204: struct_liste_variables *variable_a_supprimer;
1205: struct_liste_variables *variables_par_niveau;
1206:
1207: integer8 niveau;
1208:
1209: (*s_etat_processus).niveau_supprime = d_faux;
1210:
1211: if (recherche_variable(s_etat_processus, nom_variable) == d_vrai)
1212: {
1213: // Une variable correspondant au nom recherché est accessible.
1214:
1215: if (type == 'G')
1216: {
1217: if ((*(*s_etat_processus).pointeur_variable_courante).niveau > 1)
1218: {
1219: // La variable obtenue est une variable locale. il faut
1220: // s'assurer qu'il existe une variable de niveau 1 de même
1221: // nom sur la feuille.
1222:
1223: if ((*(*(*(*s_etat_processus).pointeur_feuille_courante)
1224: .precedent).variable).niveau <= 1)
1225: {
1226: (*s_etat_processus).pointeur_feuille_courante =
1227: (*(*s_etat_processus).pointeur_feuille_courante)
1228: .precedent;
1229: (*s_etat_processus).pointeur_variable_courante =
1230: (*(*s_etat_processus).pointeur_feuille_courante)
1231: .variable;
1232:
1233: // Si la variable retournée est de niveau 0, on regarde
1234: // un peu plus loin si une variable de niveau 1 existe.
1235:
1236: if (((*(*(*s_etat_processus).pointeur_feuille_courante)
1237: .variable).niveau == 0) &&
1238: ((*(*(*(*s_etat_processus)
1239: .pointeur_feuille_courante).precedent).variable)
1240: .niveau == 1))
1241: {
1242: (*s_etat_processus).pointeur_feuille_courante =
1243: (*(*s_etat_processus).pointeur_feuille_courante)
1244: .precedent;
1245: (*s_etat_processus).pointeur_variable_courante =
1246: (*(*s_etat_processus).pointeur_feuille_courante)
1247: .variable;
1248: }
1249: }
1250: else
1251: {
1252: // Aucune variable globale (niveau 1) n'existe.
1253:
1254: erreur = d_erreur;
1255: (*s_etat_processus).erreur_execution =
1256: d_ex_variable_non_definie;
1257: return(erreur);
1258: }
1259: }
1260:
1261: if ((*(*s_etat_processus).pointeur_variable_courante)
1262: .variable_verrouillee == d_vrai)
1263: {
1264: erreur = d_erreur;
1265: (*s_etat_processus).erreur_execution =
1266: d_ex_variable_verrouillee;
1267: return(erreur);
1268: }
1269: }
1270:
1271: // Suppression de la variable de la liste.
1272: // Deux cas peuvent survenir :
1273: // 1/ les pointeurs sur la variable et la variable suivante
1274: // sont identiques et on supprime la variable ainsi que la feuille
1275: // associée ;
1276: // 2/ ces deux pointeurs sont différents et se contente de retirer
1277: // la structure décrivant la variable.
1278:
1279: if ((*s_etat_processus).pointeur_feuille_courante ==
1280: (*(*s_etat_processus).pointeur_feuille_courante).suivant)
1281: {
1282: // Cas 1 :
1283: // On retire la variable du noeud en décrémentant le nombre
1284: // de feuilles de ce noeud. Si le nombre de feuilles du noeud
1285: // est nul, on retire les noeuds récursivement jusqu'à obtenir
1286: // un nombre non nul de feuilles utilisées (ou la racine des
1287: // variables).
1288:
1289: variable_a_supprimer = (*s_etat_processus)
1290: .pointeur_feuille_courante;
1291: s_arbre_courant = (*variable_a_supprimer).noeud;
1292: BUG((*s_arbre_courant).noeuds_utilises == 0,
1293: uprintf("Freed node !\n"));
1294: (*s_arbre_courant).noeuds_utilises--;
1295:
1296: (*((*(*variable_a_supprimer).noeud_pere).noeuds
1297: [(*(*variable_a_supprimer).noeud).indice_tableau_pere]))
1298: .feuille = NULL;
1299:
1300: while(((*s_arbre_courant).noeuds_utilises == 0) &&
1301: ((*s_arbre_courant).feuille_statique == NULL))
1302: {
1303: s_arbre_a_supprimer = s_arbre_courant;
1304: s_arbre_courant = (*s_arbre_courant).noeud_pere;
1305:
1306: if (s_arbre_courant == NULL)
1307: {
1308: liberation_tableau_noeuds(s_etat_processus,
1309: (*s_arbre_a_supprimer).noeuds);
1310: liberation_noeud(s_etat_processus, s_arbre_a_supprimer);
1311:
1312: (*s_etat_processus).s_arbre_variables = NULL;
1313: break;
1314: }
1315:
1316: // s_arbre_a_supprimer contient la structure de feuille qui
1317: // vient d'être libérée. Il s'agit maintenant
1318: // d'annuler le pointeur dans le tableau noeuds de la structure
1319: // pointée par noeud_pere, soit s_arbre_courant.
1320:
1321: BUG((*s_arbre_a_supprimer).indice_tableau_pere < 0,
1322: uprintf("Invalid pointer !\n"));
1323: (*s_arbre_courant).noeuds[(*s_arbre_a_supprimer)
1324: .indice_tableau_pere] = NULL;
1325:
1326: liberation_tableau_noeuds(s_etat_processus,
1327: (*s_arbre_a_supprimer).noeuds);
1328: liberation_noeud(s_etat_processus, s_arbre_a_supprimer);
1329:
1330: BUG((*s_arbre_courant).noeuds_utilises == 0,
1331: uprintf("Freed node !\n"));
1332: (*s_arbre_courant).noeuds_utilises--;
1333: }
1334: }
1335: else
1336: {
1337: // Cas 2 :
1338: // On retire la variable de la liste.
1339:
1340: variable_a_supprimer = (*s_etat_processus)
1341: .pointeur_feuille_courante;
1342:
1343: (*(*(*s_etat_processus).pointeur_feuille_courante).precedent)
1344: .suivant = (*(*s_etat_processus).pointeur_feuille_courante)
1345: .suivant;
1346: (*(*(*s_etat_processus).pointeur_feuille_courante).suivant)
1347: .precedent = (*(*s_etat_processus)
1348: .pointeur_feuille_courante).precedent;
1349:
1350: // Mise à jour du pointeur dans l'arbre des variables. Cette
1351: // mise à jour n'est nécessaire que dans le cas où la variable
1352: // supprimée est en tête de la liste.
1353:
1354: if (variable_a_supprimer == (*((*(*variable_a_supprimer).noeud_pere)
1355: .noeuds[(*(*variable_a_supprimer).noeud)
1356: .indice_tableau_pere])).feuille)
1357: {
1358: (*((*(*variable_a_supprimer).noeud_pere).noeuds
1359: [(*(*variable_a_supprimer).noeud).indice_tableau_pere]))
1360: .feuille = (*(*((*(*variable_a_supprimer).noeud_pere)
1361: .noeuds[(*(*variable_a_supprimer).noeud)
1362: .indice_tableau_pere])).feuille).suivant;
1363: }
1364:
1365: (*s_etat_processus).pointeur_feuille_courante =
1366: (*(*s_etat_processus).pointeur_feuille_courante).suivant;
1367: (*s_etat_processus).pointeur_variable_courante =
1368: (*(*s_etat_processus).pointeur_feuille_courante).variable;
1369: }
1370:
1371: // Dans tous les cas, on retire la variable de la liste des variables
1372: // par niveau.
1373:
1374: niveau = (*(*variable_a_supprimer).variable).niveau;
1375: variables_par_niveau = (*s_etat_processus).l_liste_variables_par_niveau;
1376: variable_supprimee = d_faux;
1377:
1378: if (variables_par_niveau != NULL)
1379: {
1380: do
1381: {
1382: l_element_courant = (*variables_par_niveau).liste;
1383:
1384: if (l_element_courant != NULL)
1385: {
1386: if ((*((struct_variable *) (*l_element_courant).donnee))
1387: .niveau == niveau)
1388: {
1389: // On parcourt le bon niveau.
1390:
1391: l_element_precedent = NULL;
1392:
1393: while(l_element_courant != NULL)
1394: {
1395: // Tant que l_element_courant est non nul, il reste
1396: // des variables à explorer dans le niveau courant.
1397:
1398: if ((*l_element_courant).donnee ==
1399: (void *) (*variable_a_supprimer).variable)
1400: {
1401: // On a trouvé la variable à supprimer.
1402:
1403: if (l_element_precedent == NULL)
1404: {
1405: (*variables_par_niveau).liste =
1406: (*l_element_courant).suivant;
1407: }
1408: else
1409: {
1410: (*l_element_precedent).suivant =
1411: (*l_element_courant).suivant;
1412: }
1413:
1414: liberation_maillon(s_etat_processus,
1415: l_element_courant);
1416:
1417: if ((*variables_par_niveau).liste == NULL)
1418: {
1419: (*s_etat_processus).niveau_supprime =
1420: d_vrai;
1421:
1422: if ((*s_etat_processus)
1423: .l_liste_variables_par_niveau
1424: == variables_par_niveau)
1425: {
1426: // On retire l'élément de la liste
1427: // pointé par
1428: // l_liste_variable_par_niveau
1429:
1430: (*s_etat_processus)
1431: .l_liste_variables_par_niveau =
1432: (*variables_par_niveau).suivant;
1433: }
1434:
1435: (*(*variables_par_niveau).precedent)
1436: .suivant =
1437: (*variables_par_niveau).suivant;
1438: (*(*variables_par_niveau).suivant)
1439: .precedent =
1440: (*variables_par_niveau)
1441: .precedent;
1442: liberation_feuille(s_etat_processus,
1443: variables_par_niveau);
1444: }
1445:
1446: variable_supprimee = d_vrai;
1447: break;
1448: }
1449:
1450: l_element_precedent = l_element_courant;
1451: l_element_courant = (*l_element_courant).suivant;
1452: }
1453: }
1454: }
1455:
1456: if (variable_supprimee == d_vrai)
1457: {
1458: break;
1459: }
1460:
1461: variables_par_niveau = (*variables_par_niveau).suivant;
1462:
1463: } while(variables_par_niveau != (*s_etat_processus)
1464: .l_liste_variables_par_niveau);
1465: }
1466:
1467: // Puis on libère le contenu de la variable.
1468:
1469: free((*(*variable_a_supprimer).variable).nom);
1470: liberation(s_etat_processus, (*(*variable_a_supprimer).variable).objet);
1471: liberation_variable(s_etat_processus, (*variable_a_supprimer).variable);
1472: liberation_feuille(s_etat_processus, variable_a_supprimer);
1473:
1474: erreur = d_absence_erreur;
1475: }
1476: else
1477: {
1478: // Aucune variable n'est accessible depuis le point courant du
1479: // programme.
1480:
1481: erreur = d_erreur;
1482: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
1483: }
1484:
1485: return(erreur);
1486: }
1487:
1488:
1489: /*
1490: ================================================================================
1491: Procédure de retrait des variables de niveau strictement supérieur au
1492: niveau courant
1493: ================================================================================
1494: Entrée :
1495: --------------------------------------------------------------------------------
1496: Sortie :
1497: --------------------------------------------------------------------------------
1498: Effets de bord : néant
1499: ================================================================================
1500: */
1501:
1502: logical1
1503: retrait_variables_par_niveau(struct_processus *s_etat_processus)
1504: {
1505: struct_liste_variables *l_element_a_supprimer;
1506:
1507: // Utilisation du champ (*s_etat_processus).liste_variables_par_niveau.
1508: // La tête de la pile contient toujours les variables de plus haut niveau
1509: // créées.
1510:
1511: while((*s_etat_processus).l_liste_variables_par_niveau != NULL)
1512: {
1513: if ((*(*s_etat_processus).l_liste_variables_par_niveau).liste == NULL)
1514: {
1515: // Si le niveau ne contient aucune variable, on le détruit.
1516: // Le pointeur sur la chaîne est déjà nul et il ne reste rien à
1517: // faire.
1518: }
1519: else
1520: {
1521: // Le niveau contient des variables.
1522:
1523: if ((*((struct_variable *) (*(*(*s_etat_processus)
1524: .l_liste_variables_par_niveau).liste).donnee)).niveau
1525: <= (*s_etat_processus).niveau_courant)
1526: {
1527: // On a retiré de l'arbre des variables toutes les
1528: // variables de niveau strictement supérieur au niveau
1529: // courant.
1530:
1531: break;
1532: }
1533:
1534: if (((*s_etat_processus).at_exit != NULL) &&
1535: ((*s_etat_processus).niveau_courant == 0))
1536: {
1537: // Il y a une routine ATEXIT enregistrée. On ne détruit pas
1538: // les variables globales qui pourraient y être utilisées.
1539:
1540: break;
1541: }
1542:
1543: while((*(*s_etat_processus).l_liste_variables_par_niveau).liste
1544: != NULL)
1545: {
1546: // Nécessaire car le pointeur sur la tête de la pile
1547: // peut être modifié par retrait_variable().
1548: // Sauvegarde des variables statiques.
1549:
1550: if ((*((struct_variable *) (*(*(*s_etat_processus)
1551: .l_liste_variables_par_niveau).liste).donnee)).origine
1552: == 'P')
1553: {
1554: if ((*((struct_variable *) (*(*(*s_etat_processus)
1555: .l_liste_variables_par_niveau).liste).donnee))
1556: .variable_statique.adresse != 0)
1557: {
1558: if (recherche_variable_statique(s_etat_processus,
1559: (*((struct_variable *) (*(*(*s_etat_processus)
1560: .l_liste_variables_par_niveau).liste).donnee))
1561: .nom, (*((struct_variable *)
1562: (*(*(*s_etat_processus)
1563: .l_liste_variables_par_niveau).liste).donnee))
1564: .variable_statique, ((*s_etat_processus)
1565: .mode_execution_programme
1566: == 'Y') ? 'P' : 'E') != NULL)
1567: {
1568: (*(*s_etat_processus)
1569: .pointeur_variable_statique_courante)
1570: .objet = (*((struct_variable *)
1571: (*(*(*s_etat_processus)
1572: .l_liste_variables_par_niveau).liste)
1573: .donnee)).objet;
1574: }
1575: else
1576: {
1577: (*s_etat_processus).erreur_systeme =
1578: d_es_variable_introuvable;
1579: }
1580:
1581: (*((struct_variable *) (*(*(*s_etat_processus)
1582: .l_liste_variables_par_niveau).liste).donnee))
1583: .objet = NULL;
1584: }
1585: }
1586: else
1587: {
1588: if ((*((struct_variable *) (*(*(*s_etat_processus)
1589: .l_liste_variables_par_niveau).liste).donnee))
1590: .variable_statique.pointeur != NULL)
1591: {
1592: /*
1593: * Gestion des variables statiques
1594: */
1595:
1596: if (recherche_variable_statique(s_etat_processus,
1597: (*((struct_variable *) (*(*(*s_etat_processus)
1598: .l_liste_variables_par_niveau).liste).donnee))
1599: .nom, (*((struct_variable *)
1600: (*(*(*s_etat_processus)
1601: .l_liste_variables_par_niveau).liste).donnee))
1602: .variable_statique, ((*s_etat_processus)
1603: .mode_execution_programme
1604: == 'Y') ? 'P' : 'E') != NULL)
1605: {
1606: (*(*s_etat_processus)
1607: .pointeur_variable_statique_courante)
1608: .objet = (*((struct_variable *)
1609: (*(*(*s_etat_processus)
1610: .l_liste_variables_par_niveau).liste)
1611: .donnee)).objet;
1612: }
1613: else
1614: {
1615: (*s_etat_processus).erreur_systeme =
1616: d_es_variable_introuvable;
1617: return(d_erreur);
1618: }
1619:
1620: (*((struct_variable *) (*(*(*s_etat_processus)
1621: .l_liste_variables_par_niveau).liste).donnee))
1622: .objet = NULL;
1623: }
1624: }
1625:
1626: if (retrait_variable(s_etat_processus,
1627: (*((struct_variable *) (*(*(*s_etat_processus)
1628: .l_liste_variables_par_niveau).liste).donnee)).nom,
1629: 'L') == d_erreur)
1630: {
1631: return(d_erreur);
1632: }
1633:
1634: if ((*((struct_variable *) (*(*(*s_etat_processus)
1635: .l_liste_variables_par_niveau).liste).donnee)).niveau
1636: <= (*s_etat_processus).niveau_courant)
1637: {
1638: // On a retiré de l'arbre des variables toutes les
1639: // variables de niveau strictement supérieur au niveau
1640: // courant.
1641:
1642: return(d_absence_erreur);
1643: }
1644: }
1645: }
1646:
1647: // On retire l'élément de la liste doublement chaînée et circulaire.
1648:
1649: (*(*(*s_etat_processus).l_liste_variables_par_niveau).precedent).suivant
1650: = (*(*s_etat_processus).l_liste_variables_par_niveau).suivant;
1651: (*(*(*s_etat_processus).l_liste_variables_par_niveau).suivant).precedent
1652: = (*(*s_etat_processus).l_liste_variables_par_niveau).precedent;
1653:
1654: l_element_a_supprimer = (*s_etat_processus)
1655: .l_liste_variables_par_niveau;
1656: (*s_etat_processus).l_liste_variables_par_niveau =
1657: (*l_element_a_supprimer).suivant;
1658: liberation_feuille(s_etat_processus, l_element_a_supprimer);
1659: }
1660:
1661: return(d_absence_erreur);
1662: }
1663:
1664:
1665: /*
1666: ================================================================================
1667: Procédure de retrait des toutes les variables locales et globales
1668: ================================================================================
1669: Entrée : drapeau indiquant s'il faut retirer les définitions (variables
1670: de niveau 0)
1671: --------------------------------------------------------------------------------
1672: Sortie :
1673: --------------------------------------------------------------------------------
1674: Effets de bord : néant
1675: ================================================================================
1676: */
1677:
1678: void
1679: liberation_arbre_variables(struct_processus *s_etat_processus,
1680: struct_arbre_variables *arbre, logical1 retrait_definitions)
1681: {
1682: int i;
1683:
1684: struct_liste_chainee *l_element_courant_liste;
1685: struct_liste_chainee *l_element_suivant_liste;
1686:
1687: struct_liste_variables *l_element_courant;
1688: struct_liste_variables *l_element_suivant;
1689:
1690: struct_liste_variables_statiques *l_element_statique_courant;
1691: struct_liste_variables_statiques *l_element_statique_suivant;
1692:
1693: // Libération de l'arbre des variables. Le contenu des variables n'est
1694: // pas détruit par cette opération, il sera détruit lors de la libération
1695: // de la liste des variables par niveau.
1696:
1697: if (arbre == NULL)
1698: {
1699: return;
1700: }
1701:
1702: l_element_courant = (*arbre).feuille;
1703:
1704: if (l_element_courant != NULL)
1705: {
1706: do
1707: {
1708: l_element_suivant = (*l_element_courant).suivant;
1709: liberation_feuille(s_etat_processus, l_element_courant);
1710: l_element_courant = l_element_suivant;
1711: } while(l_element_courant != (*arbre).feuille);
1712:
1713: (*arbre).feuille = NULL;
1714: }
1715:
1716: l_element_statique_courant = (*arbre).feuille_statique;
1717:
1718: while(l_element_statique_courant != NULL)
1719: {
1720: l_element_statique_suivant = (*l_element_statique_courant).suivant;
1721:
1722: free((*(*l_element_statique_courant).variable).nom);
1723: liberation(s_etat_processus, (*(*l_element_statique_courant)
1724: .variable).objet);
1725: free((*l_element_statique_courant).variable);
1726: free(l_element_statique_courant);
1727:
1728: l_element_statique_courant = l_element_statique_suivant;
1729: }
1730:
1731: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
1732: {
1733: if ((*arbre).noeuds[i] != NULL)
1734: {
1735: liberation_arbre_variables(s_etat_processus, (*arbre).noeuds[i],
1736: retrait_definitions);
1737: (*arbre).noeuds[i] = NULL;
1738: }
1739: }
1740:
1741: // Suppression de la liste des variables par niveau.
1742:
1743: if (arbre == (*s_etat_processus).s_arbre_variables)
1744: {
1745: l_element_courant = (*s_etat_processus).l_liste_variables_par_niveau;
1746:
1747: if (l_element_courant != NULL)
1748: {
1749: do
1750: {
1751: l_element_courant_liste = (*l_element_courant).liste;
1752:
1753: while(l_element_courant_liste != NULL)
1754: {
1755: if ((retrait_definitions == d_vrai) ||
1756: ((*((struct_variable *) (*l_element_courant_liste)
1757: .donnee)).niveau >= 1))
1758: {
1759: liberation(s_etat_processus, (*((struct_variable *)
1760: (*l_element_courant_liste).donnee)).objet);
1761: free((*((struct_variable *) (*l_element_courant_liste)
1762: .donnee)).nom);
1763: }
1764:
1765: l_element_suivant_liste =
1766: (*l_element_courant_liste).suivant;
1767: liberation_variable(s_etat_processus, (struct_variable *)
1768: (*l_element_courant_liste).donnee);
1769: liberation_maillon(s_etat_processus,
1770: l_element_courant_liste);
1771: l_element_courant_liste = l_element_suivant_liste;
1772: }
1773:
1774: l_element_suivant = (*l_element_courant).suivant;
1775: liberation_feuille(s_etat_processus, l_element_courant);
1776: l_element_courant = l_element_suivant;
1777: } while(l_element_courant != (*s_etat_processus)
1778: .l_liste_variables_par_niveau);
1779: }
1780: }
1781:
1782: liberation_tableau_noeuds(s_etat_processus, (*arbre).noeuds);
1783: liberation_noeud(s_etat_processus, arbre);
1784: arbre = NULL;
1785:
1786: return;
1787: }
1788:
1789:
1790: /*
1791: ================================================================================
1792: Procédure renvoyant les variables dans un tableau
1793: ================================================================================
1794: Entrée :
1795: --------------------------------------------------------------------------------
1796: Sortie :
1797: --------------------------------------------------------------------------------
1798: Effets de bord : néant
1799: ================================================================================
1800: */
1801:
1802: static integer8
1803: nombre_variables_locales(struct_processus *s_etat_processus,
1804: struct_arbre_variables *l_element_courant)
1805: {
1806: integer8 i;
1807: integer8 n;
1808:
1809: struct_liste_variables *l_variable;
1810: struct_liste_variables_statiques *l_variable_statique;
1811:
1812: if (l_element_courant == NULL)
1813: {
1814: return(0);
1815: }
1816:
1817: n = 0;
1818:
1819: if ((*l_element_courant).feuille != NULL)
1820: {
1821: l_variable = (*l_element_courant).feuille;
1822:
1823: do
1824: {
1825: n++;
1826: l_variable = (*l_variable).suivant;
1827: } while(l_variable != (*l_element_courant).feuille);
1828: }
1829:
1830: if ((*l_element_courant).feuille_statique != NULL)
1831: {
1832: l_variable_statique = (*l_element_courant).feuille_statique;
1833:
1834: do
1835: {
1836: // Si le pointeur est nul, la variable est accessible et a été
1837: // copiée dans l'arbre des variables.
1838:
1839: if ((*(*l_variable_statique).variable).objet != NULL)
1840: {
1841: n++;
1842: }
1843:
1844: l_variable_statique = (*l_variable_statique).suivant;
1845: } while(l_variable_statique != NULL);
1846: }
1847:
1848: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
1849: {
1850: if ((*l_element_courant).noeuds[i] != NULL)
1851: {
1852: n += nombre_variables_locales(s_etat_processus,
1853: (*l_element_courant).noeuds[i]);
1854: }
1855: }
1856:
1857: return(n);
1858: }
1859:
1860:
1861: static integer8
1862: nombre_variables_partagees(struct_processus *s_etat_processus,
1863: struct_arbre_variables_partagees *l_element_courant)
1864: {
1865: integer8 i;
1866: integer8 n;
1867:
1868: struct_liste_variables_partagees *l_variable;
1869:
1870: if (l_element_courant == NULL)
1871: {
1872: return(0);
1873: }
1874:
1875: // Mutex deverrouillé par liste_variables_partagees();
1876: if (pthread_mutex_lock(&((*l_element_courant).mutex_feuille)) != 0)
1877: {
1878: (*s_etat_processus).erreur_systeme = d_es_processus;
1879: return(0);
1880: }
1881:
1882: n = 0;
1883:
1884: if ((*l_element_courant).feuille != NULL)
1885: {
1886: l_variable = (*l_element_courant).feuille;
1887:
1888: do
1889: {
1890: n++;
1891: l_variable = (*l_variable).suivant;
1892: } while(l_variable != NULL);
1893: }
1894:
1895: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
1896: {
1897: if ((*l_element_courant).noeuds[i] != NULL)
1898: {
1899: n += nombre_variables_partagees(s_etat_processus,
1900: (*l_element_courant).noeuds[i]);
1901: }
1902: }
1903:
1904: return(n);
1905: }
1906:
1907:
1908: integer8
1909: nombre_variables(struct_processus *s_etat_processus)
1910: {
1911: return(nombre_variables_locales(s_etat_processus,
1912: (*s_etat_processus).s_arbre_variables)
1913: + nombre_variables_partagees(s_etat_processus,
1914: (*(*s_etat_processus).s_arbre_variables_partagees)));
1915: }
1916:
1917:
1918: void
1919: liberation_mutexes_arbre_variables_partagees(struct_processus *s_etat_processus,
1920: struct_arbre_variables_partagees *l_element_courant)
1921: {
1922: int i;
1923:
1924: if (l_element_courant == NULL)
1925: {
1926: return;
1927: }
1928:
1929: if (pthread_mutex_trylock(&((*l_element_courant).mutex_feuille)) != 0)
1930: {
1931: (*s_etat_processus).erreur_systeme = d_es_processus;
1932: return;
1933: }
1934:
1935: if (pthread_mutex_unlock(&((*l_element_courant).mutex_feuille)) != 0)
1936: {
1937: (*s_etat_processus).erreur_systeme = d_es_processus;
1938: return;
1939: }
1940:
1941: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
1942: {
1943: if ((*l_element_courant).noeuds[i] != NULL)
1944: {
1945: liberation_mutexes_arbre_variables_partagees(s_etat_processus,
1946: (*l_element_courant).noeuds[i]);
1947: }
1948: }
1949:
1950: return;
1951: }
1952:
1953:
1954: static integer8
1955: liste_variables_locales(struct_processus *s_etat_processus,
1956: struct_tableau_variables *tableau, integer8 position,
1957: struct_arbre_variables *l_element_courant)
1958: {
1959: integer8 i;
1960:
1961: struct_liste_variables *l_variable;
1962: struct_liste_variables_statiques *l_variable_statique;
1963:
1964: if (l_element_courant == NULL)
1965: {
1966: return(position);
1967: }
1968:
1969: if ((*l_element_courant).feuille != NULL)
1970: {
1971: l_variable = (*l_element_courant).feuille;
1972:
1973: do
1974: {
1975: tableau[position].origine = (*(*l_variable).variable).origine;
1976: tableau[position].nom = (*(*l_variable).variable).nom;
1977: tableau[position].niveau = (*(*l_variable).variable).niveau;
1978: tableau[position].objet = (*(*l_variable).variable).objet;
1979: tableau[position].variable_verrouillee =
1980: (*(*l_variable).variable).variable_verrouillee;
1981: tableau[position].variable_statique =
1982: (*(*l_variable).variable).variable_statique;
1983: tableau[position].variable_partagee =
1984: (*(*l_variable).variable).variable_partagee;
1985: tableau[position].variable_masquee = d_faux;
1986: tableau[position].mutex = NULL;
1987:
1988: position++;
1989:
1990: l_variable = (*l_variable).suivant;
1991: } while(l_variable != (*l_element_courant).feuille);
1992: }
1993:
1994: if ((*l_element_courant).feuille_statique != NULL)
1995: {
1996: l_variable_statique = (*l_element_courant).feuille_statique;
1997:
1998: do
1999: {
2000: if ((*(*l_variable_statique).variable).objet != NULL)
2001: {
2002: tableau[position].origine = 'E';
2003: tableau[position].nom = (*(*l_variable_statique).variable).nom;
2004: tableau[position].niveau =
2005: (*(*l_variable_statique).variable).niveau;
2006: tableau[position].objet = (*(*l_variable_statique).variable)
2007: .objet;
2008: tableau[position].variable_verrouillee = d_faux;
2009: tableau[position].variable_statique =
2010: (*(*l_variable_statique).variable).variable_statique;
2011: tableau[position].variable_partagee.pointeur = NULL;
2012: tableau[position].variable_masquee = d_vrai;
2013: tableau[position].mutex = NULL;
2014:
2015: position++;
2016: }
2017:
2018: l_variable_statique = (*l_variable_statique).suivant;
2019: } while(l_variable_statique != NULL);
2020: }
2021:
2022: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
2023: {
2024: if ((*l_element_courant).noeuds[i] != NULL)
2025: {
2026: position = liste_variables_locales(s_etat_processus,
2027: tableau, position, (*l_element_courant).noeuds[i]);
2028: }
2029: }
2030:
2031: return(position);
2032: }
2033:
2034:
2035: static integer8
2036: liste_variables_partagees(struct_processus *s_etat_processus,
2037: struct_tableau_variables *tableau, integer8 position,
2038: struct_arbre_variables_partagees *l_element_courant)
2039: {
2040: integer8 i;
2041:
2042: struct_liste_variables_partagees *l_variable;
2043:
2044: if (l_element_courant == NULL)
2045: {
2046: return(position);
2047: }
2048:
2049: if ((*l_element_courant).feuille != NULL)
2050: {
2051: l_variable = (*l_element_courant).feuille;
2052:
2053: do
2054: {
2055: tableau[position].origine = 'E';
2056: tableau[position].nom = (*(*l_variable).variable).nom;
2057: tableau[position].niveau = (*(*l_variable).variable).niveau;
2058: tableau[position].objet = (*(*l_variable).variable).objet;
2059: tableau[position].variable_verrouillee = d_faux;
2060: tableau[position].variable_partagee =
2061: (*(*l_variable).variable).variable_partagee;
2062: tableau[position].variable_statique.pointeur = NULL;
2063: tableau[position].variable_masquee = d_faux;
2064: tableau[position].mutex = &((*(*l_variable).variable).mutex);
2065: pthread_mutex_lock(tableau[position].mutex);
2066:
2067: position++;
2068:
2069: l_variable = (*l_variable).suivant;
2070: } while(l_variable != NULL);
2071: }
2072:
2073: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
2074: {
2075: if ((*l_element_courant).noeuds[i] != NULL)
2076: {
2077: position = liste_variables_partagees(s_etat_processus,
2078: tableau, position, (*l_element_courant).noeuds[i]);
2079: }
2080: }
2081:
2082: // Mutex verrouillé par nombre_variables_partagees();
2083: if (pthread_mutex_unlock(&((*l_element_courant).mutex_feuille)) != 0)
2084: {
2085: (*s_etat_processus).erreur_systeme = d_es_processus;
2086: return(0);
2087: }
2088:
2089: return(position);
2090: }
2091:
2092:
2093: static int
2094: fonction_ordre_variables(const void *argument_1, const void *argument_2)
2095: {
2096: int comparaison;
2097:
2098: struct_tableau_variables *a1;
2099: struct_tableau_variables *a2;
2100:
2101: a1 = (struct_tableau_variables *) argument_1;
2102: a2 = (struct_tableau_variables *) argument_2;
2103:
2104: comparaison = strcmp((*a1).nom, (*a2).nom);
2105:
2106: if (comparaison != 0)
2107: {
2108: return(comparaison);
2109: }
2110: else
2111: {
2112: return(((((*a1).niveau - (*a2).niveau)) > 0) ? 1 : -1);
2113: }
2114: }
2115:
2116:
2117: integer8
2118: liste_variables(struct_processus *s_etat_processus,
2119: struct_tableau_variables *tableau)
2120: {
2121: integer8 nombre_elements;
2122:
2123: nombre_elements = liste_variables_locales(s_etat_processus,
2124: tableau, 0, (*s_etat_processus).s_arbre_variables);
2125: nombre_elements = liste_variables_partagees(s_etat_processus,
2126: tableau, nombre_elements, (*(*s_etat_processus)
2127: .s_arbre_variables_partagees));
2128:
2129: qsort(tableau, (size_t) nombre_elements, sizeof(struct_tableau_variables),
2130: fonction_ordre_variables);
2131:
2132: return(nombre_elements);
2133: }
2134:
2135:
2136: /*
2137: ================================================================================
2138: Procédure de copie de l'arbre des variables
2139: ================================================================================
2140: Entrée :
2141: --------------------------------------------------------------------------------
2142: Sortie :
2143: --------------------------------------------------------------------------------
2144: Effets de bord : néant
2145: ================================================================================
2146: */
2147:
2148: void
2149: copie_arbre_variables(struct_processus *s_etat_processus, struct_processus
2150: *s_nouvel_etat_processus)
2151: {
2152: // Les définitions sont partagées entre tous les threads et ne sont pas
2153: // copiées.
2154: //
2155: // NB : on ne copie que les variables de niveaux 0 et 1, les autres
2156: // variables locales étant masquées par le processus de création de thread
2157: // ou de processus, elles seront inaccessibles de tous les points
2158: // du fil d'exécution fils.
2159:
2160: // Pour copier ces variables, on récupère les variables depuis la liste par
2161: // niveaux (niveaux 0 et 1) et on ajoute les variables dans la nouvelle
2162: // structure. Les variables de niveau 0 étant non modifiables, elles
2163: // ne sont pas dupliquées.
2164:
2165: int i;
2166:
2167: logical1 niveau_0_traite;
2168: logical1 niveau_1_traite;
2169:
2170: struct_arbre_variables *l_variable_courante;
2171:
2172: struct_liste_chainee *l_element_courant;
2173:
2174: struct_liste_variables *l_niveau_courant;
2175: struct_liste_variables_statiques *l_element_statique_courant;
2176:
2177: struct_variable s_variable;
2178: struct_variable_statique s_variable_statique;
2179:
2180: unsigned char *ptr;
2181:
2182: (*s_nouvel_etat_processus).s_arbre_variables = NULL;
2183: (*s_nouvel_etat_processus).l_liste_variables_par_niveau = NULL;
2184:
2185: l_niveau_courant = (*s_etat_processus).l_liste_variables_par_niveau;
2186:
2187: // Si la variable en tête n'est pas une variable de niveau 0, le niveau
2188: // 0, s'il existe est le niveau précédent la valeur courante dans la
2189: // boucle.
2190:
2191: if ((*((struct_variable *) (*(*l_niveau_courant).liste).donnee)).niveau
2192: != 0)
2193: {
2194: l_niveau_courant = (*l_niveau_courant).precedent;
2195: }
2196:
2197: // Les variables de niveaux 0 et 1 sont accessibles en au plus trois
2198: // itérations (par construction).
2199:
2200: niveau_0_traite = d_faux;
2201: niveau_1_traite = d_faux;
2202:
2203: for(i = 0; i <= 2; i++)
2204: {
2205: if ((*((struct_variable *) (*(*l_niveau_courant).liste)
2206: .donnee)).niveau == 0)
2207: {
2208: if (niveau_0_traite == d_faux)
2209: {
2210: l_element_courant = (*l_niveau_courant).liste;
2211:
2212: while(l_element_courant != NULL)
2213: {
2214: if (ajout_variable(s_nouvel_etat_processus,
2215: (struct_variable *) (*l_element_courant).donnee)
2216: == d_erreur)
2217: {
2218: return;
2219: }
2220:
2221: l_element_courant = (*l_element_courant).suivant;
2222: }
2223:
2224: niveau_0_traite = d_vrai;
2225: }
2226: }
2227: else if ((*((struct_variable *) (*(*l_niveau_courant).liste)
2228: .donnee)).niveau == 1)
2229: {
2230: if (niveau_1_traite == d_faux)
2231: {
2232: l_element_courant = (*l_niveau_courant).liste;
2233:
2234: while(l_element_courant != NULL)
2235: {
2236: s_variable = (*((struct_variable *)
2237: (*l_element_courant).donnee));
2238:
2239: if ((s_variable.nom = rpl_malloc(s_nouvel_etat_processus,
2240: (strlen((*((struct_variable *)
2241: (*l_element_courant).donnee)).nom) + 1) *
2242: sizeof(unsigned char))) == NULL)
2243: {
2244: (*s_nouvel_etat_processus).erreur_systeme =
2245: d_es_allocation_memoire;
2246: return;
2247: }
2248:
2249: strcpy(s_variable.nom, (*((struct_variable *)
2250: (*l_element_courant).donnee)).nom);
2251:
2252: if ((s_variable.objet = copie_objet(s_nouvel_etat_processus,
2253: (*((struct_variable *) (*l_element_courant).donnee))
2254: .objet, 'P')) == NULL)
2255: {
2256: (*s_nouvel_etat_processus).erreur_systeme =
2257: d_es_allocation_memoire;
2258: return;
2259: }
2260:
2261: if (ajout_variable(s_nouvel_etat_processus, &s_variable)
2262: == d_erreur)
2263: {
2264: return;
2265: }
2266:
2267: l_element_courant = (*l_element_courant).suivant;
2268: }
2269:
2270: niveau_1_traite = d_vrai;
2271: }
2272:
2273: // Les variables de niveau 0 ayant déjà été copiées, on
2274: // peut sortir de la boucle car toutes les variables sont
2275: // maintenant disponibles dans le fil d'exécution fils.
2276:
2277: break;
2278: }
2279:
2280: l_niveau_courant = (*l_niveau_courant).precedent;
2281: }
2282:
2283: // Copie des variables statiques
2284:
2285: l_element_statique_courant = (*s_etat_processus)
2286: .l_liste_variables_statiques;
2287:
2288: while(l_element_statique_courant != NULL)
2289: {
2290: // Création des branches de l'arbre si nécessaire.
2291:
2292: if ((*s_nouvel_etat_processus).s_arbre_variables == NULL)
2293: {
2294: if (((*s_nouvel_etat_processus).s_arbre_variables =
2295: allocation_noeud(s_nouvel_etat_processus)) == NULL)
2296: {
2297: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
2298: return;
2299: }
2300:
2301: (*(*s_nouvel_etat_processus).s_arbre_variables).feuille = NULL;
2302: (*(*s_nouvel_etat_processus).s_arbre_variables).feuille_statique
2303: = NULL;
2304: (*(*s_nouvel_etat_processus).s_arbre_variables).noeuds_utilises = 0;
2305: (*(*s_nouvel_etat_processus).s_arbre_variables).indice_tableau_pere
2306: = -1;
2307: (*(*s_nouvel_etat_processus).s_arbre_variables).noeud_pere = NULL;
2308:
2309: if (((*(*s_nouvel_etat_processus).s_arbre_variables).noeuds =
2310: allocation_tableau_noeuds(s_nouvel_etat_processus)) == NULL)
2311: {
2312: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
2313: return;
2314: }
2315:
2316: for(i = 0; i < (*s_nouvel_etat_processus)
2317: .nombre_caracteres_variables; i++)
2318: {
2319: (*(*s_nouvel_etat_processus).s_arbre_variables).noeuds[i]
2320: = NULL;
2321: }
2322: }
2323:
2324: l_variable_courante = (*s_nouvel_etat_processus).s_arbre_variables;
2325: ptr = (*(*l_element_statique_courant).variable).nom;
2326:
2327: while((*ptr) != d_code_fin_chaine)
2328: {
2329: BUG((*s_nouvel_etat_processus).pointeurs_caracteres_variables
2330: [*ptr] < 0, uprintf("Variable=\"%s\", (*ptr)='%c'\n",
2331: (*(*l_element_statique_courant).variable).nom, *ptr));
2332:
2333: if ((*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2334: .pointeurs_caracteres_variables[*ptr]] == NULL)
2335: {
2336: // Le noeud n'existe pas encore, on le crée et on le marque
2337: // comme utilisé dans la structure parente.
2338:
2339: if (((*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2340: .pointeurs_caracteres_variables[*ptr]] =
2341: allocation_noeud(s_nouvel_etat_processus)) == NULL)
2342: {
2343: (*s_etat_processus).erreur_systeme =
2344: d_es_allocation_memoire;
2345: return;
2346: }
2347:
2348: (*l_variable_courante).noeuds_utilises++;
2349:
2350: // La feuille est par défaut vide et aucun élément du tableau
2351: // noeuds (les branches qui peuvent être issues de ce nouveau
2352: // noeud) n'est encore utilisée.
2353:
2354: (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2355: .pointeurs_caracteres_variables[*ptr]]).feuille = NULL;
2356: (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2357: .pointeurs_caracteres_variables[*ptr]]).feuille_statique
2358: = NULL;
2359: (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2360: .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises
2361: = 0;
2362:
2363: // Le champ noeud_pere de la structure créée pointe sur
2364: // la structure parente et l'indice tableau_pere correspond à la
2365: // position réelle dans le tableau noeuds[] de la structure
2366: // parente du noeud courant. Cette valeur sera utilisée lors de
2367: // la destruction du noeud pour annuler le pointeur contenu dans
2368: // le tableau noeuds[] de la structure parente.
2369:
2370: (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2371: .pointeurs_caracteres_variables[*ptr]]).noeud_pere =
2372: l_variable_courante;
2373: (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2374: .pointeurs_caracteres_variables[*ptr]])
2375: .indice_tableau_pere = (*s_nouvel_etat_processus)
2376: .pointeurs_caracteres_variables[*ptr];
2377:
2378: // Allocation du tableau noeuds[] et initialisation à zéro de
2379: // tous les pointeurs.
2380:
2381: if (((*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2382: .pointeurs_caracteres_variables[*ptr]]).noeuds =
2383: allocation_tableau_noeuds(s_nouvel_etat_processus))
2384: == NULL)
2385: {
2386: (*s_etat_processus).erreur_systeme
2387: = d_es_allocation_memoire;
2388: return;
2389: }
2390:
2391: for(i = 0; i < (*s_nouvel_etat_processus)
2392: .nombre_caracteres_variables; i++)
2393: {
2394: (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2395: .pointeurs_caracteres_variables[*ptr]]).noeuds[i]
2396: = NULL;
2397: }
2398: }
2399:
2400: l_variable_courante = (*l_variable_courante).noeuds
2401: [(*s_nouvel_etat_processus).pointeurs_caracteres_variables
2402: [*ptr]];
2403:
2404: ptr++;
2405: }
2406:
2407: // Il faut copier la variable pour la dissocier de la variable
2408: // restant dans le thread parent.
2409:
2410: s_variable_statique = (*(*l_element_statique_courant).variable);
2411:
2412: if (copie_objet(s_etat_processus, s_variable_statique.objet, 'P')
2413: == NULL)
2414: {
2415: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
2416: return;
2417: }
2418:
2419: if ((s_variable_statique.nom = rpl_malloc(s_nouvel_etat_processus,
2420: (strlen((*(*l_element_statique_courant).variable).nom) + 1) *
2421: sizeof(unsigned char))) == NULL)
2422: {
2423: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
2424: return;
2425: }
2426:
2427: strcpy(s_variable_statique.nom, (*(*l_element_statique_courant)
2428: .variable).nom);
2429:
2430: if (creation_variable_statique(s_nouvel_etat_processus,
2431: &s_variable_statique) == d_erreur)
2432: {
2433: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
2434: return;
2435: }
2436:
2437: l_element_statique_courant = (*l_element_statique_courant).suivant;
2438: }
2439:
2440: return;
2441: }
2442:
2443:
2444: /*
2445: ================================================================================
2446: Procédure d'initialisation de la table de correspondance des variables
2447: ================================================================================
2448: Entrée :
2449: --------------------------------------------------------------------------------
2450: Sortie :
2451: --------------------------------------------------------------------------------
2452: Effets de bord : néant
2453: ================================================================================
2454: */
2455:
2456: /*
2457: * Caractères autorisés dans les variables
2458: *
2459: * 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
2460: * 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
2461: * _
2462: * 1 2 3 4 5 6 7 8 9 0
2463: */
2464:
2465: void
2466: initialisation_variables(struct_processus *s_etat_processus)
2467: {
2468: int decalage;
2469: int i;
2470: int longueur_tableau;
2471:
2472: unsigned char caractere;
2473:
2474: // Récupération de la longueur d'un unsigned char
2475:
2476: longueur_tableau = 1;
2477: decalage = 0;
2478: caractere = 1;
2479:
2480: while((1L << decalage) == (long) ((unsigned char) (caractere << decalage)))
2481: {
2482: decalage++;
2483: longueur_tableau *= 2;
2484: }
2485:
2486: if (((*s_etat_processus).pointeurs_caracteres_variables =
2487: malloc(((size_t) longueur_tableau) * sizeof(int))) == NULL)
2488: {
2489: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
2490: return;
2491: }
2492:
2493: for(i = 0; i < longueur_tableau; i++)
2494: {
2495: (*s_etat_processus).pointeurs_caracteres_variables[i] = -1;
2496: }
2497:
2498: (*s_etat_processus).nombre_caracteres_variables = 0;
2499:
2500: #define DECLARATION_CARACTERE(c) \
2501: do { (*s_etat_processus).pointeurs_caracteres_variables[c] = \
2502: (*s_etat_processus).nombre_caracteres_variables++; } while(0)
2503:
2504: DECLARATION_CARACTERE('A');
2505: DECLARATION_CARACTERE('B');
2506: DECLARATION_CARACTERE('C');
2507: DECLARATION_CARACTERE('D');
2508: DECLARATION_CARACTERE('E');
2509: DECLARATION_CARACTERE('F');
2510: DECLARATION_CARACTERE('G');
2511: DECLARATION_CARACTERE('H');
2512: DECLARATION_CARACTERE('I');
2513: DECLARATION_CARACTERE('J');
2514: DECLARATION_CARACTERE('K');
2515: DECLARATION_CARACTERE('L');
2516: DECLARATION_CARACTERE('M');
2517: DECLARATION_CARACTERE('N');
2518: DECLARATION_CARACTERE('O');
2519: DECLARATION_CARACTERE('P');
2520: DECLARATION_CARACTERE('Q');
2521: DECLARATION_CARACTERE('R');
2522: DECLARATION_CARACTERE('S');
2523: DECLARATION_CARACTERE('T');
2524: DECLARATION_CARACTERE('U');
2525: DECLARATION_CARACTERE('V');
2526: DECLARATION_CARACTERE('W');
2527: DECLARATION_CARACTERE('X');
2528: DECLARATION_CARACTERE('Y');
2529: DECLARATION_CARACTERE('Z');
2530:
2531: DECLARATION_CARACTERE('a');
2532: DECLARATION_CARACTERE('b');
2533: DECLARATION_CARACTERE('c');
2534: DECLARATION_CARACTERE('d');
2535: DECLARATION_CARACTERE('e');
2536: DECLARATION_CARACTERE('f');
2537: DECLARATION_CARACTERE('g');
2538: DECLARATION_CARACTERE('h');
2539: DECLARATION_CARACTERE('i');
2540: DECLARATION_CARACTERE('j');
2541: DECLARATION_CARACTERE('k');
2542: DECLARATION_CARACTERE('l');
2543: DECLARATION_CARACTERE('m');
2544: DECLARATION_CARACTERE('n');
2545: DECLARATION_CARACTERE('o');
2546: DECLARATION_CARACTERE('p');
2547: DECLARATION_CARACTERE('q');
2548: DECLARATION_CARACTERE('r');
2549: DECLARATION_CARACTERE('s');
2550: DECLARATION_CARACTERE('t');
2551: DECLARATION_CARACTERE('u');
2552: DECLARATION_CARACTERE('v');
2553: DECLARATION_CARACTERE('w');
2554: DECLARATION_CARACTERE('x');
2555: DECLARATION_CARACTERE('y');
2556: DECLARATION_CARACTERE('z');
2557:
2558: DECLARATION_CARACTERE('_');
2559:
2560: DECLARATION_CARACTERE('1');
2561: DECLARATION_CARACTERE('2');
2562: DECLARATION_CARACTERE('3');
2563: DECLARATION_CARACTERE('4');
2564: DECLARATION_CARACTERE('5');
2565: DECLARATION_CARACTERE('6');
2566: DECLARATION_CARACTERE('7');
2567: DECLARATION_CARACTERE('8');
2568: DECLARATION_CARACTERE('9');
2569: DECLARATION_CARACTERE('0');
2570: #undef DECLARATION_CARACTERE
2571:
2572: return;
2573: }
2574:
2575: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>