1: /*
2: ================================================================================
3: RPL/2 (R) version 4.1.13
4: Copyright (C) 1989-2013 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: while((*(*s_etat_processus).l_liste_variables_par_niveau).liste
1535: != NULL)
1536: {
1537: // Nécessaire car le pointeur sur la tête de la pile
1538: // peut être modifié par retrait_variable().
1539: // Sauvegarde des variables statiques.
1540:
1541: if ((*((struct_variable *) (*(*(*s_etat_processus)
1542: .l_liste_variables_par_niveau).liste).donnee)).origine
1543: == 'P')
1544: {
1545: if ((*((struct_variable *) (*(*(*s_etat_processus)
1546: .l_liste_variables_par_niveau).liste).donnee))
1547: .variable_statique.adresse != 0)
1548: {
1549: if (recherche_variable_statique(s_etat_processus,
1550: (*((struct_variable *) (*(*(*s_etat_processus)
1551: .l_liste_variables_par_niveau).liste).donnee))
1552: .nom, (*((struct_variable *)
1553: (*(*(*s_etat_processus)
1554: .l_liste_variables_par_niveau).liste).donnee))
1555: .variable_statique, ((*s_etat_processus)
1556: .mode_execution_programme
1557: == 'Y') ? 'P' : 'E') != NULL)
1558: {
1559: (*(*s_etat_processus)
1560: .pointeur_variable_statique_courante)
1561: .objet = (*((struct_variable *)
1562: (*(*(*s_etat_processus)
1563: .l_liste_variables_par_niveau).liste)
1564: .donnee)).objet;
1565: }
1566: else
1567: {
1568: (*s_etat_processus).erreur_systeme =
1569: d_es_variable_introuvable;
1570: }
1571:
1572: (*((struct_variable *) (*(*(*s_etat_processus)
1573: .l_liste_variables_par_niveau).liste).donnee))
1574: .objet = NULL;
1575: }
1576: }
1577: else
1578: {
1579: if ((*((struct_variable *) (*(*(*s_etat_processus)
1580: .l_liste_variables_par_niveau).liste).donnee))
1581: .variable_statique.pointeur != NULL)
1582: {
1583: /*
1584: * Gestion des variables statiques
1585: */
1586:
1587: if (recherche_variable_statique(s_etat_processus,
1588: (*((struct_variable *) (*(*(*s_etat_processus)
1589: .l_liste_variables_par_niveau).liste).donnee))
1590: .nom, (*((struct_variable *)
1591: (*(*(*s_etat_processus)
1592: .l_liste_variables_par_niveau).liste).donnee))
1593: .variable_statique, ((*s_etat_processus)
1594: .mode_execution_programme
1595: == 'Y') ? 'P' : 'E') != NULL)
1596: {
1597: (*(*s_etat_processus)
1598: .pointeur_variable_statique_courante)
1599: .objet = (*((struct_variable *)
1600: (*(*(*s_etat_processus)
1601: .l_liste_variables_par_niveau).liste)
1602: .donnee)).objet;
1603: }
1604: else
1605: {
1606: (*s_etat_processus).erreur_systeme =
1607: d_es_variable_introuvable;
1608: return(d_erreur);
1609: }
1610:
1611: (*((struct_variable *) (*(*(*s_etat_processus)
1612: .l_liste_variables_par_niveau).liste).donnee))
1613: .objet = NULL;
1614: }
1615: }
1616:
1617: if (retrait_variable(s_etat_processus,
1618: (*((struct_variable *) (*(*(*s_etat_processus)
1619: .l_liste_variables_par_niveau).liste).donnee)).nom,
1620: 'L') == d_erreur)
1621: {
1622: return(d_erreur);
1623: }
1624:
1625: if ((*((struct_variable *) (*(*(*s_etat_processus)
1626: .l_liste_variables_par_niveau).liste).donnee)).niveau
1627: <= (*s_etat_processus).niveau_courant)
1628: {
1629: // On a retiré de l'arbre des variables toutes les
1630: // variables de niveau strictement supérieur au niveau
1631: // courant.
1632:
1633: return(d_absence_erreur);
1634: }
1635: }
1636: }
1637:
1638: // On retire l'élément de la liste doublement chaînée et circulaire.
1639:
1640: (*(*(*s_etat_processus).l_liste_variables_par_niveau).precedent).suivant
1641: = (*(*s_etat_processus).l_liste_variables_par_niveau).suivant;
1642: (*(*(*s_etat_processus).l_liste_variables_par_niveau).suivant).precedent
1643: = (*(*s_etat_processus).l_liste_variables_par_niveau).precedent;
1644:
1645: l_element_a_supprimer = (*s_etat_processus)
1646: .l_liste_variables_par_niveau;
1647: (*s_etat_processus).l_liste_variables_par_niveau =
1648: (*l_element_a_supprimer).suivant;
1649: liberation_feuille(s_etat_processus, l_element_a_supprimer);
1650: }
1651:
1652: return(d_absence_erreur);
1653: }
1654:
1655:
1656: /*
1657: ================================================================================
1658: Procédure de retrait des toutes les variables locales et globales
1659: ================================================================================
1660: Entrée : drapeau indiquant s'il faut retirer les définitions (variables
1661: de niveau 0)
1662: --------------------------------------------------------------------------------
1663: Sortie :
1664: --------------------------------------------------------------------------------
1665: Effets de bord : néant
1666: ================================================================================
1667: */
1668:
1669: void
1670: liberation_arbre_variables(struct_processus *s_etat_processus,
1671: struct_arbre_variables *arbre, logical1 retrait_definitions)
1672: {
1673: int i;
1674:
1675: struct_liste_chainee *l_element_courant_liste;
1676: struct_liste_chainee *l_element_suivant_liste;
1677:
1678: struct_liste_variables *l_element_courant;
1679: struct_liste_variables *l_element_suivant;
1680:
1681: struct_liste_variables_statiques *l_element_statique_courant;
1682: struct_liste_variables_statiques *l_element_statique_suivant;
1683:
1684: // Libération de l'arbre des variables. Le contenu des variables n'est
1685: // pas détruit par cette opération, il sera détruit lors de la libération
1686: // de la liste des variables par niveau.
1687:
1688: if (arbre == NULL)
1689: {
1690: return;
1691: }
1692:
1693: l_element_courant = (*arbre).feuille;
1694:
1695: if (l_element_courant != NULL)
1696: {
1697: do
1698: {
1699: l_element_suivant = (*l_element_courant).suivant;
1700: liberation_feuille(s_etat_processus, l_element_courant);
1701: l_element_courant = l_element_suivant;
1702: } while(l_element_courant != (*arbre).feuille);
1703:
1704: (*arbre).feuille = NULL;
1705: }
1706:
1707: l_element_statique_courant = (*arbre).feuille_statique;
1708:
1709: while(l_element_statique_courant != NULL)
1710: {
1711: l_element_statique_suivant = (*l_element_statique_courant).suivant;
1712:
1713: free((*(*l_element_statique_courant).variable).nom);
1714: liberation(s_etat_processus, (*(*l_element_statique_courant)
1715: .variable).objet);
1716: free((*l_element_statique_courant).variable);
1717: free(l_element_statique_courant);
1718:
1719: l_element_statique_courant = l_element_statique_suivant;
1720: }
1721:
1722: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
1723: {
1724: if ((*arbre).noeuds[i] != NULL)
1725: {
1726: liberation_arbre_variables(s_etat_processus, (*arbre).noeuds[i],
1727: retrait_definitions);
1728: (*arbre).noeuds[i] = NULL;
1729: }
1730: }
1731:
1732: // Suppression de la liste des variables par niveau.
1733:
1734: if (arbre == (*s_etat_processus).s_arbre_variables)
1735: {
1736: l_element_courant = (*s_etat_processus).l_liste_variables_par_niveau;
1737:
1738: if (l_element_courant != NULL)
1739: {
1740: do
1741: {
1742: l_element_courant_liste = (*l_element_courant).liste;
1743:
1744: while(l_element_courant_liste != NULL)
1745: {
1746: if ((retrait_definitions == d_vrai) ||
1747: ((*((struct_variable *) (*l_element_courant_liste)
1748: .donnee)).niveau >= 1))
1749: {
1750: liberation(s_etat_processus, (*((struct_variable *)
1751: (*l_element_courant_liste).donnee)).objet);
1752: free((*((struct_variable *) (*l_element_courant_liste)
1753: .donnee)).nom);
1754: }
1755:
1756: l_element_suivant_liste =
1757: (*l_element_courant_liste).suivant;
1758: liberation_variable(s_etat_processus, (struct_variable *)
1759: (*l_element_courant_liste).donnee);
1760: liberation_maillon(s_etat_processus,
1761: l_element_courant_liste);
1762: l_element_courant_liste = l_element_suivant_liste;
1763: }
1764:
1765: l_element_suivant = (*l_element_courant).suivant;
1766: liberation_feuille(s_etat_processus, l_element_courant);
1767: l_element_courant = l_element_suivant;
1768: } while(l_element_courant != (*s_etat_processus)
1769: .l_liste_variables_par_niveau);
1770: }
1771: }
1772:
1773: liberation_tableau_noeuds(s_etat_processus, (*arbre).noeuds);
1774: liberation_noeud(s_etat_processus, arbre);
1775: arbre = NULL;
1776:
1777: return;
1778: }
1779:
1780:
1781: /*
1782: ================================================================================
1783: Procédure renvoyant les variables dans un tableau
1784: ================================================================================
1785: Entrée :
1786: --------------------------------------------------------------------------------
1787: Sortie :
1788: --------------------------------------------------------------------------------
1789: Effets de bord : néant
1790: ================================================================================
1791: */
1792:
1793: static integer8
1794: nombre_variables_locales(struct_processus *s_etat_processus,
1795: struct_arbre_variables *l_element_courant)
1796: {
1797: integer8 i;
1798: integer8 n;
1799:
1800: struct_liste_variables *l_variable;
1801: struct_liste_variables_statiques *l_variable_statique;
1802:
1803: if (l_element_courant == NULL)
1804: {
1805: return(0);
1806: }
1807:
1808: n = 0;
1809:
1810: if ((*l_element_courant).feuille != NULL)
1811: {
1812: l_variable = (*l_element_courant).feuille;
1813:
1814: do
1815: {
1816: n++;
1817: l_variable = (*l_variable).suivant;
1818: } while(l_variable != (*l_element_courant).feuille);
1819: }
1820:
1821: if ((*l_element_courant).feuille_statique != NULL)
1822: {
1823: l_variable_statique = (*l_element_courant).feuille_statique;
1824:
1825: do
1826: {
1827: // Si le pointeur est nul, la variable est accessible et a été
1828: // copiée dans l'arbre des variables.
1829:
1830: if ((*(*l_variable_statique).variable).objet != NULL)
1831: {
1832: n++;
1833: }
1834:
1835: l_variable_statique = (*l_variable_statique).suivant;
1836: } while(l_variable_statique != NULL);
1837: }
1838:
1839: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
1840: {
1841: if ((*l_element_courant).noeuds[i] != NULL)
1842: {
1843: n += nombre_variables_locales(s_etat_processus,
1844: (*l_element_courant).noeuds[i]);
1845: }
1846: }
1847:
1848: return(n);
1849: }
1850:
1851:
1852: static integer8
1853: nombre_variables_partagees(struct_processus *s_etat_processus,
1854: struct_arbre_variables_partagees *l_element_courant)
1855: {
1856: integer8 i;
1857: integer8 n;
1858:
1859: struct_liste_variables_partagees *l_variable;
1860:
1861: if (l_element_courant == NULL)
1862: {
1863: return(0);
1864: }
1865:
1866: if (pthread_mutex_lock(&((*l_element_courant).mutex_feuille)) != 0)
1867: {
1868: (*s_etat_processus).erreur_systeme = d_es_processus;
1869: return(0);
1870: }
1871:
1872: n = 0;
1873:
1874: if ((*l_element_courant).feuille != NULL)
1875: {
1876: l_variable = (*l_element_courant).feuille;
1877:
1878: do
1879: {
1880: n++;
1881: l_variable = (*l_variable).suivant;
1882: } while(l_variable != NULL);
1883: }
1884:
1885: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
1886: {
1887: if ((*l_element_courant).noeuds[i] != NULL)
1888: {
1889: n += nombre_variables_partagees(s_etat_processus,
1890: (*l_element_courant).noeuds[i]);
1891: }
1892: }
1893:
1894: return(n);
1895: }
1896:
1897:
1898: integer8
1899: nombre_variables(struct_processus *s_etat_processus)
1900: {
1901: return(nombre_variables_locales(s_etat_processus,
1902: (*s_etat_processus).s_arbre_variables)
1903: + nombre_variables_partagees(s_etat_processus,
1904: (*(*s_etat_processus).s_arbre_variables_partagees)));
1905: }
1906:
1907:
1908: void
1909: liberation_mutexes_arbre_variables_partagees(struct_processus *s_etat_processus,
1910: struct_arbre_variables_partagees *l_element_courant)
1911: {
1912: int i;
1913:
1914: if (l_element_courant == NULL)
1915: {
1916: return;
1917: }
1918:
1919: if (pthread_mutex_trylock(&((*l_element_courant).mutex_feuille)) != 0)
1920: {
1921: (*s_etat_processus).erreur_systeme = d_es_processus;
1922: return;
1923: }
1924:
1925: if (pthread_mutex_unlock(&((*l_element_courant).mutex_feuille)) != 0)
1926: {
1927: (*s_etat_processus).erreur_systeme = d_es_processus;
1928: return;
1929: }
1930:
1931: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
1932: {
1933: if ((*l_element_courant).noeuds[i] != NULL)
1934: {
1935: liberation_mutexes_arbre_variables_partagees(s_etat_processus,
1936: (*l_element_courant).noeuds[i]);
1937: }
1938: }
1939:
1940: return;
1941: }
1942:
1943:
1944: static integer8
1945: liste_variables_locales(struct_processus *s_etat_processus,
1946: struct_tableau_variables *tableau, integer8 position,
1947: struct_arbre_variables *l_element_courant)
1948: {
1949: integer8 i;
1950:
1951: struct_liste_variables *l_variable;
1952: struct_liste_variables_statiques *l_variable_statique;
1953:
1954: if (l_element_courant == NULL)
1955: {
1956: return(0);
1957: }
1958:
1959: if ((*l_element_courant).feuille != NULL)
1960: {
1961: l_variable = (*l_element_courant).feuille;
1962:
1963: do
1964: {
1965: tableau[position].origine = (*(*l_variable).variable).origine;
1966: tableau[position].nom = (*(*l_variable).variable).nom;
1967: tableau[position].niveau = (*(*l_variable).variable).niveau;
1968: tableau[position].objet = (*(*l_variable).variable).objet;
1969: tableau[position].variable_verrouillee =
1970: (*(*l_variable).variable).variable_verrouillee;
1971: tableau[position].variable_statique =
1972: (*(*l_variable).variable).variable_statique;
1973: tableau[position].variable_partagee =
1974: (*(*l_variable).variable).variable_partagee;
1975: tableau[position].variable_masquee = d_faux;
1976:
1977: position++;
1978: l_variable = (*l_variable).suivant;
1979: } while(l_variable != (*l_element_courant).feuille);
1980: }
1981:
1982: if ((*l_element_courant).feuille_statique != NULL)
1983: {
1984: l_variable_statique = (*l_element_courant).feuille_statique;
1985:
1986: do
1987: {
1988: if ((*(*l_variable_statique).variable).objet != NULL)
1989: {
1990: tableau[position].origine = 'E';
1991: tableau[position].nom = (*(*l_variable_statique).variable).nom;
1992: tableau[position].niveau =
1993: (*(*l_variable_statique).variable).niveau;
1994: tableau[position].objet =
1995: (*(*l_variable_statique).variable).objet;
1996: tableau[position].variable_verrouillee = d_faux;
1997: tableau[position].variable_statique =
1998: (*(*l_variable_statique).variable).variable_statique;
1999: tableau[position].variable_partagee.pointeur = NULL;
2000: tableau[position].variable_masquee = d_vrai;
2001:
2002: position++;
2003: }
2004:
2005: l_variable_statique = (*l_variable_statique).suivant;
2006: } while(l_variable_statique != NULL);
2007: }
2008:
2009: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
2010: {
2011: if ((*l_element_courant).noeuds[i] != NULL)
2012: {
2013: position = liste_variables_locales(s_etat_processus,
2014: tableau, position, (*l_element_courant).noeuds[i]);
2015: }
2016: }
2017:
2018: return(position);
2019: }
2020:
2021:
2022: static integer8
2023: liste_variables_partagees(struct_processus *s_etat_processus,
2024: struct_tableau_variables *tableau, integer8 position,
2025: struct_arbre_variables_partagees *l_element_courant)
2026: {
2027: integer8 i;
2028:
2029: struct_liste_variables_partagees *l_variable;
2030:
2031: if (l_element_courant == NULL)
2032: {
2033: return(0);
2034: }
2035:
2036: // mutex_liste_variables_partagees
2037: // et (*l_variable_courante).mutex_feuille
2038: if ((*l_element_courant).feuille != NULL)
2039: {
2040: l_variable = (*l_element_courant).feuille;
2041:
2042: do
2043: {
2044: tableau[position].origine = 'E';
2045: tableau[position].nom = (*(*l_variable).variable).nom;
2046: tableau[position].niveau = (*(*l_variable).variable).niveau;
2047: tableau[position].objet = (*(*l_variable).variable).objet;
2048: tableau[position].variable_verrouillee = d_faux;
2049: tableau[position].variable_partagee =
2050: (*(*l_variable).variable).variable_partagee;
2051: tableau[position].variable_partagee.pointeur = NULL;
2052: tableau[position].variable_masquee = d_faux;
2053:
2054: position++;
2055:
2056: l_variable = (*l_variable).suivant;
2057: } while(l_variable != NULL);
2058: }
2059:
2060: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
2061: {
2062: if ((*l_element_courant).noeuds[i] != NULL)
2063: {
2064: position = liste_variables_partagees(s_etat_processus,
2065: tableau, position, (*l_element_courant).noeuds[i]);
2066: }
2067: }
2068:
2069: return(position);
2070: }
2071:
2072:
2073: static int
2074: fonction_ordre_variables(const void *argument_1, const void *argument_2)
2075: {
2076: int comparaison;
2077:
2078: struct_tableau_variables *a1;
2079: struct_tableau_variables *a2;
2080:
2081: a1 = (struct_tableau_variables *) argument_1;
2082: a2 = (struct_tableau_variables *) argument_2;
2083:
2084: comparaison = strcmp((*a1).nom, (*a2).nom);
2085:
2086: if (comparaison != 0)
2087: {
2088: return(comparaison);
2089: }
2090: else
2091: {
2092: return(((((*a1).niveau - (*a2).niveau)) > 0) ? 1 : -1);
2093: }
2094: }
2095:
2096:
2097: integer8
2098: liste_variables(struct_processus *s_etat_processus,
2099: struct_tableau_variables *tableau)
2100: {
2101: integer8 nombre_elements;
2102:
2103: nombre_elements = liste_variables_locales(s_etat_processus,
2104: tableau, 0, (*s_etat_processus).s_arbre_variables);
2105: nombre_elements += liste_variables_partagees(s_etat_processus,
2106: tableau, nombre_elements, (*(*s_etat_processus)
2107: .s_arbre_variables_partagees));
2108:
2109: qsort(tableau, (size_t) nombre_elements, sizeof(struct_tableau_variables),
2110: fonction_ordre_variables);
2111:
2112: return(nombre_elements);
2113: }
2114:
2115:
2116: /*
2117: ================================================================================
2118: Procédure de copie de l'arbre des variables
2119: ================================================================================
2120: Entrée :
2121: --------------------------------------------------------------------------------
2122: Sortie :
2123: --------------------------------------------------------------------------------
2124: Effets de bord : néant
2125: ================================================================================
2126: */
2127:
2128: void
2129: copie_arbre_variables(struct_processus *s_etat_processus, struct_processus
2130: *s_nouvel_etat_processus)
2131: {
2132: // Les définitions sont partagées entre tous les threads et ne sont pas
2133: // copiées.
2134: //
2135: // NB : on ne copie que les variables de niveaux 0 et 1, les autres
2136: // variables locales étant masquées par le processus de création de thread
2137: // ou de processus, elles seront inaccessibles de tous les points
2138: // du fil d'exécution fils.
2139:
2140: // Pour copier ces variables, on récupère les variables depuis la liste par
2141: // niveaux (niveaux 0 et 1) et on ajoute les variables dans la nouvelle
2142: // structure. Les variables de niveau 0 étant non modifiables, elles
2143: // ne sont pas dupliquées.
2144:
2145: int i;
2146:
2147: logical1 niveau_0_traite;
2148: logical1 niveau_1_traite;
2149:
2150: struct_arbre_variables *l_variable_courante;
2151:
2152: struct_liste_chainee *l_element_courant;
2153:
2154: struct_liste_variables *l_niveau_courant;
2155: struct_liste_variables_statiques *l_element_statique_courant;
2156:
2157: struct_variable s_variable;
2158: struct_variable_statique s_variable_statique;
2159:
2160: unsigned char *ptr;
2161:
2162: (*s_nouvel_etat_processus).s_arbre_variables = NULL;
2163: (*s_nouvel_etat_processus).l_liste_variables_par_niveau = NULL;
2164:
2165: l_niveau_courant = (*s_etat_processus).l_liste_variables_par_niveau;
2166:
2167: // Si la variable en tête n'est pas une variable de niveau 0, le niveau
2168: // 0, s'il existe est le niveau précédent la valeur courante dans la
2169: // boucle.
2170:
2171: if ((*((struct_variable *) (*(*l_niveau_courant).liste).donnee)).niveau
2172: != 0)
2173: {
2174: l_niveau_courant = (*l_niveau_courant).precedent;
2175: }
2176:
2177: // Les variables de niveaux 0 et 1 sont accessibles en au plus trois
2178: // itérations (par construction).
2179:
2180: niveau_0_traite = d_faux;
2181: niveau_1_traite = d_faux;
2182:
2183: for(i = 0; i <= 2; i++)
2184: {
2185: if ((*((struct_variable *) (*(*l_niveau_courant).liste)
2186: .donnee)).niveau == 0)
2187: {
2188: if (niveau_0_traite == d_faux)
2189: {
2190: l_element_courant = (*l_niveau_courant).liste;
2191:
2192: while(l_element_courant != NULL)
2193: {
2194: if (ajout_variable(s_nouvel_etat_processus,
2195: (struct_variable *) (*l_element_courant).donnee)
2196: == d_erreur)
2197: {
2198: return;
2199: }
2200:
2201: l_element_courant = (*l_element_courant).suivant;
2202: }
2203:
2204: niveau_0_traite = d_vrai;
2205: }
2206: }
2207: else if ((*((struct_variable *) (*(*l_niveau_courant).liste)
2208: .donnee)).niveau == 1)
2209: {
2210: if (niveau_1_traite == d_faux)
2211: {
2212: l_element_courant = (*l_niveau_courant).liste;
2213:
2214: while(l_element_courant != NULL)
2215: {
2216: s_variable = (*((struct_variable *)
2217: (*l_element_courant).donnee));
2218:
2219: if ((s_variable.nom = strdup((*((struct_variable *)
2220: (*l_element_courant).donnee)).nom)) == NULL)
2221: {
2222: (*s_nouvel_etat_processus).erreur_systeme =
2223: d_es_allocation_memoire;
2224: return;
2225: }
2226:
2227: if ((s_variable.objet = copie_objet(s_nouvel_etat_processus,
2228: (*((struct_variable *) (*l_element_courant).donnee))
2229: .objet, 'P')) == NULL)
2230: {
2231: (*s_nouvel_etat_processus).erreur_systeme =
2232: d_es_allocation_memoire;
2233: return;
2234: }
2235:
2236: if (ajout_variable(s_nouvel_etat_processus, &s_variable)
2237: == d_erreur)
2238: {
2239: return;
2240: }
2241:
2242: l_element_courant = (*l_element_courant).suivant;
2243: }
2244:
2245: niveau_1_traite = d_vrai;
2246: }
2247:
2248: // Les variables de niveau 0 ayant déjà été copiées, on
2249: // peut sortir de la boucle car toutes les variables sont
2250: // maintenant disponibles dans le fil d'exécution fils.
2251:
2252: break;
2253: }
2254:
2255: l_niveau_courant = (*l_niveau_courant).precedent;
2256: }
2257:
2258: // Copie des variables statiques
2259:
2260: l_element_statique_courant = (*s_etat_processus)
2261: .l_liste_variables_statiques;
2262:
2263: while(l_element_statique_courant != NULL)
2264: {
2265: // Création des branches de l'arbre si nécessaire.
2266:
2267: if ((*s_nouvel_etat_processus).s_arbre_variables == NULL)
2268: {
2269: if (((*s_nouvel_etat_processus).s_arbre_variables =
2270: allocation_noeud(s_nouvel_etat_processus)) == NULL)
2271: {
2272: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
2273: return;
2274: }
2275:
2276: (*(*s_nouvel_etat_processus).s_arbre_variables).feuille = NULL;
2277: (*(*s_nouvel_etat_processus).s_arbre_variables).feuille_statique
2278: = NULL;
2279: (*(*s_nouvel_etat_processus).s_arbre_variables).noeuds_utilises = 0;
2280: (*(*s_nouvel_etat_processus).s_arbre_variables).indice_tableau_pere
2281: = -1;
2282: (*(*s_nouvel_etat_processus).s_arbre_variables).noeud_pere = NULL;
2283:
2284: if (((*(*s_nouvel_etat_processus).s_arbre_variables).noeuds =
2285: allocation_tableau_noeuds(s_nouvel_etat_processus)) == NULL)
2286: {
2287: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
2288: return;
2289: }
2290:
2291: for(i = 0; i < (*s_nouvel_etat_processus)
2292: .nombre_caracteres_variables; i++)
2293: {
2294: (*(*s_nouvel_etat_processus).s_arbre_variables).noeuds[i]
2295: = NULL;
2296: }
2297: }
2298:
2299: l_variable_courante = (*s_nouvel_etat_processus).s_arbre_variables;
2300: ptr = (*(*l_element_statique_courant).variable).nom;
2301:
2302: while((*ptr) != d_code_fin_chaine)
2303: {
2304: BUG((*s_nouvel_etat_processus).pointeurs_caracteres_variables
2305: [*ptr] < 0, uprintf("Variable=\"%s\", (*ptr)='%c'\n",
2306: (*(*l_element_statique_courant).variable).nom, *ptr));
2307:
2308: if ((*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2309: .pointeurs_caracteres_variables[*ptr]] == NULL)
2310: {
2311: // Le noeud n'existe pas encore, on le crée et on le marque
2312: // comme utilisé dans la structure parente.
2313:
2314: if (((*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2315: .pointeurs_caracteres_variables[*ptr]] =
2316: allocation_noeud(s_nouvel_etat_processus)) == NULL)
2317: {
2318: (*s_etat_processus).erreur_systeme =
2319: d_es_allocation_memoire;
2320: return;
2321: }
2322:
2323: (*l_variable_courante).noeuds_utilises++;
2324:
2325: // La feuille est par défaut vide et aucun élément du tableau
2326: // noeuds (les branches qui peuvent être issues de ce nouveau
2327: // noeud) n'est encore utilisée.
2328:
2329: (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2330: .pointeurs_caracteres_variables[*ptr]]).feuille = NULL;
2331: (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2332: .pointeurs_caracteres_variables[*ptr]]).feuille_statique
2333: = NULL;
2334: (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2335: .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises
2336: = 0;
2337:
2338: // Le champ noeud_pere de la structure créée pointe sur
2339: // la structure parente et l'indice tableau_pere correspond à la
2340: // position réelle dans le tableau noeuds[] de la structure
2341: // parente du noeud courant. Cette valeur sera utilisée lors de
2342: // la destruction du noeud pour annuler le pointeur contenu dans
2343: // le tableau noeuds[] de la structure parente.
2344:
2345: (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2346: .pointeurs_caracteres_variables[*ptr]]).noeud_pere =
2347: l_variable_courante;
2348: (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2349: .pointeurs_caracteres_variables[*ptr]])
2350: .indice_tableau_pere = (*s_nouvel_etat_processus)
2351: .pointeurs_caracteres_variables[*ptr];
2352:
2353: // Allocation du tableau noeuds[] et initialisation à zéro de
2354: // tous les pointeurs.
2355:
2356: if (((*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2357: .pointeurs_caracteres_variables[*ptr]]).noeuds =
2358: allocation_tableau_noeuds(s_nouvel_etat_processus))
2359: == NULL)
2360: {
2361: (*s_etat_processus).erreur_systeme
2362: = d_es_allocation_memoire;
2363: return;
2364: }
2365:
2366: for(i = 0; i < (*s_nouvel_etat_processus)
2367: .nombre_caracteres_variables; i++)
2368: {
2369: (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
2370: .pointeurs_caracteres_variables[*ptr]]).noeuds[i]
2371: = NULL;
2372: }
2373: }
2374:
2375: l_variable_courante = (*l_variable_courante).noeuds
2376: [(*s_nouvel_etat_processus).pointeurs_caracteres_variables
2377: [*ptr]];
2378:
2379: ptr++;
2380: }
2381:
2382: // Il faut copier la variable pour la dissocier de la variable
2383: // restant dans le thread parent.
2384:
2385: s_variable_statique = (*(*l_element_statique_courant).variable);
2386:
2387: if (copie_objet(s_etat_processus, s_variable_statique.objet, 'P')
2388: == NULL)
2389: {
2390: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
2391: return;
2392: }
2393:
2394: if ((s_variable_statique.nom = malloc((strlen(
2395: (*(*l_element_statique_courant).variable).nom) + 1) *
2396: sizeof(unsigned char))) == NULL)
2397: {
2398: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
2399: return;
2400: }
2401:
2402: strcpy(s_variable_statique.nom, (*(*l_element_statique_courant)
2403: .variable).nom);
2404:
2405: if (creation_variable_statique(s_nouvel_etat_processus,
2406: &s_variable_statique) == d_erreur)
2407: {
2408: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
2409: return;
2410: }
2411:
2412: l_element_statique_courant = (*l_element_statique_courant).suivant;
2413: }
2414:
2415: return;
2416: }
2417:
2418:
2419: /*
2420: ================================================================================
2421: Procédure d'initialisation de la table de correspondance des variables
2422: ================================================================================
2423: Entrée :
2424: --------------------------------------------------------------------------------
2425: Sortie :
2426: --------------------------------------------------------------------------------
2427: Effets de bord : néant
2428: ================================================================================
2429: */
2430:
2431: /*
2432: * Caractères autorisés dans les instructions
2433: *
2434: * 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
2435: * 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
2436: * _
2437: * 1 2 3 4 5 6 7 8 9 0
2438: */
2439:
2440: void
2441: initialisation_variables(struct_processus *s_etat_processus)
2442: {
2443: int decalage;
2444: int i;
2445: int longueur_tableau;
2446:
2447: unsigned char caractere;
2448:
2449: // Récupération de la longueur d'un unsigned char
2450:
2451: longueur_tableau = 1;
2452: decalage = 0;
2453: caractere = 1;
2454:
2455: while((1L << decalage) == (long) ((unsigned char) (caractere << decalage)))
2456: {
2457: decalage++;
2458: longueur_tableau *= 2;
2459: }
2460:
2461: if (((*s_etat_processus).pointeurs_caracteres_variables =
2462: malloc(((size_t) longueur_tableau) * sizeof(int))) == NULL)
2463: {
2464: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
2465: return;
2466: }
2467:
2468: for(i = 0; i < longueur_tableau; i++)
2469: {
2470: (*s_etat_processus).pointeurs_caracteres_variables[i] = -1;
2471: }
2472:
2473: (*s_etat_processus).nombre_caracteres_variables = 0;
2474:
2475: #define DECLARATION_CARACTERE(c) \
2476: do { (*s_etat_processus).pointeurs_caracteres_variables[c] = \
2477: (*s_etat_processus).nombre_caracteres_variables++; } while(0)
2478:
2479: DECLARATION_CARACTERE('A');
2480: DECLARATION_CARACTERE('B');
2481: DECLARATION_CARACTERE('C');
2482: DECLARATION_CARACTERE('D');
2483: DECLARATION_CARACTERE('E');
2484: DECLARATION_CARACTERE('F');
2485: DECLARATION_CARACTERE('G');
2486: DECLARATION_CARACTERE('H');
2487: DECLARATION_CARACTERE('I');
2488: DECLARATION_CARACTERE('J');
2489: DECLARATION_CARACTERE('K');
2490: DECLARATION_CARACTERE('L');
2491: DECLARATION_CARACTERE('M');
2492: DECLARATION_CARACTERE('N');
2493: DECLARATION_CARACTERE('O');
2494: DECLARATION_CARACTERE('P');
2495: DECLARATION_CARACTERE('Q');
2496: DECLARATION_CARACTERE('R');
2497: DECLARATION_CARACTERE('S');
2498: DECLARATION_CARACTERE('T');
2499: DECLARATION_CARACTERE('U');
2500: DECLARATION_CARACTERE('V');
2501: DECLARATION_CARACTERE('W');
2502: DECLARATION_CARACTERE('X');
2503: DECLARATION_CARACTERE('Y');
2504: DECLARATION_CARACTERE('Z');
2505:
2506: DECLARATION_CARACTERE('a');
2507: DECLARATION_CARACTERE('b');
2508: DECLARATION_CARACTERE('c');
2509: DECLARATION_CARACTERE('d');
2510: DECLARATION_CARACTERE('e');
2511: DECLARATION_CARACTERE('f');
2512: DECLARATION_CARACTERE('g');
2513: DECLARATION_CARACTERE('h');
2514: DECLARATION_CARACTERE('i');
2515: DECLARATION_CARACTERE('j');
2516: DECLARATION_CARACTERE('k');
2517: DECLARATION_CARACTERE('l');
2518: DECLARATION_CARACTERE('m');
2519: DECLARATION_CARACTERE('n');
2520: DECLARATION_CARACTERE('o');
2521: DECLARATION_CARACTERE('p');
2522: DECLARATION_CARACTERE('q');
2523: DECLARATION_CARACTERE('r');
2524: DECLARATION_CARACTERE('s');
2525: DECLARATION_CARACTERE('t');
2526: DECLARATION_CARACTERE('u');
2527: DECLARATION_CARACTERE('v');
2528: DECLARATION_CARACTERE('w');
2529: DECLARATION_CARACTERE('x');
2530: DECLARATION_CARACTERE('y');
2531: DECLARATION_CARACTERE('z');
2532:
2533: DECLARATION_CARACTERE('_');
2534:
2535: DECLARATION_CARACTERE('1');
2536: DECLARATION_CARACTERE('2');
2537: DECLARATION_CARACTERE('3');
2538: DECLARATION_CARACTERE('4');
2539: DECLARATION_CARACTERE('5');
2540: DECLARATION_CARACTERE('6');
2541: DECLARATION_CARACTERE('7');
2542: DECLARATION_CARACTERE('8');
2543: DECLARATION_CARACTERE('9');
2544: DECLARATION_CARACTERE('0');
2545: #undef DECLARATION_CARACTERE
2546:
2547: return;
2548: }
2549:
2550: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>