1: /*
2: ================================================================================
3: RPL/2 (R) version 4.1.0.prerelease.1
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>