Annotation of rpl/src/gestion_variables_statiques.c, revision 1.42

1.1       bertrand    1: /*
                      2: ================================================================================
1.36      bertrand    3:   RPL/2 (R) version 4.1.11
1.30      bertrand    4:   Copyright (C) 1989-2012 Dr. BERTRAND Joël
1.1       bertrand    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: 
1.11      bertrand   23: #include "rpl-conv.h"
1.1       bertrand   24: 
                     25: 
                     26: /*
                     27: ================================================================================
1.38      bertrand   28:   Routine de retrait des variables statiques
1.1       bertrand   29: ================================================================================
                     30:   Entrée :
                     31: --------------------------------------------------------------------------------
                     32:   Sortie :
                     33: --------------------------------------------------------------------------------
                     34:   Effets de bords : néant
                     35: ================================================================================
                     36: */
                     37: 
1.38      bertrand   38: // Cette routine libère toutes les variables statiques de niveau non
                     39: // nul, donc attachées à une expression et non un programme.
1.37      bertrand   40: 
1.1       bertrand   41: logical1
1.38      bertrand   42: retrait_variables_statiques_locales(struct_processus *s_etat_processus)
1.1       bertrand   43: {
1.38      bertrand   44:    struct_liste_variables_statiques    *l_element_courant;
                     45:    struct_liste_variables_statiques    *l_element_suivant;
1.37      bertrand   46: 
                     47:    unsigned char                       registre_mode_execution;
1.1       bertrand   48: 
1.37      bertrand   49:    registre_mode_execution = (*s_etat_processus).mode_execution_programme;
1.38      bertrand   50:    l_element_courant = (*s_etat_processus).l_liste_variables_statiques;
1.1       bertrand   51: 
1.38      bertrand   52:    while(l_element_courant != NULL)
1.37      bertrand   53:    {
1.38      bertrand   54:        l_element_suivant = (*l_element_courant).suivant;
                     55: 
1.37      bertrand   56:        (*s_etat_processus).mode_execution_programme =
1.38      bertrand   57:                ((*(*l_element_courant).variable).origine == 'P') ? 'Y' : 'N';
1.37      bertrand   58: 
1.38      bertrand   59:        if ((*(*l_element_courant).variable).niveau > 0)
1.37      bertrand   60:        {
1.38      bertrand   61:            if (retrait_variable_statique(s_etat_processus,
                     62:                    (*(*l_element_courant).variable).nom,
                     63:                    (*(*l_element_courant).variable).variable_statique)
                     64:                    == d_erreur)
                     65:            {
                     66:                (*s_etat_processus).mode_execution_programme =
                     67:                        registre_mode_execution;
                     68:                return(d_erreur);
                     69:            }
1.37      bertrand   70:        }
                     71: 
1.38      bertrand   72:        l_element_courant = l_element_suivant;
1.37      bertrand   73:    }
                     74: 
                     75:    (*s_etat_processus).mode_execution_programme = registre_mode_execution;
                     76:    return(d_absence_erreur);
                     77: }
                     78: 
                     79: 
                     80: /*
                     81: ================================================================================
                     82:   Routine de création d'une nouvelle variable statique
                     83: ================================================================================
                     84:   Entrée :
                     85: --------------------------------------------------------------------------------
                     86:   Sortie :
                     87: --------------------------------------------------------------------------------
                     88:   Effets de bords : néant
                     89: ================================================================================
                     90: */
                     91: 
                     92: logical1
                     93: creation_variable_statique(struct_processus *s_etat_processus,
                     94:        struct_variable_statique *s_variable)
                     95: {
1.38      bertrand   96:    int                                     i;
                     97: 
1.37      bertrand   98:    struct_arbre_variables                  *l_variable_courante;
                     99: 
                    100:    struct_liste_variables_statiques        *l_nouvel_element;
1.1       bertrand  101: 
1.37      bertrand  102:    unsigned char                           *ptr;
                    103: 
                    104:    // Ajout de la variable en tête de la liste des variables statiques
                    105: 
                    106:    if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
                    107:            == NULL)
                    108:    {
                    109:        (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    110:        return(d_erreur);
1.1       bertrand  111:    }
                    112: 
1.37      bertrand  113:    if (((*l_nouvel_element).variable = malloc(sizeof(
                    114:            struct_variable_statique))) == NULL)
                    115:    {
                    116:        (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    117:        return(d_erreur);
                    118:    }
1.1       bertrand  119: 
1.37      bertrand  120:    (*(*l_nouvel_element).variable) = (*s_variable);
1.40      bertrand  121: 
1.37      bertrand  122:    (*l_nouvel_element).suivant = (*s_etat_processus)
                    123:            .l_liste_variables_statiques;
                    124:    (*l_nouvel_element).precedent = NULL;
1.38      bertrand  125: 
                    126:    if ((*s_etat_processus).l_liste_variables_statiques != NULL)
                    127:    {
                    128:        (*(*s_etat_processus).l_liste_variables_statiques).precedent
                    129:                = l_nouvel_element;
                    130:    }
                    131: 
1.37      bertrand  132:    (*s_etat_processus).l_liste_variables_statiques = l_nouvel_element;
                    133: 
                    134:    // Ajout de la variable à la feuille statique de l'arbre des variables
1.1       bertrand  135: 
1.38      bertrand  136:    if ((*s_etat_processus).s_arbre_variables == NULL)
                    137:    {
                    138:        if (((*s_etat_processus).s_arbre_variables =
                    139:                    allocation_noeud(s_etat_processus)) == NULL)
                    140:        {
                    141:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    142:            return(d_erreur);
                    143:        }
                    144: 
                    145:        (*(*s_etat_processus).s_arbre_variables).feuille = NULL;
                    146:        (*(*s_etat_processus).s_arbre_variables).feuille_statique = NULL;
1.42    ! bertrand  147:        (*(*s_etat_processus).s_arbre_variables).feuille_partagee = NULL;
1.38      bertrand  148:        (*(*s_etat_processus).s_arbre_variables).noeuds_utilises = 0;
                    149:        (*(*s_etat_processus).s_arbre_variables).indice_tableau_pere = -1;
                    150:        (*(*s_etat_processus).s_arbre_variables).noeud_pere = NULL;
1.42    ! bertrand  151:        INITIALISATION_MUTEX((*(*s_etat_processus).s_arbre_variables)
        !           152:                .mutex_feuille_partagee);
1.38      bertrand  153: 
                    154:        if (((*(*s_etat_processus).s_arbre_variables).noeuds =
                    155:                allocation_tableau_noeuds(s_etat_processus)) == NULL)
                    156:        {
                    157:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    158:            return(d_erreur);
                    159:        }
                    160: 
                    161:        for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
                    162:        {
                    163:            (*(*s_etat_processus).s_arbre_variables).noeuds[i] = NULL;
                    164:        }
                    165:    }
1.37      bertrand  166: 
                    167:    l_variable_courante = (*s_etat_processus).s_arbre_variables;
                    168:    ptr = (*s_variable).nom;
                    169: 
                    170:    while((*ptr) != d_code_fin_chaine)
1.1       bertrand  171:    {
1.37      bertrand  172:        BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0,
                    173:                uprintf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom,
                    174:                *ptr));
                    175: 
1.38      bertrand  176:        if ((*l_variable_courante).noeuds[(*s_etat_processus)
                    177:                .pointeurs_caracteres_variables[*ptr]] == NULL)
                    178:        {
                    179:            // Le noeud n'existe pas encore, on le crée et on le marque
                    180:            // comme utilisé dans la structure parente.
                    181: 
                    182:            if (((*l_variable_courante).noeuds[(*s_etat_processus)
                    183:                    .pointeurs_caracteres_variables[*ptr]] =
                    184:                    allocation_noeud(s_etat_processus)) == NULL)
                    185:            {
                    186:                (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    187:                return(d_erreur);
                    188:            }
                    189: 
                    190:            (*l_variable_courante).noeuds_utilises++;
1.37      bertrand  191: 
1.38      bertrand  192:            // La feuille est par défaut vide et aucun élément du tableau noeuds
                    193:            // (les branches qui peuvent être issues de ce nouveau noeud)
                    194:            // n'est encore utilisée.
                    195: 
                    196:            (*(*l_variable_courante).noeuds[(*s_etat_processus)
                    197:                    .pointeurs_caracteres_variables[*ptr]]).feuille = NULL;
                    198:            (*(*l_variable_courante).noeuds[(*s_etat_processus)
                    199:                    .pointeurs_caracteres_variables[*ptr]]).feuille_statique
                    200:                    = NULL;
                    201:            (*(*l_variable_courante).noeuds[(*s_etat_processus)
1.42    ! bertrand  202:                    .pointeurs_caracteres_variables[*ptr]]).feuille_partagee
        !           203:                    = NULL;
        !           204:            (*(*l_variable_courante).noeuds[(*s_etat_processus)
1.38      bertrand  205:                    .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises = 0;
1.42    ! bertrand  206:            INITIALISATION_MUTEX((*(*l_variable_courante).noeuds
        !           207:                    [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]])
        !           208:                    .mutex_feuille_partagee);
1.38      bertrand  209: 
                    210:            // Le champ noeud_pere de la structure créée pointe sur
                    211:            // la structure parente et l'indice tableau_pere correspond à la
                    212:            // position réelle dans le tableau noeuds[] de la structure parente
                    213:            // du noeud courant. Cette valeur sera utilisée lors de la
                    214:            // destruction du noeud pour annuler le pointeur contenu dans
                    215:            // le tableau noeuds[] de la structure parente.
                    216: 
                    217:            (*(*l_variable_courante).noeuds[(*s_etat_processus)
                    218:                    .pointeurs_caracteres_variables[*ptr]]).noeud_pere =
                    219:                    l_variable_courante;
                    220:            (*(*l_variable_courante).noeuds[(*s_etat_processus)
                    221:                    .pointeurs_caracteres_variables[*ptr]])
                    222:                    .indice_tableau_pere = (*s_etat_processus)
                    223:                    .pointeurs_caracteres_variables[*ptr];
                    224: 
                    225:            // Allocation du tableau noeuds[] et initialisation à zéro de
                    226:            // tous les pointeurs.
                    227: 
                    228:            if (((*(*l_variable_courante).noeuds[(*s_etat_processus)
                    229:                    .pointeurs_caracteres_variables[*ptr]]).noeuds =
                    230:                    allocation_tableau_noeuds(s_etat_processus)) == NULL)
                    231:            {
                    232:                (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    233:                return(d_erreur);
                    234:            }
                    235: 
                    236:            for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
                    237:            {
                    238:                (*(*l_variable_courante).noeuds[(*s_etat_processus)
                    239:                        .pointeurs_caracteres_variables[*ptr]]).noeuds[i]
                    240:                        = NULL;
                    241:            }
                    242:        }
1.37      bertrand  243: 
                    244:        l_variable_courante = (*l_variable_courante).noeuds
                    245:                [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]];
                    246:        ptr++;
1.1       bertrand  247:    }
1.37      bertrand  248: 
                    249:    if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
                    250:            == NULL)
1.1       bertrand  251:    {
1.37      bertrand  252:        (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    253:        return(d_erreur);
1.1       bertrand  254:    }
                    255: 
1.37      bertrand  256:    // Dans la feuille statique de l'arbre des variables, on ne balaie
                    257:    // les variables que dans l'ordre. Le champ 'reference' est alors utilisé
                    258:    // pour sauvegarder une référence vers la liste des variables statiques
                    259:    // pour pouvoir purger l'élément en cas de besoin.
                    260: 
                    261:    (*l_nouvel_element).suivant = (*l_variable_courante).feuille_statique;
                    262:    (*l_nouvel_element).precedent = NULL;
1.38      bertrand  263: 
                    264:    if ((*l_nouvel_element).suivant != NULL)
                    265:    {
                    266:        (*(*l_nouvel_element).suivant).precedent = l_nouvel_element;
                    267:    }
1.37      bertrand  268: 
                    269:    (*l_nouvel_element).reference =
                    270:            (*s_etat_processus).l_liste_variables_statiques;
                    271:    (*l_nouvel_element).variable = (*(*s_etat_processus)
                    272:            .l_liste_variables_statiques).variable;
                    273:    (*l_variable_courante).feuille_statique = l_nouvel_element;
1.38      bertrand  274:    (*l_nouvel_element).feuille = l_variable_courante;
                    275: 
1.37      bertrand  276:    return(d_absence_erreur);
1.1       bertrand  277: }
                    278: 
                    279: 
                    280: /*
                    281: ================================================================================
                    282:   Procédure de retrait d'une variable statique de la base
                    283: ================================================================================
                    284:   Entrée :
                    285: --------------------------------------------------------------------------------
                    286:   Sortie :
                    287: --------------------------------------------------------------------------------
                    288:   Effets de bord : néant
                    289: ================================================================================
                    290: */
                    291: 
                    292: logical1
                    293: retrait_variable_statique(struct_processus *s_etat_processus,
                    294:        unsigned char *nom_variable, union_position_variable position)
                    295: {
1.37      bertrand  296:    struct_liste_variables_statiques        *l_element_a_supprimer;
                    297:    struct_liste_variables_statiques        *l_element_liste_a_supprimer;
                    298: 
                    299:    logical1                                erreur;
                    300: 
                    301:    if ((l_element_a_supprimer = recherche_variable_statique(s_etat_processus,
                    302:            nom_variable, position, ((*s_etat_processus)
                    303:            .mode_execution_programme == 'Y') ? 'P' : 'E')) != NULL)
                    304:    {
                    305:        // (*s_etat_processus).pointeur_variable_statique_courante
                    306:        // pointe sur la variable à éliminer. Cette variable est celle qui
                    307:        // est présente dans l'une des feuilles statiques de l'arbre des
                    308:        // variables.
1.1       bertrand  309: 
1.37      bertrand  310:        l_element_liste_a_supprimer = (*l_element_a_supprimer).reference;
1.1       bertrand  311: 
1.37      bertrand  312:        // Suppression de la liste des variables statiques
1.1       bertrand  313: 
1.37      bertrand  314:        if ((*l_element_liste_a_supprimer).precedent != NULL)
                    315:        {
1.39      bertrand  316:            // L'élément à supprimer n'est pas le premier de la liste.
                    317: 
1.37      bertrand  318:            (*(*l_element_liste_a_supprimer).precedent).suivant =
                    319:                    (*l_element_liste_a_supprimer).suivant;
1.39      bertrand  320: 
                    321:            if ((*l_element_liste_a_supprimer).suivant != NULL)
                    322:            {
                    323:                // Il y a un élément suivant. On le chaîne.
                    324:                (*(*l_element_liste_a_supprimer).suivant).precedent = NULL;
                    325:            }
1.37      bertrand  326:        }
                    327:        else
1.1       bertrand  328:        {
1.39      bertrand  329:            // L'élement est le premier de la liste. S'il y a un élément
                    330:            // suivant, on le chaîne.
                    331: 
1.38      bertrand  332:            if ((*l_element_liste_a_supprimer).suivant != NULL)
                    333:            {
                    334:                (*(*l_element_liste_a_supprimer).suivant).precedent = NULL;
                    335:            }
                    336: 
                    337:            (*s_etat_processus).l_liste_variables_statiques =
                    338:                    (*l_element_liste_a_supprimer).suivant;
1.37      bertrand  339:        }
1.1       bertrand  340: 
1.37      bertrand  341:        free(l_element_liste_a_supprimer);
1.1       bertrand  342: 
1.37      bertrand  343:        // Suppression depuis la feuille statique. Le champ 'precedent' ne sert
                    344:        // pas car la liste est simplement chaînée.
1.1       bertrand  345: 
1.37      bertrand  346:        if ((*l_element_a_supprimer).precedent != NULL)
                    347:        {
1.39      bertrand  348:            // L'élément n'est pas le premier de la liste.
                    349: 
1.37      bertrand  350:            (*(*l_element_a_supprimer).precedent).suivant =
                    351:                    (*l_element_a_supprimer).suivant;
1.39      bertrand  352: 
                    353:            if ((*l_element_a_supprimer).suivant != NULL)
                    354:            {
                    355:                (*(*l_element_a_supprimer).suivant).precedent =
                    356:                        (*l_element_a_supprimer).precedent;
                    357:            }
                    358:            else
                    359:            {
                    360:                (*(*l_element_a_supprimer).precedent).suivant = NULL;
                    361:            }
1.37      bertrand  362:        }
                    363:        else
                    364:        {
1.39      bertrand  365:            // L'élément est le premier de la liste.
                    366: 
                    367:            if ((*l_element_a_supprimer).suivant != NULL)
                    368:            {
                    369:                (*(*l_element_a_supprimer).suivant).precedent = NULL;
                    370:            }
                    371: 
1.38      bertrand  372:            (*(*l_element_a_supprimer).feuille).feuille_statique
                    373:                    = (*l_element_a_supprimer).suivant;
1.37      bertrand  374:        }
1.1       bertrand  375: 
1.37      bertrand  376:        liberation(s_etat_processus, (*(*l_element_a_supprimer).variable)
                    377:                .objet);
                    378:        free((*(*l_element_a_supprimer).variable).nom);
                    379:        free((*l_element_a_supprimer).variable);
                    380:        free(l_element_a_supprimer);
                    381: 
1.1       bertrand  382:        erreur = d_absence_erreur;
                    383:    }
                    384:    else
                    385:    {
                    386:        erreur = d_erreur;
                    387:        (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
                    388:    }
                    389: 
                    390:    return erreur;
                    391: }
                    392: 
                    393: 
                    394: /*
                    395: ================================================================================
                    396:   Procédure de recherche d'une variable statique par son nom dans la base
                    397: ================================================================================
                    398:   Entrée :
                    399: --------------------------------------------------------------------------------
                    400:   Sortie :
                    401: --------------------------------------------------------------------------------
                    402:   Effets de bord : néant
                    403: ================================================================================
                    404: */
                    405: 
1.37      bertrand  406: struct_liste_variables_statiques *
1.1       bertrand  407: recherche_variable_statique(struct_processus *s_etat_processus,
                    408:        unsigned char *nom_variable, union_position_variable position,
                    409:        unsigned char origine)
                    410: {
1.37      bertrand  411:    int                                 pointeur;
1.1       bertrand  412: 
1.37      bertrand  413:    struct_arbre_variables              *l_variable_courante;
                    414:    struct_liste_variables_statiques    *l_element_courant;
1.1       bertrand  415: 
1.37      bertrand  416:    unsigned char                       *ptr;
1.1       bertrand  417: 
1.37      bertrand  418:    l_variable_courante = (*s_etat_processus).s_arbre_variables;
                    419:    ptr = nom_variable;
1.1       bertrand  420: 
1.37      bertrand  421:    while((*ptr) != d_code_fin_chaine)
1.1       bertrand  422:    {
1.37      bertrand  423:        pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr];
1.1       bertrand  424: 
1.37      bertrand  425:        if (pointeur < 0)
1.1       bertrand  426:        {
1.37      bertrand  427:            // Caractère hors de l'alphabet des variables
1.1       bertrand  428: 
1.37      bertrand  429:            (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
                    430:            return(NULL);
1.1       bertrand  431:        }
1.37      bertrand  432: 
                    433:        if ((*l_variable_courante).noeuds[pointeur] == NULL)
1.1       bertrand  434:        {
1.37      bertrand  435:            // Le chemin de la variable candidate n'existe pas.
                    436:            (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
                    437:            return(NULL);
1.1       bertrand  438:        }
                    439: 
1.37      bertrand  440:        l_variable_courante = (*l_variable_courante).noeuds[pointeur];
                    441:        ptr++;
1.1       bertrand  442:    }
1.37      bertrand  443: 
                    444:    if ((*l_variable_courante).feuille_statique != NULL)
1.1       bertrand  445:    {
1.37      bertrand  446:        // Il existe au moins une variable statique du nom requis.
1.1       bertrand  447: 
1.37      bertrand  448:        l_element_courant = (*l_variable_courante).feuille_statique;
1.1       bertrand  449: 
1.37      bertrand  450:        while(l_element_courant != NULL)
1.1       bertrand  451:        {
1.37      bertrand  452:            if ((*(*l_element_courant).variable).origine == 'P')
1.1       bertrand  453:            {
1.37      bertrand  454:                if (((*(*l_element_courant).variable).variable_statique.adresse
                    455:                        == position.adresse) &&
                    456:                        ((*(*l_element_courant).variable).origine == origine))
1.1       bertrand  457:                {
1.37      bertrand  458:                    (*s_etat_processus).pointeur_variable_statique_courante
1.38      bertrand  459:                            = (*l_element_courant).variable;
1.37      bertrand  460:                    return(l_element_courant);
1.1       bertrand  461:                }
                    462:            }
1.37      bertrand  463:            else
1.1       bertrand  464:            {
1.37      bertrand  465:                if (((*(*l_element_courant).variable).variable_statique.pointeur
                    466:                        == position.pointeur) &&
                    467:                        ((*(*l_element_courant).variable).origine == origine))
1.1       bertrand  468:                {
1.37      bertrand  469:                    (*s_etat_processus).pointeur_variable_statique_courante
1.38      bertrand  470:                            = (*l_element_courant).variable;
1.37      bertrand  471:                    return(l_element_courant);
1.1       bertrand  472:                }
                    473:            }
1.38      bertrand  474: 
                    475:            l_element_courant = (*l_element_courant).suivant;
1.1       bertrand  476:        }
                    477:    }
                    478: 
1.37      bertrand  479:    (*s_etat_processus).pointeur_variable_statique_courante = NULL;
                    480:    return(NULL);
1.1       bertrand  481: }
                    482: 
                    483: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>