File:
[local] /
rpl /
src /
gestion_variables.c
Revision
1.39:
download - view:
text,
annotated -
select for diffs -
revision graph
Tue Jun 21 15:26:29 2011 UTC (12 years, 10 months ago) by
bertrand
Branches:
MAIN
CVS tags:
HEAD
Correction d'une réinitialisation sauvage de la pile des variables par niveau
dans la copie de la structure de description du processus. Cela corrige
la fonction SPAWN qui échouait sur un segmentation fault car la pile des
variables par niveau était vide alors même que l'arbre des variables contenait
bien les variables. Passage à la prerelease 2.
1: /*
2: ================================================================================
3: RPL/2 (R) version 4.1.0.prerelease.2
4: Copyright (C) 1989-2011 Dr. BERTRAND Joël
5:
6: This file is part of RPL/2.
7:
8: RPL/2 is free software; you can redistribute it and/or modify it
9: under the terms of the CeCILL V2 License as published by the french
10: CEA, CNRS and INRIA.
11:
12: RPL/2 is distributed in the hope that it will be useful, but WITHOUT
13: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14: FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License
15: for more details.
16:
17: You should have received a copy of the CeCILL License
18: along with RPL/2. If not, write to info@cecill.info.
19: ================================================================================
20: */
21:
22:
23: #include "rpl-conv.h"
24:
25:
26: /*
27: ================================================================================
28: 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 création d'une nouvelle variable
231: ================================================================================
232: Entrée : autorisation_creation_variable_statique vaut 'v' ou 's'.
233: dans le cas 'v', la variable est volatile.
234: dans le cas 's', elle est statique.
235: Entrée : autorisation_creation_variable_partagee vaut 'p' ou 's'.
236: dans le cas 'p', la variable est privée.
237: dans le cas 's', elle est partagée.
238: --------------------------------------------------------------------------------
239: Sortie :
240: --------------------------------------------------------------------------------
241: Effets de bords : néant
242: ================================================================================
243: */
244:
245: static logical1
246: ajout_variable(struct_processus *s_etat_processus, struct_variable *s_variable)
247: {
248: int i;
249:
250: logical1 niveau_acceptable;
251:
252: struct_liste_variables *l_nouvelle_variable;
253: struct_liste_variables *l_variable_candidate;
254:
255: struct_arbre_variables *l_variable_courante;
256: struct_arbre_variables *l_variable_precedente;
257:
258: struct_liste_chainee *l_nouvel_element;
259:
260: unsigned char *ptr;
261:
262: void *pointeur_variable_cree;
263:
264: if ((*s_etat_processus).s_arbre_variables == NULL)
265: {
266: if (((*s_etat_processus).s_arbre_variables =
267: malloc(sizeof(struct_arbre_variables))) == NULL)
268: {
269: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
270: return(d_erreur);
271: }
272:
273: (*(*s_etat_processus).s_arbre_variables).feuille = NULL;
274: (*(*s_etat_processus).s_arbre_variables).noeuds_utilises = 0;
275: (*(*s_etat_processus).s_arbre_variables).indice_tableau_pere = -1;
276: (*(*s_etat_processus).s_arbre_variables).noeud_pere = NULL;
277:
278: if (((*(*s_etat_processus).s_arbre_variables).noeuds =
279: malloc((*s_etat_processus).nombre_caracteres_variables
280: * sizeof(struct_arbre_variables))) == NULL)
281: {
282: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
283: return(d_erreur);
284: }
285:
286: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
287: {
288: (*(*s_etat_processus).s_arbre_variables).noeuds[i] = NULL;
289: }
290: }
291:
292: l_variable_precedente = NULL;
293: l_variable_courante = (*s_etat_processus).s_arbre_variables;
294: ptr = (*s_variable).nom;
295:
296: while((*ptr) != d_code_fin_chaine)
297: {
298: BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0,
299: printf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom,
300: *ptr));
301:
302: if ((*l_variable_courante).noeuds[(*s_etat_processus)
303: .pointeurs_caracteres_variables[*ptr]] == NULL)
304: {
305: // Le noeud n'existe pas encore, on le crée et on le marque
306: // comme utilisé dans la structure parente.
307:
308: if (((*l_variable_courante).noeuds[(*s_etat_processus)
309: .pointeurs_caracteres_variables[*ptr]] =
310: malloc(sizeof(struct_arbre_variables))) == NULL)
311: {
312: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
313: return(d_erreur);
314: }
315:
316: (*l_variable_courante).noeuds_utilises++;
317:
318: // La feuille est par défaut vide et aucun élément du tableau noeuds
319: // (les branches qui peuvent être issues de ce nouveau noeud)
320: // n'est encore utilisée.
321:
322: (*(*l_variable_courante).noeuds[(*s_etat_processus)
323: .pointeurs_caracteres_variables[*ptr]]).feuille = NULL;
324: (*(*l_variable_courante).noeuds[(*s_etat_processus)
325: .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises = 0;
326:
327: // Le champ noeud_pere de la structure créée pointe sur
328: // la structure parente et l'indice tableau_pere correspond à la
329: // position réelle dans le tableau noeuds[] de la structure parente
330: // du noeud courant. Cette valeur sera utilisée lors de la
331: // destruction du noeud pour annuler le pointeur contenu dans
332: // le tableau noeuds[] de la structure parente.
333:
334: (*(*l_variable_courante).noeuds[(*s_etat_processus)
335: .pointeurs_caracteres_variables[*ptr]]).noeud_pere =
336: l_variable_courante;
337: (*(*l_variable_courante).noeuds[(*s_etat_processus)
338: .pointeurs_caracteres_variables[*ptr]])
339: .indice_tableau_pere = (*s_etat_processus)
340: .pointeurs_caracteres_variables[*ptr];
341:
342: // Allocation du tableau noeuds[] et initialisation à zéro de
343: // tous les pointeurs.
344:
345: if (((*(*l_variable_courante).noeuds[(*s_etat_processus)
346: .pointeurs_caracteres_variables[*ptr]]).noeuds =
347: malloc((*s_etat_processus).nombre_caracteres_variables
348: * sizeof(struct_arbre_variables))) == NULL)
349: {
350: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
351: return(d_erreur);
352: }
353:
354: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
355: {
356: (*(*l_variable_courante).noeuds[(*s_etat_processus)
357: .pointeurs_caracteres_variables[*ptr]]).noeuds[i]
358: = NULL;
359: }
360: }
361:
362: l_variable_precedente = l_variable_courante;
363: l_variable_courante = (*l_variable_courante).noeuds
364: [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]];
365: ptr++;
366: }
367:
368: if ((*l_variable_courante).feuille == NULL)
369: {
370: // Aucune variable de même nom préexiste. On alloue le premier
371: // élément de la liste doublement chaînée contenant toutes les
372: // variables de même nom. Cette liste boucle en premier lieu sur
373: // elle-même.
374:
375: if (((*l_variable_courante).feuille = malloc(
376: sizeof(struct_liste_variables))) == NULL)
377: {
378: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
379: return(d_erreur);
380: }
381:
382: (*l_variable_courante).noeuds_utilises++;
383:
384: (*(*l_variable_courante).feuille).suivant =
385: (*l_variable_courante).feuille;
386: (*(*l_variable_courante).feuille).precedent =
387: (*l_variable_courante).feuille;
388: (*(*l_variable_courante).feuille).noeud_pere = l_variable_precedente;
389: (*(*l_variable_courante).feuille).noeud = l_variable_courante;
390:
391: // Allocation de la variable sur l'élément de la liste.
392:
393: if (((*(*l_variable_courante).feuille).variable =
394: malloc(sizeof(struct_variable))) == NULL)
395: {
396: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
397: return(d_erreur);
398: }
399:
400: (*((struct_variable *) (*(*l_variable_courante).feuille).variable)) =
401: (*s_variable);
402: pointeur_variable_cree = (*(*l_variable_courante).feuille).variable;
403: }
404: else
405: {
406: if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables)))
407: == NULL)
408: {
409: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
410: return(d_erreur);
411: }
412:
413: if ((*s_variable).niveau > 1)
414: {
415: // Cas d'une variable locale
416:
417: // Si le niveau de la dernière variable de même nom est
418: // supérieur au niveau de la variable locale que l'on veut
419: // enregistrer dans la liste, cette liste est incohérente.
420:
421: BUG((*(*(*l_variable_courante).feuille).variable).niveau >=
422: (*s_variable).niveau,
423: printf("Variable=\"%s\"\n", (*s_variable).nom));
424:
425: // On ajoute la variable à la liste existante.
426:
427: (*l_nouvelle_variable).suivant = (*l_variable_courante).feuille;
428: (*l_nouvelle_variable).precedent = (*(*l_variable_courante).feuille)
429: .precedent;
430: (*l_nouvelle_variable).noeud_pere = l_variable_precedente;
431: (*l_nouvelle_variable).noeud = l_variable_courante;
432: (*(*(*l_variable_courante).feuille).precedent).suivant =
433: l_nouvelle_variable;
434: (*(*l_variable_courante).feuille).precedent =
435: l_nouvelle_variable;
436: (*l_variable_courante).feuille = l_nouvelle_variable;
437:
438: if (((*(*l_variable_courante).feuille).variable =
439: malloc(sizeof(struct_variable))) == NULL)
440: {
441: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
442: return(d_erreur);
443: }
444:
445: (*((struct_variable *) (*(*l_variable_courante).feuille).variable))
446: = (*s_variable);
447: pointeur_variable_cree = (*(*l_variable_courante).feuille).variable;
448: }
449: else
450: {
451: // Cas d'une variable globale (niveau 0 [définitions] ou 1
452: // [variables globales])
453:
454: l_variable_candidate = (*l_variable_courante).feuille;
455:
456: do
457: {
458: // S'il y a déjà une variable de même niveau, la pile
459: // est incohérente.
460:
461: BUG((*(*l_variable_candidate).variable).niveau ==
462: (*s_variable).niveau,
463: printf("Variable=\"%s\"\n", (*s_variable).nom));
464:
465: l_variable_candidate = (*l_variable_candidate).precedent;
466: } while((l_variable_candidate != (*l_variable_courante).feuille) &&
467: ((*(*l_variable_candidate).variable).niveau <= 1));
468:
469: BUG((*s_variable).niveau == 0,
470: uprintf("Attempt to create a level-0 variable!\n"));
471:
472: if ((*(*(*(*l_variable_courante).feuille).precedent).variable)
473: .niveau > 1)
474: {
475: // La variable précédente est de niveau strictement supérieur
476: // à 1. Il ne peut donc y avoir aucune variable de niveau
477: // inférieur ou égal à 1 puisque la boucle est triée.
478: // On insère donc directement la variable en queue.
479: }
480: else
481: {
482: // Le niveau de la variable précédente dans la boucle est
483: // inférieur ou égal à 1.
484: l_variable_candidate = (*(*l_variable_courante).feuille)
485: .precedent;
486: }
487:
488: (*l_nouvelle_variable).suivant = l_variable_candidate;
489: (*l_nouvelle_variable).precedent = (*l_variable_candidate)
490: .precedent;
491: (*l_nouvelle_variable).noeud_pere = l_variable_precedente;
492: (*l_nouvelle_variable).noeud = l_variable_courante;
493: (*(*l_variable_candidate).precedent).suivant = l_nouvelle_variable;
494: (*l_variable_candidate).precedent = l_nouvelle_variable;
495:
496: // Si la variable suivant la variable que l'on vient d'insérer
497: // dans la boucle est de niveau 0, la variable insérée est par
498: // construction de niveau 1 et il convient de modifier le
499: // pointeur de feuille pointant sur l'élément de plus haut niveau
500: // de la boucle.
501:
502: if ((*(*(*l_nouvelle_variable).precedent).variable).niveau == 0)
503: {
504: (*(*l_nouvelle_variable).noeud).feuille = l_nouvelle_variable;
505: }
506:
507: if (((*l_nouvelle_variable).variable =
508: malloc(sizeof(struct_variable))) == NULL)
509: {
510: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
511: return(d_erreur);
512: }
513:
514: (*(*l_nouvelle_variable).variable) = (*s_variable);
515: pointeur_variable_cree = (*l_nouvelle_variable).variable;
516: }
517: }
518:
519: // Ajout de la variable nouvellement créée à la liste par niveaux.
520: // Le pointeur contenu dans la structure de description du processus indique
521: // toujours le plus haut niveau utilisé.
522:
523: if ((*s_etat_processus).l_liste_variables_par_niveau == NULL)
524: {
525: // Le niveau courant n'existe pas. Il est créé.
526:
527: if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables)))
528: == NULL)
529: {
530: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
531: return(d_erreur);
532: }
533:
534: (*l_nouvelle_variable).suivant = l_nouvelle_variable;
535: (*l_nouvelle_variable).precedent = l_nouvelle_variable;
536: (*l_nouvelle_variable).noeud_pere = NULL;
537: (*l_nouvelle_variable).liste = NULL;
538:
539: (*s_etat_processus).l_liste_variables_par_niveau = l_nouvelle_variable;
540:
541: // Ajout de la variable en tête de la liste
542:
543: if ((l_nouvel_element = malloc(sizeof(struct_liste_chainee))) == NULL)
544: {
545: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
546: return(d_erreur);
547: }
548:
549: (*l_nouvel_element).suivant = (*(*s_etat_processus)
550: .l_liste_variables_par_niveau).liste;
551: (*l_nouvel_element).donnee = pointeur_variable_cree;
552: (*(*s_etat_processus).l_liste_variables_par_niveau).liste =
553: l_nouvel_element;
554: }
555: else if ((*s_variable).niveau > (*((struct_variable *)
556: (*(*(*s_etat_processus).l_liste_variables_par_niveau).liste)
557: .donnee)).niveau)
558: {
559: // Le niveau courant n'existe pas. Il est créé.
560:
561: if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables)))
562: == NULL)
563: {
564: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
565: return(d_erreur);
566: }
567:
568: (*l_nouvelle_variable).suivant = (*s_etat_processus)
569: .l_liste_variables_par_niveau;
570: (*l_nouvelle_variable).precedent = (*(*s_etat_processus)
571: .l_liste_variables_par_niveau).precedent;
572: (*l_nouvelle_variable).noeud_pere = NULL;
573: (*l_nouvelle_variable).liste = NULL;
574: (*(*(*s_etat_processus).l_liste_variables_par_niveau).precedent)
575: .suivant = l_nouvelle_variable;
576: (*(*s_etat_processus).l_liste_variables_par_niveau)
577: .precedent = l_nouvelle_variable;
578:
579: (*s_etat_processus).l_liste_variables_par_niveau = l_nouvelle_variable;
580:
581: // Ajout de la variable en tête de la liste
582:
583: if ((l_nouvel_element = malloc(sizeof(struct_liste_chainee))) == NULL)
584: {
585: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
586: return(d_erreur);
587: }
588:
589: (*l_nouvel_element).suivant = (*(*s_etat_processus)
590: .l_liste_variables_par_niveau).liste;
591: (*l_nouvel_element).donnee = pointeur_variable_cree;
592: (*(*s_etat_processus).l_liste_variables_par_niveau).liste =
593: l_nouvel_element;
594: }
595: else if ((*s_variable).niveau <= 1)
596: {
597: // Création d'une variable de niveau 0 ou 1. Il convient de
598: // chercher dans la liste si un niveau 0 ou 1 préexiste. Pour cela, on
599: // regarde la position courante et les deux précédentes.
600:
601: l_variable_candidate = (*s_etat_processus).l_liste_variables_par_niveau;
602: niveau_acceptable = d_faux;
603:
604: for(i = 0; i <= 2; i++)
605: {
606: if ((*l_variable_candidate).liste == NULL)
607: {
608: continue;
609: }
610:
611: if ((*((struct_variable *) (*(*l_variable_candidate)
612: .liste).donnee)).niveau == (*s_variable).niveau)
613: {
614: niveau_acceptable = d_vrai;
615: break;
616: }
617:
618: l_variable_candidate = (*l_variable_candidate).precedent;
619: }
620:
621: if (niveau_acceptable == d_faux)
622: {
623: if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables)))
624: == NULL)
625: {
626: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
627: return(d_erreur);
628: }
629:
630: l_variable_candidate =
631: (*(*s_etat_processus).l_liste_variables_par_niveau)
632: .precedent;
633:
634: // On ne peut créer qu'une variable de niveau supérieur ou égal à
635: // 1 lors de l'exécution normale d'un programme. Les variables
636: // de niveau 0 sont créées à l'initialisation et relèvent du
637: // cas précédent car il n'existe lors de leur création aucun
638: // niveau non nul.
639:
640: BUG((*s_variable).niveau == 0,
641: uprintf("Attempt to create a level-0 variable!\n"));
642:
643: (*l_nouvelle_variable).suivant = l_variable_candidate;
644: (*l_nouvelle_variable).precedent = (*l_variable_candidate)
645: .precedent;
646: (*l_nouvelle_variable).noeud_pere = NULL;
647: (*l_nouvelle_variable).liste = NULL;
648: (*(*l_variable_candidate).precedent).suivant = l_nouvelle_variable;
649: (*l_variable_candidate).precedent = l_nouvelle_variable;
650:
651: l_variable_candidate = l_nouvelle_variable;
652: }
653:
654: // Ajout de la variable en tête de la liste l_variable_candidate.
655:
656: if ((l_nouvel_element = malloc(sizeof(struct_liste_chainee))) == NULL)
657: {
658: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
659: return(d_erreur);
660: }
661:
662: (*l_nouvel_element).suivant = (*l_variable_candidate).liste;
663: (*l_nouvel_element).donnee = pointeur_variable_cree;
664: (*l_variable_candidate).liste = l_nouvel_element;
665: }
666: else
667: {
668: // Ajout de la variable en tête de la liste
669:
670: if ((l_nouvel_element = malloc(sizeof(struct_liste_chainee))) == NULL)
671: {
672: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
673: return(d_erreur);
674: }
675:
676: (*l_nouvel_element).suivant = (*(*s_etat_processus)
677: .l_liste_variables_par_niveau).liste;
678: (*l_nouvel_element).donnee = pointeur_variable_cree;
679: (*(*s_etat_processus).l_liste_variables_par_niveau).liste =
680: l_nouvel_element;
681: }
682:
683: return(d_absence_erreur);
684: }
685:
686:
687: logical1
688: creation_variable(struct_processus *s_etat_processus,
689: struct_variable *s_variable,
690: unsigned char autorisation_creation_variable_statique,
691: unsigned char autorisation_creation_variable_partagee)
692: {
693: if ((*s_etat_processus).mode_execution_programme == 'Y')
694: {
695: (*s_variable).origine = 'P';
696: }
697: else
698: {
699: (*s_variable).origine = 'E';
700: }
701:
702: if ((*s_variable).niveau == 0)
703: {
704: // Un point d'entrée de définition est verrouillé.
705:
706: if ((*s_variable).origine == 'P')
707: {
708: (*s_variable).variable_statique.adresse = 0;
709: (*s_variable).variable_partagee.adresse = 0;
710: }
711: else
712: {
713: (*s_variable).variable_statique.pointeur = NULL;
714: (*s_variable).variable_partagee.pointeur = NULL;
715: }
716:
717: (*s_variable).variable_verrouillee = d_vrai;
718: }
719: else if ((*s_variable).niveau == 1)
720: {
721: // Une variable globale ne peut être statique.
722:
723: if ((*s_variable).origine == 'P')
724: {
725: (*s_variable).variable_statique.adresse = 0;
726: (*s_variable).variable_partagee.adresse = 0;
727: }
728: else
729: {
730: (*s_variable).variable_statique.pointeur = NULL;
731: (*s_variable).variable_partagee.pointeur = NULL;
732: }
733:
734: (*s_variable).variable_verrouillee = d_faux;
735: }
736: else
737: {
738: // 0 -> variable volatile
739: // adresse de création -> variable statique
740:
741: if (autorisation_creation_variable_statique == 'V')
742: {
743: if (autorisation_creation_variable_partagee == 'S')
744: {
745: // On force la création d'une variable partagée
746:
747: if ((*s_variable).origine == 'P')
748: {
749: (*s_variable).variable_statique.adresse = 0;
750: (*s_variable).variable_partagee.adresse =
751: (*s_etat_processus).position_courante;
752: }
753: else
754: {
755: (*s_variable).variable_statique.pointeur = NULL;
756: (*s_variable).variable_partagee.pointeur =
757: (*s_etat_processus).objet_courant;
758: }
759: }
760: else
761: {
762: // On force la création d'une variable volatile
763:
764: if ((*s_variable).origine == 'P')
765: {
766: (*s_variable).variable_statique.adresse = 0;
767: (*s_variable).variable_partagee.adresse = 0;
768: }
769: else
770: {
771: (*s_variable).variable_statique.pointeur = NULL;
772: (*s_variable).variable_partagee.pointeur = NULL;
773: }
774: }
775: }
776: else
777: {
778: // On force la création d'une variable statique.
779:
780: if ((*s_variable).origine == 'P')
781: {
782: (*s_variable).variable_statique.adresse =
783: (*s_etat_processus).position_courante;
784: (*s_variable).variable_partagee.adresse = 0;
785: }
786: else
787: {
788: (*s_variable).variable_statique.pointeur =
789: (*s_etat_processus).objet_courant;
790: (*s_variable).variable_partagee.pointeur = 0;
791: }
792: }
793:
794: (*s_variable).variable_verrouillee = d_faux;
795: }
796:
797: /*
798: * Recherche de la feuille correspondante dans l'arbre des variables.
799: * Si cette feuille n'existe pas, elle est créée.
800: */
801:
802: if (ajout_variable(s_etat_processus, s_variable) == d_erreur)
803: {
804: return(d_erreur);
805: }
806:
807: return(d_absence_erreur);
808: }
809:
810:
811: /*
812: ================================================================================
813: Procédure de recherche d'une variable par son nom dans la base
814: ================================================================================
815: Entrée :
816: --------------------------------------------------------------------------------
817: Sortie :
818: --------------------------------------------------------------------------------
819: Effets de bord : néant
820: ================================================================================
821: */
822:
823: logical1
824: recherche_variable(struct_processus *s_etat_processus,
825: unsigned char *nom_variable)
826: {
827: int pointeur;
828:
829: struct_arbre_variables *l_variable_courante;
830: struct_liste_pile_systeme *l_element_courant;
831:
832: unsigned char *ptr;
833:
834: unsigned long niveau_appel;
835:
836: if ((*s_etat_processus).s_arbre_variables == NULL)
837: {
838: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
839: return(d_faux);
840: }
841:
842: l_variable_courante = (*s_etat_processus).s_arbre_variables;
843: ptr = nom_variable;
844:
845: while((*ptr) != d_code_fin_chaine)
846: {
847: pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr];
848:
849: if (pointeur < 0)
850: {
851: // Caractère hors de l'alphabet des variables
852:
853: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
854: return(d_faux);
855: }
856:
857: if ((*l_variable_courante).noeuds[pointeur] == NULL)
858: {
859: // Le chemin de la variable candidate n'existe pas.
860: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
861: return(d_faux);
862: }
863:
864: l_variable_courante = (*l_variable_courante).noeuds[pointeur];
865: ptr++;
866: }
867:
868: if ((*l_variable_courante).feuille != NULL)
869: {
870: // Il existe une pile de variables de même nom. Le sommet de la
871: // pile est la variable de niveau le plus haut.
872:
873: l_element_courant = (*s_etat_processus).l_base_pile_systeme;
874:
875: if (l_element_courant == NULL)
876: {
877: // Problème : la pile système est vide !
878: (*s_etat_processus).erreur_systeme = d_es_pile_vide;
879: return(d_faux);
880: }
881:
882: while((*l_element_courant).retour_definition != 'Y')
883: {
884: l_element_courant = (*l_element_courant).suivant;
885:
886: if (l_element_courant == NULL)
887: {
888: (*s_etat_processus).erreur_systeme = d_es_pile_vide;
889: return(d_faux);
890: }
891: }
892:
893: niveau_appel = (*l_element_courant).niveau_courant;
894:
895: if (niveau_appel < (*(*(*l_variable_courante).feuille).variable).niveau)
896: {
897: // Une variable locale est accessible puisque créée dans la
898: // fonction courante.
899:
900: (*s_etat_processus).pointeur_variable_courante =
901: (*(*l_variable_courante).feuille).variable;
902: (*s_etat_processus).pointeur_feuille_courante =
903: (*l_variable_courante).feuille;
904: return(d_vrai);
905: }
906: else
907: {
908: // Aucune variable locale n'est accessible depuis la fonction.
909: // Dans ce cas, on prend la variable de niveau le plus bas
910: // si ce niveau est inférieur ou égal à 1 (variable globale
911: // ou fonction définie par l'utilisateur). Si le niveau de la
912: // plus ancienne variable est strictement supérieur à 1, il
913: // s'agit d'une variable locale inaccessible.
914:
915: if ((*(*(*(*l_variable_courante).feuille).precedent).variable)
916: .niveau <= 1)
917: {
918: (*s_etat_processus).pointeur_variable_courante =
919: (*(*(*l_variable_courante).feuille).precedent).variable;
920: (*s_etat_processus).pointeur_feuille_courante =
921: (*(*l_variable_courante).feuille).precedent;
922:
923: // S'il existe une variable de niveau 0 et une seconde de
924: // niveau 1, la variable de niveau 0 (fonction) est masquée
925: // par celle de niveau 1.
926:
927: if (((*(*(*(*l_variable_courante).feuille).precedent)
928: .variable).niveau == 0) && ((*(*(*(*
929: (*l_variable_courante).feuille).precedent).precedent)
930: .variable).niveau == 1))
931: {
932: (*s_etat_processus).pointeur_variable_courante =
933: (*(*(*(*l_variable_courante).feuille).precedent)
934: .precedent).variable;
935: (*s_etat_processus).pointeur_feuille_courante =
936: (*(*(*l_variable_courante).feuille).precedent)
937: .precedent;
938: }
939:
940: return(d_vrai);
941: }
942: }
943: }
944:
945: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
946: return(d_faux);
947: }
948:
949:
950: logical1
951: recherche_variable_globale(struct_processus *s_etat_processus,
952: unsigned char *nom)
953: {
954: logical1 presence_variable;
955:
956: presence_variable = recherche_variable(s_etat_processus, nom);
957:
958: if (presence_variable == d_vrai)
959: {
960: switch((*(*s_etat_processus).pointeur_variable_courante).niveau)
961: {
962: case 0:
963: {
964: // La variable est une définition.
965: presence_variable = d_faux;
966: break;
967: }
968:
969: case 1:
970: {
971: break;
972: }
973:
974: default:
975: {
976: if ((*(*(*(*s_etat_processus).pointeur_feuille_courante)
977: .precedent).variable).niveau == 1)
978: {
979: (*s_etat_processus).pointeur_feuille_courante =
980: (*(*s_etat_processus).pointeur_feuille_courante)
981: .precedent;
982: (*s_etat_processus).pointeur_variable_courante =
983: (*(*s_etat_processus).pointeur_feuille_courante)
984: .variable;
985: }
986: else if ((*(*(*(*(*s_etat_processus).pointeur_feuille_courante)
987: .precedent).precedent).variable).niveau == 1)
988: {
989: (*s_etat_processus).pointeur_feuille_courante =
990: (*(*(*s_etat_processus).pointeur_feuille_courante)
991: .precedent).precedent;
992: (*s_etat_processus).pointeur_variable_courante =
993: (*(*s_etat_processus).pointeur_feuille_courante)
994: .variable;
995: }
996: else
997: {
998: presence_variable = d_faux;
999: }
1000:
1001: break;
1002: }
1003: }
1004: }
1005:
1006: if (presence_variable == d_vrai)
1007: {
1008: if ((*(*s_etat_processus).pointeur_variable_courante).objet == NULL)
1009: {
1010: // La variable n'est pas globale, elle est partagée.
1011: presence_variable = d_faux;
1012: (*s_etat_processus).erreur_execution = d_ex_variable_partagee;
1013: }
1014: }
1015:
1016: return(presence_variable);
1017: }
1018:
1019:
1020: /*
1021: ================================================================================
1022: Procédure de retrait d'une variable de la base
1023: ================================================================================
1024: Entrée : type 'G' ou 'L' selon que l'on retire une variable locale (incluant
1025: les globales) ou strictement globale.
1026: --------------------------------------------------------------------------------
1027: Sortie :
1028: --------------------------------------------------------------------------------
1029: Effets de bord : néant
1030: ================================================================================
1031: */
1032:
1033: logical1
1034: retrait_variable(struct_processus *s_etat_processus,
1035: unsigned char *nom_variable, unsigned char type)
1036: {
1037: logical1 erreur;
1038: logical1 variable_supprimee;
1039:
1040: struct_arbre_variables *s_arbre_a_supprimer;
1041: struct_arbre_variables *s_arbre_courant;
1042:
1043: struct_liste_chainee *l_element_courant;
1044: struct_liste_chainee *l_element_precedent;
1045:
1046: struct_liste_variables *variable_a_supprimer;
1047: struct_liste_variables *variables_par_niveau;
1048:
1049: unsigned long niveau;
1050:
1051: (*s_etat_processus).niveau_supprime = d_faux;
1052:
1053: if (recherche_variable(s_etat_processus, nom_variable) == d_vrai)
1054: {
1055: // Une variable correspondant au nom recherché est accessible.
1056:
1057: if (type == 'G')
1058: {
1059: if ((*(*s_etat_processus).pointeur_variable_courante).niveau > 1)
1060: {
1061: // La variable obtenue est une variable locale. il faut
1062: // s'assurer qu'il existe une variable de niveau 1 de même
1063: // nom sur la feuille.
1064:
1065: if ((*(*(*(*s_etat_processus).pointeur_feuille_courante)
1066: .precedent).variable).niveau <= 1)
1067: {
1068: (*s_etat_processus).pointeur_feuille_courante =
1069: (*(*s_etat_processus).pointeur_feuille_courante)
1070: .precedent;
1071: (*s_etat_processus).pointeur_variable_courante =
1072: (*(*s_etat_processus).pointeur_feuille_courante)
1073: .variable;
1074:
1075: // Si la variable retournée est de niveau 0, on regarde
1076: // un peu plus loin si une variable de niveau 1 existe.
1077:
1078: if (((*(*(*s_etat_processus).pointeur_feuille_courante)
1079: .variable).niveau == 0) &&
1080: ((*(*(*(*s_etat_processus)
1081: .pointeur_feuille_courante).precedent).variable)
1082: .niveau == 1))
1083: {
1084: (*s_etat_processus).pointeur_feuille_courante =
1085: (*(*s_etat_processus).pointeur_feuille_courante)
1086: .precedent;
1087: (*s_etat_processus).pointeur_variable_courante =
1088: (*(*s_etat_processus).pointeur_feuille_courante)
1089: .variable;
1090: }
1091: }
1092: else
1093: {
1094: // Aucune variable globale (niveau 1) n'existe.
1095:
1096: erreur = d_erreur;
1097: (*s_etat_processus).erreur_execution =
1098: d_ex_variable_non_definie;
1099: return(erreur);
1100: }
1101: }
1102:
1103: if ((*(*s_etat_processus).pointeur_variable_courante)
1104: .variable_verrouillee == d_vrai)
1105: {
1106: erreur = d_erreur;
1107: (*s_etat_processus).erreur_execution =
1108: d_ex_variable_verrouillee;
1109: return(erreur);
1110: }
1111: }
1112:
1113: // Suppression de la variable de la liste.
1114: // Deux cas peuvent survenir :
1115: // 1/ les pointeurs sur la variable et la variable suivante
1116: // sont identiques et on supprime la variable ainsi que la feuille
1117: // associée ;
1118: // 2/ ces deux pointeurs sont différents et se contente de retirer
1119: // la structure décrivant la variable.
1120:
1121: if ((*s_etat_processus).pointeur_feuille_courante ==
1122: (*(*s_etat_processus).pointeur_feuille_courante).suivant)
1123: {
1124: // Cas 1 :
1125: // On retire la variable du noeud en décrémentant le nombre
1126: // de feuilles de ce noeud. Si le nombre de feuilles du noeud
1127: // est nul, on retire les noeuds récursivement jusqu'à obtenir
1128: // un nombre non nul de feuilles utilisées (ou la racine des
1129: // variables).
1130:
1131: variable_a_supprimer = (*s_etat_processus)
1132: .pointeur_feuille_courante;
1133: s_arbre_courant = (*variable_a_supprimer).noeud;
1134: BUG((*s_arbre_courant).noeuds_utilises == 0,
1135: uprintf("Freed node !\n"));
1136: (*s_arbre_courant).noeuds_utilises--;
1137:
1138: (*((*(*variable_a_supprimer).noeud_pere).noeuds
1139: [(*(*variable_a_supprimer).noeud).indice_tableau_pere]))
1140: .feuille = NULL;
1141:
1142: while((*s_arbre_courant).noeuds_utilises == 0)
1143: {
1144: s_arbre_a_supprimer = s_arbre_courant;
1145: s_arbre_courant = (*s_arbre_courant).noeud_pere;
1146:
1147: if (s_arbre_courant == NULL)
1148: {
1149: free((*s_arbre_a_supprimer).noeuds);
1150: free(s_arbre_a_supprimer);
1151:
1152: (*s_etat_processus).s_arbre_variables = NULL;
1153: break;
1154: }
1155:
1156: // s_arbre_a_supprimer contient la structure de feuille qui
1157: // vient d'être libérée. Il s'agit maintenant
1158: // d'annuler le pointeur dans le tableau noeuds de la structure
1159: // pointée par noeud_pere, soit s_arbre_courant.
1160:
1161: BUG((*s_arbre_a_supprimer).indice_tableau_pere < 0,
1162: uprintf("Invalid pointer !\n"));
1163: (*s_arbre_courant).noeuds[(*s_arbre_a_supprimer)
1164: .indice_tableau_pere] = NULL;
1165:
1166: free((*s_arbre_a_supprimer).noeuds);
1167: free(s_arbre_a_supprimer);
1168:
1169: BUG((*s_arbre_courant).noeuds_utilises == 0,
1170: uprintf("Freed node !\n"));
1171: (*s_arbre_courant).noeuds_utilises--;
1172: }
1173: }
1174: else
1175: {
1176: // Cas 2 :
1177: // On retire la variable de la liste.
1178:
1179: variable_a_supprimer = (*s_etat_processus)
1180: .pointeur_feuille_courante;
1181:
1182: (*(*(*s_etat_processus).pointeur_feuille_courante).precedent)
1183: .suivant = (*(*s_etat_processus).pointeur_feuille_courante)
1184: .suivant;
1185: (*(*(*s_etat_processus).pointeur_feuille_courante).suivant)
1186: .precedent = (*(*s_etat_processus)
1187: .pointeur_feuille_courante).precedent;
1188:
1189: // Mise à jour du pointeur dans l'arbre des variables. Cette
1190: // mise à jour n'est nécessaire que dans le cas où la variable
1191: // supprimée est en tête de la liste.
1192:
1193: if (variable_a_supprimer == (*((*(*variable_a_supprimer).noeud_pere)
1194: .noeuds[(*(*variable_a_supprimer).noeud)
1195: .indice_tableau_pere])).feuille)
1196: {
1197: (*((*(*variable_a_supprimer).noeud_pere).noeuds
1198: [(*(*variable_a_supprimer).noeud).indice_tableau_pere]))
1199: .feuille = (*(*((*(*variable_a_supprimer).noeud_pere)
1200: .noeuds[(*(*variable_a_supprimer).noeud)
1201: .indice_tableau_pere])).feuille).suivant;
1202: }
1203:
1204: (*s_etat_processus).pointeur_feuille_courante =
1205: (*(*s_etat_processus).pointeur_feuille_courante).suivant;
1206: (*s_etat_processus).pointeur_variable_courante =
1207: (*(*s_etat_processus).pointeur_feuille_courante).variable;
1208: }
1209:
1210: // Dans tous les cas, on retire la variable de la liste des variables
1211: // par niveau.
1212:
1213: niveau = (*(*variable_a_supprimer).variable).niveau;
1214: variables_par_niveau = (*s_etat_processus).l_liste_variables_par_niveau;
1215: variable_supprimee = d_faux;
1216:
1217: if (variables_par_niveau != NULL)
1218: {
1219: do
1220: {
1221: l_element_courant = (*variables_par_niveau).liste;
1222:
1223: if (l_element_courant != NULL)
1224: {
1225: if ((*((struct_variable *) (*l_element_courant).donnee))
1226: .niveau == niveau)
1227: {
1228: // On parcourt le bon niveau.
1229:
1230: l_element_precedent = NULL;
1231:
1232: while(l_element_courant != NULL)
1233: {
1234: // Tant que l_element_courant est non nul, il reste
1235: // des variables à explorer dans le niveau courant.
1236:
1237: if ((*l_element_courant).donnee ==
1238: (void *) (*variable_a_supprimer).variable)
1239: {
1240: // On a trouvé la variable à supprimer.
1241:
1242: if (l_element_precedent == NULL)
1243: {
1244: (*variables_par_niveau).liste =
1245: (*l_element_courant).suivant;
1246: }
1247: else
1248: {
1249: (*l_element_precedent).suivant =
1250: (*l_element_courant).suivant;
1251: }
1252:
1253: free(l_element_courant);
1254:
1255: if ((*variables_par_niveau).liste == NULL)
1256: {
1257: (*s_etat_processus).niveau_supprime =
1258: d_vrai;
1259:
1260: if ((*s_etat_processus)
1261: .l_liste_variables_par_niveau
1262: == variables_par_niveau)
1263: {
1264: // On retire l'élément de la liste
1265: // pointé par
1266: // l_liste_variable_par_niveau
1267:
1268: (*s_etat_processus)
1269: .l_liste_variables_par_niveau =
1270: (*variables_par_niveau).suivant;
1271: }
1272:
1273: (*(*variables_par_niveau).precedent)
1274: .suivant =
1275: (*variables_par_niveau).suivant;
1276: (*(*variables_par_niveau).suivant)
1277: .precedent =
1278: (*variables_par_niveau)
1279: .precedent;
1280: free(variables_par_niveau);
1281: }
1282:
1283: variable_supprimee = d_vrai;
1284: break;
1285: }
1286:
1287: l_element_precedent = l_element_courant;
1288: l_element_courant = (*l_element_courant).suivant;
1289: }
1290: }
1291: }
1292:
1293: if (variable_supprimee == d_vrai)
1294: {
1295: break;
1296: }
1297:
1298: variables_par_niveau = (*variables_par_niveau).suivant;
1299:
1300: } while(variables_par_niveau != (*s_etat_processus)
1301: .l_liste_variables_par_niveau);
1302: }
1303:
1304: // Puis on libère le contenu de la variable.
1305:
1306: free((*(*variable_a_supprimer).variable).nom);
1307: liberation(s_etat_processus, (*(*variable_a_supprimer).variable).objet);
1308: free((*variable_a_supprimer).variable);
1309: free(variable_a_supprimer);
1310:
1311: erreur = d_absence_erreur;
1312: }
1313: else
1314: {
1315: // Aucune variable n'est accessible depuis le point courant du
1316: // programme.
1317:
1318: erreur = d_erreur;
1319: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
1320: }
1321:
1322: return(erreur);
1323: }
1324:
1325:
1326: /*
1327: ================================================================================
1328: Procédure de retrait des variables de niveau strictement supérieur au
1329: niveau courant
1330: ================================================================================
1331: Entrée :
1332: --------------------------------------------------------------------------------
1333: Sortie :
1334: --------------------------------------------------------------------------------
1335: Effets de bord : néant
1336: ================================================================================
1337: */
1338:
1339: logical1
1340: retrait_variable_par_niveau(struct_processus *s_etat_processus)
1341: {
1342: struct_liste_variables *l_element_a_supprimer;
1343:
1344: // Utilisation du champ (*s_etat_processus).liste_variables_par_niveau.
1345: // La tête de la pile contient toujours les variables de plus haut niveau
1346: // créées.
1347:
1348: while((*s_etat_processus).l_liste_variables_par_niveau != NULL)
1349: {
1350: if ((*(*s_etat_processus).l_liste_variables_par_niveau).liste == NULL)
1351: {
1352: // Si le niveau ne contient aucune variable, on le détruit.
1353: // Le pointeur sur la chaîne est déjà nul et il ne reste rien à
1354: // faire.
1355: }
1356: else
1357: {
1358: // Le niveau contient des variables.
1359:
1360: if ((*((struct_variable *) (*(*(*s_etat_processus)
1361: .l_liste_variables_par_niveau).liste).donnee)).niveau
1362: <= (*s_etat_processus).niveau_courant)
1363: {
1364: // On a retiré de l'arbre des variables toutes les
1365: // variables de niveau strictement supérieur au niveau
1366: // courant.
1367:
1368: break;
1369: }
1370:
1371: while((*(*s_etat_processus).l_liste_variables_par_niveau).liste
1372: != NULL)
1373: {
1374: // Nécessaire car le pointeur sur la tête de la pile
1375: // peut être modifié par retrait_variable().
1376: // Sauvegarde des variables statiques.
1377:
1378: if ((*((struct_variable *) (*(*(*s_etat_processus)
1379: .l_liste_variables_par_niveau).liste).donnee)).origine
1380: == 'P')
1381: {
1382: if ((*((struct_variable *) (*(*(*s_etat_processus)
1383: .l_liste_variables_par_niveau).liste).donnee))
1384: .variable_statique.adresse != 0)
1385: {
1386: if (recherche_variable_statique(s_etat_processus,
1387: (*((struct_variable *) (*(*(*s_etat_processus)
1388: .l_liste_variables_par_niveau).liste).donnee))
1389: .nom, (*((struct_variable *)
1390: (*(*(*s_etat_processus)
1391: .l_liste_variables_par_niveau).liste).donnee))
1392: .variable_statique, ((*s_etat_processus)
1393: .mode_execution_programme
1394: == 'Y') ? 'P' : 'E') == d_vrai)
1395: {
1396: (*s_etat_processus).s_liste_variables_statiques
1397: [(*s_etat_processus)
1398: .position_variable_statique_courante]
1399: .objet = (*((struct_variable *)
1400: (*(*(*s_etat_processus)
1401: .l_liste_variables_par_niveau).liste)
1402: .donnee)).objet;
1403: }
1404: else
1405: {
1406: (*s_etat_processus).erreur_systeme =
1407: d_es_variable_introuvable;
1408: }
1409:
1410: (*((struct_variable *) (*(*(*s_etat_processus)
1411: .l_liste_variables_par_niveau).liste).donnee))
1412: .objet = NULL;
1413: }
1414: }
1415: else
1416: {
1417: if ((*((struct_variable *) (*(*(*s_etat_processus)
1418: .l_liste_variables_par_niveau).liste).donnee))
1419: .variable_statique.pointeur != NULL)
1420: {
1421: /*
1422: * Gestion des variables statiques
1423: */
1424:
1425: if (recherche_variable_statique(s_etat_processus,
1426: (*((struct_variable *) (*(*(*s_etat_processus)
1427: .l_liste_variables_par_niveau).liste).donnee))
1428: .nom, (*((struct_variable *)
1429: (*(*(*s_etat_processus)
1430: .l_liste_variables_par_niveau).liste).donnee))
1431: .variable_statique, ((*s_etat_processus)
1432: .mode_execution_programme
1433: == 'Y') ? 'P' : 'E') == d_vrai)
1434: {
1435: (*s_etat_processus).s_liste_variables_statiques
1436: [(*s_etat_processus)
1437: .position_variable_statique_courante]
1438: .objet = (*((struct_variable *)
1439: (*(*(*s_etat_processus)
1440: .l_liste_variables_par_niveau).liste)
1441: .donnee)).objet;
1442: }
1443: else
1444: {
1445: (*s_etat_processus).erreur_systeme =
1446: d_es_variable_introuvable;
1447: return(d_erreur);
1448: }
1449:
1450: (*((struct_variable *) (*(*(*s_etat_processus)
1451: .l_liste_variables_par_niveau).liste).donnee))
1452: .objet = NULL;
1453: }
1454: }
1455:
1456: if (retrait_variable(s_etat_processus,
1457: (*((struct_variable *) (*(*(*s_etat_processus)
1458: .l_liste_variables_par_niveau).liste).donnee)).nom,
1459: 'L') == d_erreur)
1460: {
1461: return(d_erreur);
1462: }
1463:
1464: if ((*((struct_variable *) (*(*(*s_etat_processus)
1465: .l_liste_variables_par_niveau).liste).donnee)).niveau
1466: <= (*s_etat_processus).niveau_courant)
1467: {
1468: // On a retiré de l'arbre des variables toutes les
1469: // variables de niveau strictement supérieur au niveau
1470: // courant.
1471:
1472: return(d_absence_erreur);
1473: }
1474: }
1475: }
1476:
1477: // On retire l'élément de la liste doublement chaînée et circulaire.
1478:
1479: (*(*(*s_etat_processus).l_liste_variables_par_niveau).precedent).suivant
1480: = (*(*s_etat_processus).l_liste_variables_par_niveau).suivant;
1481: (*(*(*s_etat_processus).l_liste_variables_par_niveau).suivant).precedent
1482: = (*(*s_etat_processus).l_liste_variables_par_niveau).precedent;
1483:
1484: l_element_a_supprimer = (*s_etat_processus)
1485: .l_liste_variables_par_niveau;
1486: (*s_etat_processus).l_liste_variables_par_niveau =
1487: (*l_element_a_supprimer).suivant;
1488: free(l_element_a_supprimer);
1489: }
1490:
1491: return(d_absence_erreur);
1492: }
1493:
1494:
1495: /*
1496: ================================================================================
1497: Procédure de retrait des toutes les variables locales et globales
1498: ================================================================================
1499: Entrée : drapeau indiquant s'il faut retirer les définitions (variables
1500: de niveau 0)
1501: --------------------------------------------------------------------------------
1502: Sortie :
1503: --------------------------------------------------------------------------------
1504: Effets de bord : néant
1505: ================================================================================
1506: */
1507:
1508: void
1509: liberation_arbre_variables(struct_processus *s_etat_processus,
1510: struct_arbre_variables *arbre, logical1 retrait_definitions)
1511: {
1512: int i;
1513:
1514: struct_liste_chainee *l_element_courant_liste;
1515: struct_liste_chainee *l_element_suivant_liste;
1516:
1517: struct_liste_variables *l_element_courant;
1518: struct_liste_variables *l_element_suivant;
1519:
1520: // Libération de l'arbre des variables. Le contenu des variables n'est
1521: // pas détruit par cette opération, il sera détruit lors de la libération
1522: // de la liste des variables par niveau.
1523:
1524: if (arbre == NULL)
1525: {
1526: return;
1527: }
1528:
1529: l_element_courant = (*arbre).feuille;
1530:
1531: if (l_element_courant != NULL)
1532: {
1533: do
1534: {
1535: l_element_suivant = (*l_element_courant).suivant;
1536: free(l_element_courant);
1537: l_element_courant = l_element_suivant;
1538: } while(l_element_courant != (*arbre).feuille);
1539:
1540: (*arbre).feuille = NULL;
1541: }
1542:
1543: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
1544: {
1545: if ((*arbre).noeuds[i] != NULL)
1546: {
1547: liberation_arbre_variables(s_etat_processus, (*arbre).noeuds[i],
1548: retrait_definitions);
1549: (*arbre).noeuds[i] = NULL;
1550: }
1551: }
1552:
1553: // Suppression de la liste des variables par niveau.
1554:
1555: if (arbre == (*s_etat_processus).s_arbre_variables)
1556: {
1557: l_element_courant = (*s_etat_processus).l_liste_variables_par_niveau;
1558:
1559: if (l_element_courant != NULL)
1560: {
1561: do
1562: {
1563: l_element_courant_liste = (*l_element_courant).liste;
1564:
1565: while(l_element_courant_liste != NULL)
1566: {
1567: if ((retrait_definitions == d_vrai) ||
1568: ((*((struct_variable *) (*l_element_courant_liste)
1569: .donnee)).niveau >= 1))
1570: {
1571: liberation(s_etat_processus, (*((struct_variable *)
1572: (*l_element_courant_liste).donnee)).objet);
1573: free((*((struct_variable *) (*l_element_courant_liste)
1574: .donnee)).nom);
1575: }
1576:
1577: l_element_suivant_liste =
1578: (*l_element_courant_liste).suivant;
1579: free((*l_element_courant_liste).donnee);
1580: free(l_element_courant_liste);
1581: l_element_courant_liste = l_element_suivant_liste;
1582: }
1583:
1584: l_element_suivant = (*l_element_courant).suivant;
1585: free(l_element_courant);
1586: l_element_courant = l_element_suivant;
1587: } while(l_element_courant != (*s_etat_processus)
1588: .l_liste_variables_par_niveau);
1589: }
1590: }
1591:
1592: free((*arbre).noeuds);
1593: free(arbre);
1594: arbre = NULL;
1595:
1596: return;
1597: }
1598:
1599:
1600: /*
1601: ================================================================================
1602: Procédure renvoyant les variables dans un tableau
1603: ================================================================================
1604: Entrée :
1605: --------------------------------------------------------------------------------
1606: Sortie :
1607: --------------------------------------------------------------------------------
1608: Effets de bord : néant
1609: ================================================================================
1610: */
1611:
1612: int
1613: nombre_variables(struct_processus *s_etat_processus,
1614: struct_arbre_variables *l_element_courant)
1615: {
1616: int i;
1617: int n;
1618:
1619: struct_liste_variables *l_variable;
1620:
1621: n = 0;
1622:
1623: if ((*l_element_courant).feuille != NULL)
1624: {
1625: l_variable = (*l_element_courant).feuille;
1626:
1627: do
1628: {
1629: n++;
1630: l_variable = (*l_variable).suivant;
1631: } while(l_variable != (*l_element_courant).feuille);
1632: }
1633:
1634: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
1635: {
1636: if ((*l_element_courant).noeuds[i] != NULL)
1637: {
1638: n += nombre_variables(s_etat_processus,
1639: (*l_element_courant).noeuds[i]);
1640: }
1641: }
1642:
1643: return(n);
1644: }
1645:
1646: int
1647: liste_variables(struct_processus *s_etat_processus,
1648: struct_tableau_variables *tableau, int position,
1649: struct_arbre_variables *l_element_courant)
1650: {
1651: int i;
1652:
1653: struct_liste_variables *l_variable;
1654:
1655: if ((*l_element_courant).feuille != NULL)
1656: {
1657: l_variable = (*l_element_courant).feuille;
1658:
1659: do
1660: {
1661: tableau[position].origine = (*(*l_variable).variable).origine;
1662: tableau[position].nom = (*(*l_variable).variable).nom;
1663: tableau[position].niveau = (*(*l_variable).variable).niveau;
1664: tableau[position].objet = (*(*l_variable).variable).objet;
1665: tableau[position].variable_verrouillee =
1666: (*(*l_variable).variable).variable_verrouillee;
1667: tableau[position].variable_statique =
1668: (*(*l_variable).variable).variable_statique;
1669: tableau[position].variable_partagee =
1670: (*(*l_variable).variable).variable_partagee;
1671:
1672: position++;
1673: l_variable = (*l_variable).suivant;
1674: } while(l_variable != (*l_element_courant).feuille);
1675: }
1676:
1677: for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
1678: {
1679: if ((*l_element_courant).noeuds[i] != NULL)
1680: {
1681: position = liste_variables(s_etat_processus,
1682: tableau, position, (*l_element_courant).noeuds[i]);
1683: }
1684: }
1685:
1686: return(position);
1687: }
1688:
1689: /*
1690: ================================================================================
1691: Procédure de copie de l'arbre des variables
1692: ================================================================================
1693: Entrée :
1694: --------------------------------------------------------------------------------
1695: Sortie :
1696: --------------------------------------------------------------------------------
1697: Effets de bord : néant
1698: ================================================================================
1699: */
1700:
1701: void
1702: copie_arbre_variables(struct_processus *s_etat_processus, struct_processus
1703: *s_nouvel_etat_processus)
1704: {
1705: // Les définitions sont partagées entre tous les threads et ne sont pas
1706: // copiées.
1707: //
1708: // NB : on ne copie que les variables de niveaux 0 et 1, les autres
1709: // variables locales étant masquées par le processus de création de thread
1710: // ou de processus, elles seront inaccessibles de tous les points
1711: // du fil d'exécution fils.
1712:
1713: // Pour copier ces variables, on récupère les variables depuis la liste par
1714: // niveaux (niveaux 0 et 1) et on ajoute les variables dans la nouvelle
1715: // structure. Les variables de niveau 0 étant non modifiables, elles
1716: // ne sont pas dupliquées.
1717:
1718: int i;
1719:
1720: struct_liste_chainee *l_element_courant;
1721:
1722: struct_liste_variables *l_niveau_courant;
1723:
1724: struct_variable s_variable;
1725:
1726: (*s_nouvel_etat_processus).s_arbre_variables = NULL;
1727: (*s_nouvel_etat_processus).l_liste_variables_par_niveau = NULL;
1728:
1729: l_niveau_courant = (*s_etat_processus).l_liste_variables_par_niveau;
1730:
1731: // Si la variable en tête n'est pas une variable de niveau 0, le niveau
1732: // 0, s'il existe est le nivau précédent la valeur courante dans la
1733: // boucle.
1734:
1735: if ((*((struct_variable *) (*(*l_niveau_courant).liste).donnee)).niveau
1736: != 0)
1737: {
1738: l_niveau_courant = (*l_niveau_courant).precedent;
1739: }
1740:
1741: // Les variables de niveaux 0 et 1 sont accessibles en au plus trois
1742: // itérations (par construction).
1743:
1744: for(i = 0; i <= 2; i++)
1745: {
1746: if ((*((struct_variable *) (*(*l_niveau_courant).liste)
1747: .donnee)).niveau == 0)
1748: {
1749: l_element_courant = (*l_niveau_courant).liste;
1750:
1751: while(l_element_courant != NULL)
1752: {
1753: if (ajout_variable(s_nouvel_etat_processus,
1754: (struct_variable *) (*l_element_courant).donnee)
1755: == d_erreur)
1756: {
1757: return;
1758: }
1759:
1760: l_element_courant = (*l_element_courant).suivant;
1761: }
1762: }
1763: else if ((*((struct_variable *) (*(*l_niveau_courant).liste)
1764: .donnee)).niveau == 1)
1765: {
1766: l_element_courant = (*l_niveau_courant).liste;
1767:
1768: while(l_element_courant != NULL)
1769: {
1770: s_variable = (*((struct_variable *)
1771: (*l_element_courant).donnee));
1772:
1773: if ((s_variable.nom = strdup((*((struct_variable *)
1774: (*l_element_courant).donnee)).nom)) == NULL)
1775: {
1776: (*s_nouvel_etat_processus).erreur_systeme =
1777: d_es_allocation_memoire;
1778: return;
1779: }
1780:
1781: if ((s_variable.objet = copie_objet(s_nouvel_etat_processus,
1782: (*((struct_variable *) (*l_element_courant).donnee))
1783: .objet, 'P')) == NULL)
1784: {
1785: (*s_nouvel_etat_processus).erreur_systeme =
1786: d_es_allocation_memoire;
1787: return;
1788: }
1789:
1790: if (ajout_variable(s_nouvel_etat_processus, &s_variable)
1791: == d_erreur)
1792: {
1793: return;
1794: }
1795:
1796: l_element_courant = (*l_element_courant).suivant;
1797: }
1798:
1799: // Les variables de niveau 0 ayant déjà été copiées, on
1800: // peut sortir de la boucle car toutes les variables sont
1801: // maintenant disponibles dans le fil d'exécution fils.
1802:
1803: break;
1804: }
1805:
1806: l_niveau_courant = (*l_niveau_courant).precedent;
1807: }
1808:
1809: return;
1810: }
1811:
1812:
1813: /*
1814: ================================================================================
1815: Procédure d'initialisation de la table de correspondance des variables
1816: ================================================================================
1817: Entrée :
1818: --------------------------------------------------------------------------------
1819: Sortie :
1820: --------------------------------------------------------------------------------
1821: Effets de bord : néant
1822: ================================================================================
1823: */
1824:
1825: /*
1826: * Caractères autorisés dans les instructions
1827: *
1828: * 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
1829: * 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
1830: * _
1831: * 1 2 3 4 5 6 7 8 9 0
1832: */
1833:
1834: void
1835: initialisation_variables(struct_processus *s_etat_processus)
1836: {
1837: int decalage;
1838: int i;
1839: int longueur_tableau;
1840:
1841: unsigned char caractere;
1842:
1843: // Récupération de la longueur d'un unsigned char
1844:
1845: longueur_tableau = 1;
1846: decalage = 0;
1847: caractere = 1;
1848:
1849: while((1L << decalage) == (long) ((unsigned char) (caractere << decalage)))
1850: {
1851: decalage++;
1852: longueur_tableau *= 2;
1853: }
1854:
1855: if (((*s_etat_processus).pointeurs_caracteres_variables =
1856: malloc(longueur_tableau * sizeof(int))) == NULL)
1857: {
1858: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
1859: return;
1860: }
1861:
1862: for(i = 0; i < longueur_tableau; i++)
1863: {
1864: (*s_etat_processus).pointeurs_caracteres_variables[i] = -1;
1865: }
1866:
1867: (*s_etat_processus).nombre_caracteres_variables = 0;
1868:
1869: #define DECLARATION_CARACTERE(c) \
1870: do { (*s_etat_processus).pointeurs_caracteres_variables[c] = \
1871: (*s_etat_processus).nombre_caracteres_variables++; } while(0)
1872:
1873: DECLARATION_CARACTERE('A');
1874: DECLARATION_CARACTERE('B');
1875: DECLARATION_CARACTERE('C');
1876: DECLARATION_CARACTERE('D');
1877: DECLARATION_CARACTERE('E');
1878: DECLARATION_CARACTERE('F');
1879: DECLARATION_CARACTERE('G');
1880: DECLARATION_CARACTERE('H');
1881: DECLARATION_CARACTERE('I');
1882: DECLARATION_CARACTERE('J');
1883: DECLARATION_CARACTERE('K');
1884: DECLARATION_CARACTERE('L');
1885: DECLARATION_CARACTERE('M');
1886: DECLARATION_CARACTERE('N');
1887: DECLARATION_CARACTERE('O');
1888: DECLARATION_CARACTERE('P');
1889: DECLARATION_CARACTERE('Q');
1890: DECLARATION_CARACTERE('R');
1891: DECLARATION_CARACTERE('S');
1892: DECLARATION_CARACTERE('T');
1893: DECLARATION_CARACTERE('U');
1894: DECLARATION_CARACTERE('V');
1895: DECLARATION_CARACTERE('W');
1896: DECLARATION_CARACTERE('X');
1897: DECLARATION_CARACTERE('Y');
1898: DECLARATION_CARACTERE('Z');
1899:
1900: DECLARATION_CARACTERE('a');
1901: DECLARATION_CARACTERE('b');
1902: DECLARATION_CARACTERE('c');
1903: DECLARATION_CARACTERE('d');
1904: DECLARATION_CARACTERE('e');
1905: DECLARATION_CARACTERE('f');
1906: DECLARATION_CARACTERE('g');
1907: DECLARATION_CARACTERE('h');
1908: DECLARATION_CARACTERE('i');
1909: DECLARATION_CARACTERE('j');
1910: DECLARATION_CARACTERE('k');
1911: DECLARATION_CARACTERE('l');
1912: DECLARATION_CARACTERE('m');
1913: DECLARATION_CARACTERE('n');
1914: DECLARATION_CARACTERE('o');
1915: DECLARATION_CARACTERE('p');
1916: DECLARATION_CARACTERE('q');
1917: DECLARATION_CARACTERE('r');
1918: DECLARATION_CARACTERE('s');
1919: DECLARATION_CARACTERE('t');
1920: DECLARATION_CARACTERE('u');
1921: DECLARATION_CARACTERE('v');
1922: DECLARATION_CARACTERE('w');
1923: DECLARATION_CARACTERE('x');
1924: DECLARATION_CARACTERE('y');
1925: DECLARATION_CARACTERE('z');
1926:
1927: DECLARATION_CARACTERE('_');
1928:
1929: DECLARATION_CARACTERE('1');
1930: DECLARATION_CARACTERE('2');
1931: DECLARATION_CARACTERE('3');
1932: DECLARATION_CARACTERE('4');
1933: DECLARATION_CARACTERE('5');
1934: DECLARATION_CARACTERE('6');
1935: DECLARATION_CARACTERE('7');
1936: DECLARATION_CARACTERE('8');
1937: DECLARATION_CARACTERE('9');
1938: DECLARATION_CARACTERE('0');
1939: #undef DECLARATION_CARACTERE
1940:
1941: return;
1942: }
1943:
1944: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>