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