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