Annotation of rpl/src/gestion_variables.c, revision 1.12
1.1 bertrand 1: /*
2: ================================================================================
1.11 bertrand 3: RPL/2 (R) version 4.0.18
1.1 bertrand 4: Copyright (C) 1989-2010 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: logical1
43: creation_variable(struct_processus *s_etat_processus,
44: struct_variable *s_variable,
45: unsigned char autorisation_creation_variable_statique,
46: unsigned char autorisation_creation_variable_partagee)
47: {
1.12 ! bertrand 48: logical1 presence;
! 49:
1.1 bertrand 50: long i;
51:
52: struct_variable *s_nouvelle_base;
53:
54: (*s_etat_processus).nombre_variables++;
55:
56: if ((*s_etat_processus).nombre_variables > (*s_etat_processus)
57: .nombre_variables_allouees)
58: {
59: // La nouvelle variable ne tient pas dans la table courante. Il
60: // faut donc en augmenter la taille.
61:
62: if ((*s_etat_processus).nombre_variables_allouees == 0)
63: {
64: (*s_etat_processus).nombre_variables_allouees =
65: (*s_etat_processus).nombre_variables;
66: }
67: else
68: {
69: while((*s_etat_processus).nombre_variables >
70: (*s_etat_processus).nombre_variables_allouees)
71: {
72: (*s_etat_processus).nombre_variables_allouees *= 2;
73: }
74: }
75:
76: if ((s_nouvelle_base = realloc((*s_etat_processus).s_liste_variables,
77: (*s_etat_processus).nombre_variables_allouees *
78: sizeof(struct_variable))) == NULL)
79: {
80: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
81: (*s_etat_processus).nombre_variables--;
82: return(d_erreur);
83: }
84:
85: (*s_etat_processus).s_liste_variables = s_nouvelle_base;
86: }
87:
88: if ((*s_etat_processus).mode_execution_programme == 'Y')
89: {
90: (*s_variable).origine = 'P';
91: }
92: else
93: {
94: (*s_variable).origine = 'E';
95: }
96:
97: if ((*s_variable).niveau == 0)
98: {
99: // Un point d'entrée de définition est verrouillé.
100:
101: if ((*s_variable).origine == 'P')
102: {
103: (*s_variable).variable_statique.adresse = 0;
104: (*s_variable).variable_partagee.adresse = 0;
105: }
106: else
107: {
108: (*s_variable).variable_statique.pointeur = NULL;
109: (*s_variable).variable_partagee.pointeur = NULL;
110: }
111:
112: (*s_variable).variable_verrouillee = d_vrai;
113: }
114: else if ((*s_variable).niveau == 1)
115: {
116: // Une variable globale ne peut être statique.
117:
118: if ((*s_variable).origine == 'P')
119: {
120: (*s_variable).variable_statique.adresse = 0;
121: (*s_variable).variable_partagee.adresse = 0;
122: }
123: else
124: {
125: (*s_variable).variable_statique.pointeur = NULL;
126: (*s_variable).variable_partagee.pointeur = NULL;
127: }
128:
129: (*s_variable).variable_verrouillee = d_faux;
130: }
131: else
132: {
133: // 0 -> variable volatile
134: // adresse de création -> variable statique
135:
136: if (autorisation_creation_variable_statique == 'V')
137: {
138: if (autorisation_creation_variable_partagee == 'S')
139: {
140: // On force la création d'une variable partagée
141:
142: if ((*s_variable).origine == 'P')
143: {
144: (*s_variable).variable_statique.adresse = 0;
145: (*s_variable).variable_partagee.adresse =
146: (*s_etat_processus).position_courante;
147: }
148: else
149: {
150: (*s_variable).variable_statique.pointeur = NULL;
151: (*s_variable).variable_partagee.pointeur =
152: (*s_etat_processus).objet_courant;
153: }
154: }
155: else
156: {
157: // On force la création d'une variable volatile
158:
159: if ((*s_variable).origine == 'P')
160: {
161: (*s_variable).variable_statique.adresse = 0;
162: (*s_variable).variable_partagee.adresse = 0;
163: }
164: else
165: {
166: (*s_variable).variable_statique.pointeur = NULL;
167: (*s_variable).variable_partagee.pointeur = NULL;
168: }
169: }
170: }
171: else
172: {
173: // On force la création d'une variable statique.
174:
175: if ((*s_variable).origine == 'P')
176: {
177: (*s_variable).variable_statique.adresse =
178: (*s_etat_processus).position_courante;
179: (*s_variable).variable_partagee.adresse = 0;
180: }
181: else
182: {
183: (*s_variable).variable_statique.pointeur =
184: (*s_etat_processus).objet_courant;
185: (*s_variable).variable_partagee.pointeur = 0;
186: }
187: }
188:
189: (*s_variable).variable_verrouillee = d_faux;
190: }
191:
192: /*
193: * Positionnement de la variable au bon endroit
194: */
195:
196: // Nous avons (*s_etat_processus).nombre_variables - 1 variables dans la
197: // table qui sera balayée de la fin vers le début.
198:
199: if ((*s_etat_processus).nombre_variables == 1)
200: {
201: (*s_etat_processus).s_liste_variables[0] = (*s_variable);
202: }
203: else
204: {
205: for(i = (*s_etat_processus).nombre_variables - 2; i >= 0; i--)
206: {
207: if (strcmp((*s_variable).nom,
208: (*s_etat_processus).s_liste_variables[i].nom) < 0)
209: {
210: (*s_etat_processus).s_liste_variables[i + 1] =
211: (*s_etat_processus).s_liste_variables[i];
212: }
213: else
214: {
215: break;
216: }
217: }
218:
1.12 ! bertrand 219: if ((*s_variable).niveau > 1)
! 220: {
! 221: // Cas d'une variable locale
! 222: (*s_etat_processus).s_liste_variables[i + 1] = (*s_variable);
! 223: }
! 224: else
! 225: {
! 226: // Cas d'une variable globale
! 227: presence = d_faux;
! 228:
! 229: for(; i >= 0; i--)
! 230: {
! 231: if (strcmp((*s_variable).nom,
! 232: (*s_etat_processus).s_liste_variables[i].nom) == 0)
! 233: {
! 234: (*s_etat_processus).s_liste_variables[i + 1] =
! 235: (*s_etat_processus).s_liste_variables[i];
! 236: }
! 237: else
! 238: {
! 239: presence = d_vrai;
! 240: break;
! 241: }
! 242: }
! 243:
! 244: if (presence = d_faux)
! 245: {
! 246: (*s_etat_processus).s_liste_variables[0] = (*s_variable);
! 247: }
! 248: else
! 249: {
! 250: (*s_etat_processus).s_liste_variables[i + 1] = (*s_variable);
! 251: }
! 252: }
1.1 bertrand 253: }
254:
255: return(d_absence_erreur);
256: }
257:
258:
259: /*
260: ================================================================================
261: Procédure de retrait d'une variable de la base
262: ================================================================================
263: Entrée : type 'G' ou 'L' selon que l'on retire une variable locale (incluant
264: les globales) ou strictement globale.
265: --------------------------------------------------------------------------------
266: Sortie :
267: --------------------------------------------------------------------------------
268: Effets de bord : néant
269: ================================================================================
270: */
271:
272: logical1
273: retrait_variable(struct_processus *s_etat_processus,
274: unsigned char *nom_variable, unsigned char type)
275: {
276: struct_variable *s_nouvelle_base;
277:
278: logical1 erreur;
279:
280: unsigned long position_courante;
281: unsigned long position_supprimee;
282:
283: if (recherche_variable(s_etat_processus, nom_variable) == d_vrai)
284: {
285: if (type == 'G')
286: {
287: if ((*s_etat_processus).position_variable_courante > 0)
288: {
289: while(strcmp((*s_etat_processus).s_liste_variables
290: [(*s_etat_processus).position_variable_courante]
291: .nom, nom_variable) == 0)
292: {
293: (*s_etat_processus).position_variable_courante--;
294:
295: if ((*s_etat_processus).position_variable_courante >=
296: (*s_etat_processus).nombre_variables)
297: {
298: erreur = d_erreur;
299: (*s_etat_processus).erreur_execution =
300: d_ex_variable_non_definie;
301: return erreur;
302: }
303: }
304:
305: (*s_etat_processus).position_variable_courante++;
306: }
307:
308: if ((*s_etat_processus).s_liste_variables
309: [(*s_etat_processus).position_variable_courante]
310: .niveau != 1)
311: {
312: erreur = d_erreur;
313: (*s_etat_processus).erreur_execution =
314: d_ex_variable_non_definie;
315: return erreur;
316: }
317:
318: if ((*s_etat_processus).s_liste_variables
319: [(*s_etat_processus).position_variable_courante]
320: .variable_verrouillee == d_vrai)
321: {
322: erreur = d_erreur;
323: (*s_etat_processus).erreur_execution =
324: d_ex_variable_verrouillee;
325: return erreur;
326: }
327: }
328:
329: if ((*s_etat_processus).nombre_variables <
330: ((*s_etat_processus).nombre_variables_allouees / 2))
331: {
332: (*s_etat_processus).nombre_variables_allouees /= 2;
333:
334: // (*s_etat_processus).nombre_variables est forcément
335: // supérieur à 1 (la décrémentation est postérieure). Ce test
336: // est vrai lorsque le nombre de variables allouées est
337: // strictement supérieur à 2.
338:
339: if ((s_nouvelle_base =
340: realloc((*s_etat_processus).s_liste_variables,
341: (*s_etat_processus).nombre_variables_allouees *
342: sizeof(struct_variable))) == NULL)
343: {
344: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
345: return(d_erreur);
346: }
347:
348: (*s_etat_processus).s_liste_variables = s_nouvelle_base;
349: }
350:
351: position_supprimee = (*s_etat_processus).position_variable_courante;
352:
353: liberation(s_etat_processus, (*s_etat_processus).s_liste_variables
354: [position_supprimee].objet);
355: free((*s_etat_processus).s_liste_variables[position_supprimee].nom);
356:
357: (*s_etat_processus).nombre_variables--;
358:
359: for(position_courante = position_supprimee;
360: position_courante < (*s_etat_processus).nombre_variables;
361: position_courante++)
362: {
363: (*s_etat_processus).s_liste_variables[position_courante] =
364: (*s_etat_processus).s_liste_variables
365: [position_courante + 1];
366: }
367:
368: erreur = d_absence_erreur;
369: }
370: else
371: {
372: erreur = d_erreur;
373: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
374: }
375:
376: return erreur;
377: }
378:
379:
380: /*
381: ================================================================================
382: Procédure de recherche d'une variable par son nom dans la base
383: ================================================================================
384: Entrée :
385: --------------------------------------------------------------------------------
386: Sortie :
387: --------------------------------------------------------------------------------
388: Effets de bord : néant
389: ================================================================================
390: */
391:
392: logical1
393: recherche_variable(struct_processus *s_etat_processus,
394: unsigned char *nom_variable)
395: {
396: logical1 existence_variable;
397:
398: long difference;
399: long difference_inferieure;
400: long difference_superieure;
401:
402: struct_liste_pile_systeme *l_element_courant;
403:
404: unsigned long borne_inferieure;
405: unsigned long borne_superieure;
406: unsigned long moyenne;
407: unsigned long niveau_appel;
408: unsigned long nombre_iterations_maximal;
409: unsigned long ordre_iteration;
410:
411: if ((*s_etat_processus).nombre_variables == 0)
412: {
413: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
414: return d_faux;
415: }
416:
417: ordre_iteration = 0;
418: nombre_iterations_maximal = ((unsigned long)
419: (log((*s_etat_processus).nombre_variables) / log(2))) + 2;
420:
421: borne_inferieure = 0;
422: borne_superieure = (*s_etat_processus).nombre_variables - 1;
423:
424: do
425: {
426: moyenne = (borne_inferieure + borne_superieure) / 2;
427: ordre_iteration++;
428:
429: if (((borne_inferieure + borne_superieure) % 2) == 0)
430: {
431: difference = strcmp(nom_variable,
432: ((*s_etat_processus).s_liste_variables)[moyenne].nom);
433:
434: if (difference != 0)
435: {
436: if (difference > 0)
437: {
438: borne_inferieure = moyenne;
439: }
440: else
441: {
442: borne_superieure = moyenne;
443: }
444: }
445: }
446: else
447: {
448: difference_inferieure = strcmp(nom_variable,
449: ((*s_etat_processus).s_liste_variables)[moyenne].nom);
450: difference_superieure = strcmp(nom_variable,
451: ((*s_etat_processus).s_liste_variables)[moyenne + 1].nom);
452:
453: if (difference_inferieure == 0)
454: {
455: difference = 0;
456: }
457: else if (difference_superieure == 0)
458: {
459: difference = 0;
460: moyenne++;
461: }
462: else
463: {
464: difference = difference_inferieure;
465:
466: if (difference > 0)
467: {
468: borne_inferieure = moyenne;
469: }
470: else
471: {
472: borne_superieure = moyenne;
473: }
474: }
475: }
476: } while((difference != 0) &&
477: (ordre_iteration <= nombre_iterations_maximal));
478:
479: if (ordre_iteration > nombre_iterations_maximal)
480: {
481: existence_variable = d_faux;
482: (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
483: }
484: else
485: {
486: if ((moyenne + 1) < (*s_etat_processus).nombre_variables)
487: {
488: while(strcmp(((*s_etat_processus).s_liste_variables)
489: [moyenne + 1].nom, nom_variable) == 0)
490: {
491: moyenne++;
492:
493: if ((moyenne + 1) >= (*s_etat_processus).nombre_variables)
494: {
495: break;
496: }
497: }
498: }
499:
500: (*s_etat_processus).position_variable_courante = moyenne;
501:
502: if ((*s_etat_processus).s_liste_variables[(*s_etat_processus)
503: .position_variable_courante].niveau > 1)
504: {
505: // La variable trouvée est une variable locale.
506: // On vérifie qu'elle est accessible à la définition
507: // courante.
508:
509: niveau_appel = (*s_etat_processus).niveau_courant;
510: l_element_courant = (*s_etat_processus).l_base_pile_systeme;
511:
512: if (l_element_courant == NULL)
513: {
514: (*s_etat_processus).erreur_systeme = d_es_pile_vide;
515: existence_variable = d_faux;
516:
517: return existence_variable;
518: }
519:
520: while((*l_element_courant).retour_definition != 'Y')
521: {
522: l_element_courant = (*l_element_courant).suivant;
523:
524: if (l_element_courant == NULL)
525: {
526: (*s_etat_processus).erreur_systeme = d_es_pile_vide;
527: existence_variable = d_faux;
528:
529: return existence_variable;
530: }
531: }
532:
533: niveau_appel = (*l_element_courant).niveau_courant;
534:
535: if (niveau_appel < (*s_etat_processus).s_liste_variables
536: [(*s_etat_processus).position_variable_courante].niveau)
537: {
538: existence_variable = d_vrai;
539: }
540: else
541: {
542: existence_variable = d_faux;
543:
544: // La variable locale n'est pas accessible. On regarde si par
545: // hasard il existe une variable globale.
546:
547: while((*s_etat_processus).position_variable_courante != 0)
548: {
549: if (strcmp(((*s_etat_processus).s_liste_variables)
550: [(*s_etat_processus).position_variable_courante - 1] .nom, nom_variable) == 0)
551: {
552: (*s_etat_processus).position_variable_courante--;
553: }
554: else
555: {
556: if ((*s_etat_processus).s_liste_variables
557: [(*s_etat_processus).position_variable_courante]
558: .niveau <= 1)
559: {
560: existence_variable = d_vrai;
561: }
562:
563: break;
564: }
565: }
566:
567: if ((strcmp(((*s_etat_processus).s_liste_variables)
568: [(*s_etat_processus).position_variable_courante].nom,
569: nom_variable) == 0) && ((*s_etat_processus)
570: .s_liste_variables[(*s_etat_processus)
571: .position_variable_courante].niveau <= 1))
572: {
573: existence_variable = d_vrai;
574: }
575: }
576: }
577: else
578: {
579: // La variable trouvée est soit un pointeur sur une définition
580: // (niveau 0), soit une variable globale (niveau 1).
581:
582: existence_variable = d_vrai;
583: }
584: }
585:
586: return existence_variable;
587: }
588:
589:
590: /*
591: ================================================================================
592: Procédure de retrait des variables de niveau strictement supérieur au
593: niveau courant
594: ================================================================================
595: Entrée :
596: --------------------------------------------------------------------------------
597: Sortie :
598: --------------------------------------------------------------------------------
599: Effets de bord : néant
600: ================================================================================
601: */
602:
603: logical1
604: retrait_variable_par_niveau(struct_processus *s_etat_processus)
605: {
606: unsigned long i;
607: unsigned long j;
608:
609: struct_variable *tampon;
610:
611: for(j = 0, i = 0; i < (*s_etat_processus).nombre_variables; i++)
612: {
613: if ((*s_etat_processus).s_liste_variables[i].niveau <=
614: (*s_etat_processus).niveau_courant)
615: {
616: (*s_etat_processus).s_liste_variables[j++] =
617: (*s_etat_processus).s_liste_variables[i];
618: }
619: else
620: {
621: if ((*s_etat_processus).s_liste_variables[i].origine == 'P')
622: {
623: if ((*s_etat_processus).s_liste_variables[i]
624: .variable_statique.adresse != 0)
625: {
626: /*
627: * Gestion des variables statiques
628: */
629:
630: if (recherche_variable_statique(s_etat_processus,
631: (*s_etat_processus).s_liste_variables[i]
632: .nom, (*s_etat_processus).s_liste_variables
633: [i].variable_statique, ((*s_etat_processus)
634: .mode_execution_programme
635: == 'Y') ? 'P' : 'E') == d_vrai)
636: {
637: (*s_etat_processus).s_liste_variables_statiques
638: [(*s_etat_processus)
639: .position_variable_statique_courante]
640: .objet = (*s_etat_processus)
641: .s_liste_variables[i].objet;
642: }
643: else
644: {
645: (*s_etat_processus).erreur_systeme =
646: d_es_variable_introuvable;
647: }
648:
649: (*s_etat_processus).s_liste_variables[i].objet = NULL;
650: }
651: }
652: else
653: {
654: if ((*s_etat_processus).s_liste_variables[i]
655: .variable_statique.pointeur != NULL)
656: {
657: /*
658: * Gestion des variables statiques
659: */
660:
661: if (recherche_variable_statique(s_etat_processus,
662: (*s_etat_processus).s_liste_variables[i]
663: .nom, (*s_etat_processus).s_liste_variables[i]
664: .variable_statique, ((*s_etat_processus)
665: .mode_execution_programme
666: == 'Y') ? 'P' : 'E') == d_vrai)
667: {
668: (*s_etat_processus).s_liste_variables_statiques
669: [(*s_etat_processus)
670: .position_variable_statique_courante]
671: .objet = (*s_etat_processus)
672: .s_liste_variables[i].objet;
673: }
674: else
675: {
676: (*s_etat_processus).erreur_systeme =
677: d_es_variable_introuvable;
678: }
679:
680: (*s_etat_processus).s_liste_variables[i].objet = NULL;
681: }
682: }
683:
684: free((*s_etat_processus).s_liste_variables[i].nom);
685: liberation(s_etat_processus,
686: (*s_etat_processus).s_liste_variables[i].objet);
687: }
688: }
689:
690: (*s_etat_processus).nombre_variables = j;
691:
692: if ((*s_etat_processus).nombre_variables <
693: ((*s_etat_processus).nombre_variables_allouees / 2))
694: {
695: (*s_etat_processus).nombre_variables_allouees /= 2;
696:
697: if ((tampon = realloc((*s_etat_processus).s_liste_variables,
698: (*s_etat_processus).nombre_variables_allouees *
699: sizeof(struct_variable))) == NULL)
700: {
701: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
702: return(d_erreur);
703: }
704:
705: (*s_etat_processus).s_liste_variables = tampon;
706: }
707:
708: return(d_absence_erreur);
709: }
710:
711: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>