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