File:  [local] / rpl / src / gestion_variables.c
Revision 1.7: download - view: text, annotated - select for diffs - revision graph
Wed Apr 21 13:45:45 2010 UTC (14 years ago) by bertrand
Branches: MAIN
CVS tags: HEAD
En route pour la 4.0.15 !

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

CVSweb interface <joel.bertrand@systella.fr>