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

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: 
1.38    ! bertrand  106: printf("<0>\n");
1.37      bertrand  107:    if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
                    108:            == NULL)
                    109:    {
                    110:        (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    111:        return(d_erreur);
1.1       bertrand  112:    }
                    113: 
1.37      bertrand  114:    if (((*l_nouvel_element).variable = malloc(sizeof(
                    115:            struct_variable_statique))) == NULL)
                    116:    {
                    117:        (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    118:        return(d_erreur);
                    119:    }
1.1       bertrand  120: 
1.37      bertrand  121:    (*(*l_nouvel_element).variable) = (*s_variable);
                    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;
        !           147:        (*(*s_etat_processus).s_arbre_variables).noeuds_utilises = 0;
        !           148:        (*(*s_etat_processus).s_arbre_variables).indice_tableau_pere = -1;
        !           149:        (*(*s_etat_processus).s_arbre_variables).noeud_pere = NULL;
        !           150: 
        !           151:        if (((*(*s_etat_processus).s_arbre_variables).noeuds =
        !           152:                allocation_tableau_noeuds(s_etat_processus)) == NULL)
        !           153:        {
        !           154:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
        !           155:            return(d_erreur);
        !           156:        }
        !           157: 
        !           158:        for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
        !           159:        {
        !           160:            (*(*s_etat_processus).s_arbre_variables).noeuds[i] = NULL;
        !           161:        }
        !           162:    }
1.37      bertrand  163: 
                    164:    l_variable_courante = (*s_etat_processus).s_arbre_variables;
                    165:    ptr = (*s_variable).nom;
                    166: 
                    167:    while((*ptr) != d_code_fin_chaine)
1.1       bertrand  168:    {
1.37      bertrand  169:        BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0,
                    170:                uprintf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom,
                    171:                *ptr));
                    172: 
1.38    ! bertrand  173:        if ((*l_variable_courante).noeuds[(*s_etat_processus)
        !           174:                .pointeurs_caracteres_variables[*ptr]] == NULL)
        !           175:        {
        !           176:            // Le noeud n'existe pas encore, on le crée et on le marque
        !           177:            // comme utilisé dans la structure parente.
        !           178: 
        !           179:            if (((*l_variable_courante).noeuds[(*s_etat_processus)
        !           180:                    .pointeurs_caracteres_variables[*ptr]] =
        !           181:                    allocation_noeud(s_etat_processus)) == NULL)
        !           182:            {
        !           183:                (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
        !           184:                return(d_erreur);
        !           185:            }
        !           186: 
        !           187:            (*l_variable_courante).noeuds_utilises++;
1.37      bertrand  188: 
1.38    ! bertrand  189:            // La feuille est par défaut vide et aucun élément du tableau noeuds
        !           190:            // (les branches qui peuvent être issues de ce nouveau noeud)
        !           191:            // n'est encore utilisée.
        !           192: 
        !           193:            (*(*l_variable_courante).noeuds[(*s_etat_processus)
        !           194:                    .pointeurs_caracteres_variables[*ptr]]).feuille = NULL;
        !           195:            (*(*l_variable_courante).noeuds[(*s_etat_processus)
        !           196:                    .pointeurs_caracteres_variables[*ptr]]).feuille_statique
        !           197:                    = NULL;
        !           198:            (*(*l_variable_courante).noeuds[(*s_etat_processus)
        !           199:                    .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises = 0;
        !           200: 
        !           201:            // Le champ noeud_pere de la structure créée pointe sur
        !           202:            // la structure parente et l'indice tableau_pere correspond à la
        !           203:            // position réelle dans le tableau noeuds[] de la structure parente
        !           204:            // du noeud courant. Cette valeur sera utilisée lors de la
        !           205:            // destruction du noeud pour annuler le pointeur contenu dans
        !           206:            // le tableau noeuds[] de la structure parente.
        !           207: 
        !           208:            (*(*l_variable_courante).noeuds[(*s_etat_processus)
        !           209:                    .pointeurs_caracteres_variables[*ptr]]).noeud_pere =
        !           210:                    l_variable_courante;
        !           211:            (*(*l_variable_courante).noeuds[(*s_etat_processus)
        !           212:                    .pointeurs_caracteres_variables[*ptr]])
        !           213:                    .indice_tableau_pere = (*s_etat_processus)
        !           214:                    .pointeurs_caracteres_variables[*ptr];
        !           215: 
        !           216:            // Allocation du tableau noeuds[] et initialisation à zéro de
        !           217:            // tous les pointeurs.
        !           218: 
        !           219:            if (((*(*l_variable_courante).noeuds[(*s_etat_processus)
        !           220:                    .pointeurs_caracteres_variables[*ptr]]).noeuds =
        !           221:                    allocation_tableau_noeuds(s_etat_processus)) == NULL)
        !           222:            {
        !           223:                (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
        !           224:                return(d_erreur);
        !           225:            }
        !           226: 
        !           227:            for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
        !           228:            {
        !           229:                (*(*l_variable_courante).noeuds[(*s_etat_processus)
        !           230:                        .pointeurs_caracteres_variables[*ptr]]).noeuds[i]
        !           231:                        = NULL;
        !           232:            }
        !           233:        }
1.37      bertrand  234: 
                    235:        l_variable_courante = (*l_variable_courante).noeuds
                    236:                [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]];
                    237:        ptr++;
1.1       bertrand  238:    }
1.37      bertrand  239: 
                    240:    if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
                    241:            == NULL)
1.1       bertrand  242:    {
1.37      bertrand  243:        (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    244:        return(d_erreur);
1.1       bertrand  245:    }
                    246: 
1.37      bertrand  247:    // Dans la feuille statique de l'arbre des variables, on ne balaie
                    248:    // les variables que dans l'ordre. Le champ 'reference' est alors utilisé
                    249:    // pour sauvegarder une référence vers la liste des variables statiques
                    250:    // pour pouvoir purger l'élément en cas de besoin.
                    251: 
                    252:    (*l_nouvel_element).suivant = (*l_variable_courante).feuille_statique;
                    253:    (*l_nouvel_element).precedent = NULL;
1.38    ! bertrand  254: 
        !           255:    if ((*l_nouvel_element).suivant != NULL)
        !           256:    {
        !           257:        (*(*l_nouvel_element).suivant).precedent = l_nouvel_element;
        !           258:    }
1.37      bertrand  259: 
                    260:    (*l_nouvel_element).reference =
                    261:            (*s_etat_processus).l_liste_variables_statiques;
                    262:    (*l_nouvel_element).variable = (*(*s_etat_processus)
                    263:            .l_liste_variables_statiques).variable;
                    264:    (*l_variable_courante).feuille_statique = l_nouvel_element;
1.38    ! bertrand  265:    (*l_nouvel_element).feuille = l_variable_courante;
        !           266: 
1.37      bertrand  267:    return(d_absence_erreur);
1.1       bertrand  268: }
                    269: 
                    270: 
                    271: /*
                    272: ================================================================================
                    273:   Procédure de retrait d'une variable statique de la base
                    274: ================================================================================
                    275:   Entrée :
                    276: --------------------------------------------------------------------------------
                    277:   Sortie :
                    278: --------------------------------------------------------------------------------
                    279:   Effets de bord : néant
                    280: ================================================================================
                    281: */
                    282: 
                    283: logical1
                    284: retrait_variable_statique(struct_processus *s_etat_processus,
                    285:        unsigned char *nom_variable, union_position_variable position)
                    286: {
1.37      bertrand  287:    struct_liste_variables_statiques        *l_element_a_supprimer;
                    288:    struct_liste_variables_statiques        *l_element_liste_a_supprimer;
                    289: 
                    290:    logical1                                erreur;
                    291: 
1.38    ! bertrand  292: printf("<1>\n");
1.37      bertrand  293:    if ((l_element_a_supprimer = recherche_variable_statique(s_etat_processus,
                    294:            nom_variable, position, ((*s_etat_processus)
                    295:            .mode_execution_programme == 'Y') ? 'P' : 'E')) != NULL)
                    296:    {
1.38    ! bertrand  297: printf("<2>\n");
1.37      bertrand  298:        // (*s_etat_processus).pointeur_variable_statique_courante
                    299:        // pointe sur la variable à éliminer. Cette variable est celle qui
                    300:        // est présente dans l'une des feuilles statiques de l'arbre des
                    301:        // variables.
1.1       bertrand  302: 
1.37      bertrand  303:        l_element_liste_a_supprimer = (*l_element_a_supprimer).reference;
1.1       bertrand  304: 
1.37      bertrand  305:        // Suppression de la liste des variables statiques
1.1       bertrand  306: 
1.37      bertrand  307:        if ((*l_element_liste_a_supprimer).precedent != NULL)
                    308:        {
                    309:            (*(*l_element_liste_a_supprimer).precedent).suivant =
                    310:                    (*l_element_liste_a_supprimer).suivant;
                    311:        }
                    312:        else
1.1       bertrand  313:        {
1.38    ! bertrand  314:            if ((*l_element_liste_a_supprimer).suivant != NULL)
        !           315:            {
        !           316:                (*(*l_element_liste_a_supprimer).suivant).precedent = NULL;
        !           317:            }
        !           318: 
        !           319:            (*s_etat_processus).l_liste_variables_statiques =
        !           320:                    (*l_element_liste_a_supprimer).suivant;
1.37      bertrand  321:        }
1.1       bertrand  322: 
1.37      bertrand  323:        if ((*l_element_liste_a_supprimer).suivant != NULL)
                    324:        {
                    325:            (*(*l_element_liste_a_supprimer).suivant).precedent =
                    326:                    (*l_element_liste_a_supprimer).precedent;
                    327:        }
                    328:        else
                    329:        {
                    330:            (*(*l_element_liste_a_supprimer).precedent).suivant = NULL;
1.1       bertrand  331:        }
                    332: 
1.37      bertrand  333:        free(l_element_liste_a_supprimer);
1.1       bertrand  334: 
1.37      bertrand  335:        // Suppression depuis la feuille statique. Le champ 'precedent' ne sert
                    336:        // pas car la liste est simplement chaînée.
1.1       bertrand  337: 
1.37      bertrand  338:        if ((*l_element_a_supprimer).precedent != NULL)
                    339:        {
                    340:            (*(*l_element_a_supprimer).precedent).suivant =
                    341:                    (*l_element_a_supprimer).suivant;
                    342:        }
                    343:        else
                    344:        {
                    345:            (*(*l_element_a_supprimer).suivant).precedent = NULL;
1.38    ! bertrand  346:            (*(*l_element_a_supprimer).feuille).feuille_statique
        !           347:                    = (*l_element_a_supprimer).suivant;
1.37      bertrand  348:        }
1.1       bertrand  349: 
1.37      bertrand  350:        if ((*l_element_a_supprimer).suivant != NULL)
                    351:        {
                    352:            (*(*l_element_a_supprimer).suivant).precedent =
                    353:                    (*l_element_a_supprimer).precedent;
                    354:        }
                    355:        else
1.1       bertrand  356:        {
1.37      bertrand  357:            (*(*l_element_a_supprimer).precedent).suivant = NULL;
1.1       bertrand  358:        }
                    359: 
1.37      bertrand  360:        liberation(s_etat_processus, (*(*l_element_a_supprimer).variable)
                    361:                .objet);
                    362:        free((*(*l_element_a_supprimer).variable).nom);
                    363:        free((*l_element_a_supprimer).variable);
                    364:        free(l_element_a_supprimer);
                    365: 
1.1       bertrand  366:        erreur = d_absence_erreur;
                    367:    }
                    368:    else
                    369:    {
                    370:        erreur = d_erreur;
                    371:        (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
                    372:    }
                    373: 
                    374:    return erreur;
                    375: }
                    376: 
                    377: 
                    378: /*
                    379: ================================================================================
                    380:   Procédure de recherche d'une variable statique par son nom dans la base
                    381: ================================================================================
                    382:   Entrée :
                    383: --------------------------------------------------------------------------------
                    384:   Sortie :
                    385: --------------------------------------------------------------------------------
                    386:   Effets de bord : néant
                    387: ================================================================================
                    388: */
                    389: 
1.37      bertrand  390: struct_liste_variables_statiques *
1.1       bertrand  391: recherche_variable_statique(struct_processus *s_etat_processus,
                    392:        unsigned char *nom_variable, union_position_variable position,
                    393:        unsigned char origine)
                    394: {
1.37      bertrand  395:    int                                 pointeur;
1.1       bertrand  396: 
1.37      bertrand  397:    struct_arbre_variables              *l_variable_courante;
                    398:    struct_liste_variables_statiques    *l_element_courant;
1.1       bertrand  399: 
1.37      bertrand  400:    unsigned char                       *ptr;
1.1       bertrand  401: 
1.37      bertrand  402:    l_variable_courante = (*s_etat_processus).s_arbre_variables;
                    403:    ptr = nom_variable;
1.1       bertrand  404: 
1.37      bertrand  405:    while((*ptr) != d_code_fin_chaine)
1.1       bertrand  406:    {
1.37      bertrand  407:        pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr];
1.1       bertrand  408: 
1.37      bertrand  409:        if (pointeur < 0)
1.1       bertrand  410:        {
1.37      bertrand  411:            // Caractère hors de l'alphabet des variables
1.1       bertrand  412: 
1.37      bertrand  413:            (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
                    414:            return(NULL);
1.1       bertrand  415:        }
1.37      bertrand  416: 
                    417:        if ((*l_variable_courante).noeuds[pointeur] == NULL)
1.1       bertrand  418:        {
1.37      bertrand  419:            // Le chemin de la variable candidate n'existe pas.
                    420:            (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
                    421:            return(NULL);
1.1       bertrand  422:        }
                    423: 
1.37      bertrand  424:        l_variable_courante = (*l_variable_courante).noeuds[pointeur];
                    425:        ptr++;
1.1       bertrand  426:    }
1.37      bertrand  427: 
                    428:    if ((*l_variable_courante).feuille_statique != NULL)
1.1       bertrand  429:    {
1.37      bertrand  430:        // Il existe au moins une variable statique du nom requis.
1.1       bertrand  431: 
1.37      bertrand  432:        l_element_courant = (*l_variable_courante).feuille_statique;
1.1       bertrand  433: 
1.37      bertrand  434:        while(l_element_courant != NULL)
1.1       bertrand  435:        {
1.37      bertrand  436:            if ((*(*l_element_courant).variable).origine == 'P')
1.1       bertrand  437:            {
1.37      bertrand  438:                if (((*(*l_element_courant).variable).variable_statique.adresse
                    439:                        == position.adresse) &&
                    440:                        ((*(*l_element_courant).variable).origine == origine))
1.1       bertrand  441:                {
1.37      bertrand  442:                    (*s_etat_processus).pointeur_variable_statique_courante
1.38    ! bertrand  443:                            = (*l_element_courant).variable;
1.37      bertrand  444:                    return(l_element_courant);
1.1       bertrand  445:                }
                    446:            }
1.37      bertrand  447:            else
1.1       bertrand  448:            {
1.37      bertrand  449:                if (((*(*l_element_courant).variable).variable_statique.pointeur
                    450:                        == position.pointeur) &&
                    451:                        ((*(*l_element_courant).variable).origine == origine))
1.1       bertrand  452:                {
1.37      bertrand  453:                    (*s_etat_processus).pointeur_variable_statique_courante
1.38    ! bertrand  454:                            = (*l_element_courant).variable;
1.37      bertrand  455:                    return(l_element_courant);
1.1       bertrand  456:                }
                    457:            }
1.38    ! bertrand  458: 
        !           459:            l_element_courant = (*l_element_courant).suivant;
1.1       bertrand  460:        }
                    461:    }
                    462: 
1.37      bertrand  463:    (*s_etat_processus).pointeur_variable_statique_courante = NULL;
                    464:    return(NULL);
1.1       bertrand  465: }
                    466: 
                    467: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>