File:  [local] / rpl / src / gestion_pile_systeme.c
Revision 1.92: download - view: text, annotated - select for diffs - revision graph
Tue Jan 9 07:33:48 2024 UTC (3 months, 2 weeks ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_35, HEAD
Mise à jour du copyright.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.1.35
    4:   Copyright (C) 1989-2024 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:   Procédure d'estimation de la longueur du tampon
   29: ================================================================================
   30:   Entrée :
   31: --------------------------------------------------------------------------------
   32:   Sortie :
   33: --------------------------------------------------------------------------------
   34:   Effets de bord : néant
   35: ================================================================================
   36: */
   37: 
   38: static inline void
   39: estimation_taille_pile_systeme(struct_processus *s_etat_processus)
   40: {
   41:     (*s_etat_processus).estimation_taille_pile_systeme_tampon =
   42:             (((double) (*s_etat_processus)
   43:             .estimation_taille_pile_systeme_tampon) *
   44:             ((double) 0.9)) + (((double) (*s_etat_processus)
   45:             .hauteur_pile_systeme) * ((double) 0.1));
   46:     return;
   47: }
   48: 
   49: 
   50: /*
   51: ================================================================================
   52:   Procédure d'empilement d'un nouvel élément
   53: ================================================================================
   54:   Entrée :
   55: --------------------------------------------------------------------------------
   56:   Sortie :
   57: --------------------------------------------------------------------------------
   58:   Effets de bord : néant
   59: ================================================================================
   60: */
   61: 
   62: void
   63: empilement_pile_systeme(struct_processus *s_etat_processus)
   64: {
   65:     struct_liste_pile_systeme       *l_ancienne_base_liste;
   66:     struct_liste_pile_systeme       *l_nouvelle_base_liste;
   67: 
   68:     l_ancienne_base_liste = (*s_etat_processus).l_base_pile_systeme;
   69: 
   70:     if ((*s_etat_processus).debug == d_vrai)
   71:         if (((*s_etat_processus).type_debug &
   72:                 d_debug_pile_systeme) != 0)
   73:     {
   74:         if (strlen((*s_etat_processus).instruction_courante) != 0)
   75:         {
   76:             if ((*s_etat_processus).langue == 'F')
   77:             {
   78:                 printf("[%d] Empilement sur la pile système à la suite de "
   79:                         "l'instruction %s\n", (int) getpid(),
   80:                         (*s_etat_processus).instruction_courante);
   81:             }
   82:             else
   83:             {
   84:                 printf("[%d] Pushing on system stack (instruction %s)\n",
   85:                         (int) getpid(),
   86:                         (*s_etat_processus).instruction_courante);
   87:             }
   88:         }
   89:         else
   90:         {
   91:             if ((*s_etat_processus).langue == 'F')
   92:             {
   93:                 printf("[%d] Empilement sur la pile système\n",
   94:                         (int) getpid());
   95:             }
   96:             else
   97:             {
   98:                 printf("[%d] Pushing on system stack\n", (int) getpid());
   99:             }
  100:         }
  101: 
  102:         fflush(stdout);
  103:     }
  104: 
  105:     if ((*s_etat_processus).pile_systeme_tampon == NULL)
  106:     {
  107:         // Tampon vide, on alloue un élément.
  108: 
  109:         if ((l_nouvelle_base_liste = malloc(sizeof(struct_liste_pile_systeme)))
  110:                 == NULL)
  111:         {
  112:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  113:             return;
  114:         }
  115:     }
  116:     else
  117:     {
  118:         // Tampon utilisable, on retire un élément du tampon.
  119: 
  120:         l_nouvelle_base_liste = (*s_etat_processus).pile_systeme_tampon;
  121:         (*s_etat_processus).pile_systeme_tampon =
  122:                 (*l_nouvelle_base_liste).suivant;
  123:         (*s_etat_processus).taille_pile_systeme_tampon--;
  124:     }
  125: 
  126:     (*s_etat_processus).hauteur_pile_systeme++;
  127:     (*s_etat_processus).l_base_pile_systeme = l_nouvelle_base_liste;
  128:     (*(*s_etat_processus).l_base_pile_systeme).suivant =
  129:             l_ancienne_base_liste;
  130: 
  131:     (*(*s_etat_processus).l_base_pile_systeme).type_cloture = ' ';
  132:     (*(*s_etat_processus).l_base_pile_systeme).clause = ' ';
  133:     (*(*s_etat_processus).l_base_pile_systeme).adresse_retour = 0;
  134:     (*(*s_etat_processus).l_base_pile_systeme).niveau_courant =
  135:             (*s_etat_processus).niveau_courant;
  136:     (*(*s_etat_processus).l_base_pile_systeme).retour_definition = 'N';
  137:     (*(*s_etat_processus).l_base_pile_systeme).indice_boucle = NULL;
  138:     (*(*s_etat_processus).l_base_pile_systeme).limite_indice_boucle = NULL;
  139:     (*(*s_etat_processus).l_base_pile_systeme).objet_de_test = NULL;
  140:     (*(*s_etat_processus).l_base_pile_systeme).nom_variable = NULL;
  141:     (*(*s_etat_processus).l_base_pile_systeme).pointeur_objet_retour = NULL;
  142:     (*(*s_etat_processus).l_base_pile_systeme)
  143:             .origine_routine_evaluation = 'N';
  144:     (*(*s_etat_processus).l_base_pile_systeme).arret_si_exception =
  145:             (*s_etat_processus).arret_si_exception;
  146:     (*(*s_etat_processus).l_base_pile_systeme).creation_variables_statiques
  147:             = (*s_etat_processus).creation_variables_statiques;
  148:     (*(*s_etat_processus).l_base_pile_systeme).creation_variables_partagees
  149:             = (*s_etat_processus).creation_variables_partagees;
  150:     (*(*s_etat_processus).l_base_pile_systeme).evaluation_expression =
  151:             d_faux;
  152:     (*(*s_etat_processus).l_base_pile_systeme).debug_programme =
  153:             (*s_etat_processus).debug_programme;
  154: 
  155:     (*s_etat_processus).erreur_systeme = d_es;
  156:     (*s_etat_processus).creation_variables_statiques = d_faux;
  157:     (*s_etat_processus).creation_variables_partagees = d_faux;
  158:     (*s_etat_processus).debug_programme = d_faux;
  159: 
  160:     return;
  161: }
  162: 
  163: 
  164: /*
  165: ================================================================================
  166:   Procédure de dépilement d'un élément
  167: ================================================================================
  168:   Entrée :
  169: --------------------------------------------------------------------------------
  170:   Sortie :
  171: --------------------------------------------------------------------------------
  172:   Effets de bord : néant
  173: ================================================================================
  174: */
  175: 
  176: void
  177: depilement_pile_systeme(struct_processus *s_etat_processus)
  178: {
  179:     struct_liste_pile_systeme       *l_ancienne_base_liste;
  180:     struct_liste_pile_systeme       *l_nouvelle_base_liste;
  181: 
  182:     if ((*s_etat_processus).debug == d_vrai)
  183:         if (((*s_etat_processus).type_debug &
  184:                 d_debug_pile_systeme) != 0)
  185:     {
  186:         if (strlen((*s_etat_processus).instruction_courante) != 0)
  187:         {
  188:             if ((*s_etat_processus).langue == 'F')
  189:             {
  190:                 printf("[%d] Dépilement de la pile système à la suite "
  191:                         "de l'instruction %s\n", (int) getpid(),
  192:                         (*s_etat_processus).instruction_courante);
  193:             }
  194:             else
  195:             {
  196:                 printf("[%d] Pulling from system stack (instruction %s)\n",
  197:                         (int) getpid(),
  198:                         (*s_etat_processus).instruction_courante);
  199:             }
  200:         }
  201:         else
  202:         {
  203:             if ((*s_etat_processus).langue == 'F')
  204:             {
  205:                 printf("[%d] Dépilement de la pile système\n",
  206:                         (int) getpid());
  207:             }
  208:             else
  209:             {
  210:                 printf("[%d] Pulling from system stack\n", (int) getpid());
  211:             }
  212:         }
  213: 
  214:         fflush(stdout);
  215:     }
  216: 
  217:     if ((*s_etat_processus).l_base_pile_systeme == NULL)
  218:     {
  219:         (*s_etat_processus).erreur_systeme = d_es_pile_vide;
  220:     }
  221:     else
  222:     {
  223:         (*s_etat_processus).hauteur_pile_systeme--;
  224:         l_ancienne_base_liste = (*s_etat_processus).l_base_pile_systeme;
  225:         l_nouvelle_base_liste = (*l_ancienne_base_liste).suivant;
  226: 
  227:         (*s_etat_processus).l_base_pile_systeme = l_nouvelle_base_liste;
  228:         (*s_etat_processus).erreur_systeme = d_es;
  229:         (*s_etat_processus).debug_programme = (*l_ancienne_base_liste)
  230:                 .debug_programme;
  231: 
  232:         // On positionne le drapeau de création des variables statiques.
  233: 
  234:         (*s_etat_processus).creation_variables_statiques =
  235:                  (*l_ancienne_base_liste).creation_variables_statiques;
  236:         (*s_etat_processus).creation_variables_partagees =
  237:                  (*l_ancienne_base_liste).creation_variables_partagees;
  238: 
  239:         if ((*l_ancienne_base_liste).nom_variable != NULL)
  240:         {
  241:             free((*l_ancienne_base_liste).nom_variable);
  242:         }
  243: 
  244:         liberation(s_etat_processus, (*l_ancienne_base_liste).indice_boucle);
  245:         liberation(s_etat_processus,
  246:                 (*l_ancienne_base_liste).limite_indice_boucle);
  247:         liberation(s_etat_processus, (*l_ancienne_base_liste).objet_de_test);
  248: 
  249:         if ((*s_etat_processus).taille_pile_systeme_tampon <= (10 *
  250:                 ((*s_etat_processus).estimation_taille_pile_systeme_tampon
  251:                 + 1)))
  252:         {
  253:             // Enregistrement de la structure pour un usage ultérieur.
  254: 
  255:             (*l_ancienne_base_liste).suivant =
  256:                     (*s_etat_processus).pile_systeme_tampon;
  257:             (*s_etat_processus).pile_systeme_tampon = l_ancienne_base_liste;
  258:             (*s_etat_processus).taille_pile_systeme_tampon++;
  259:         }
  260:         else
  261:         {
  262:             // Libération car le tampon est plein.
  263: 
  264:             free(l_ancienne_base_liste);
  265:         }
  266:     }
  267: 
  268:     return;
  269: }
  270: 
  271: 
  272: /*
  273: ================================================================================
  274:   Procédure d'effacement de la pile système
  275: ================================================================================
  276:   Entrée :
  277: --------------------------------------------------------------------------------
  278:   Sortie :
  279: --------------------------------------------------------------------------------
  280:   Effets de bord : néant
  281: ================================================================================
  282: */
  283: 
  284: void
  285: effacement_pile_systeme(struct_processus *s_etat_processus)
  286: {
  287:     while((*s_etat_processus).l_base_pile_systeme != NULL)
  288:     {
  289:         depilement_pile_systeme(s_etat_processus);
  290:     }
  291: 
  292:     return;
  293: }
  294: 
  295: 
  296: /*
  297: ================================================================================
  298:   Procédure d'affichage de la pile système
  299: ================================================================================
  300:   Entrée :
  301: --------------------------------------------------------------------------------
  302:   Sortie :
  303: --------------------------------------------------------------------------------
  304:   Effets de bord : néant
  305: ================================================================================
  306: */
  307: 
  308: void
  309: trace(struct_processus *s_etat_processus, FILE *flux)
  310: {
  311:     integer8                        i;
  312:     integer8                        j;
  313:     integer8                        candidat;
  314:     integer8                        candidat8;
  315:     integer8                        delta;
  316:     integer8                        nb_variables;
  317: 
  318:     struct_liste_chainee            *l_element_expression;
  319: 
  320:     struct_liste_pile_systeme       *l_element_courant;
  321: 
  322:     struct_tableau_variables        *tableau;
  323: 
  324:     unsigned char                   *tampon;
  325: 
  326:     l_element_courant = (*s_etat_processus).l_base_pile_systeme;
  327:     i = 0;
  328: 
  329:     while(l_element_courant != NULL)
  330:     {
  331:         i++;
  332:         l_element_courant = (*l_element_courant).suivant;
  333:     }
  334: 
  335:     l_element_courant = (*s_etat_processus).l_base_pile_systeme;
  336:     flockfile(flux);
  337: 
  338:     nb_variables = nombre_variables(s_etat_processus);
  339: 
  340:     if ((tableau = malloc(((size_t) nb_variables) *
  341:             sizeof(struct_tableau_variables))) == NULL)
  342:     {
  343:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  344:         return;
  345:     }
  346: 
  347:     liste_variables(s_etat_processus, tableau);
  348: 
  349:     if ((flux == stderr) || (flux == stdout))
  350:     {
  351:         fprintf(flux, "+++Backtrace\n");
  352:     }
  353: 
  354:     while(l_element_courant != NULL)
  355:     {
  356:         fprintf(flux, "%lld : address # %016Xh\n", i--, l_element_courant);
  357: 
  358:         if ((*l_element_courant).creation_variables_statiques == d_vrai)
  359:         {
  360:             fprintf(flux, "    Variables         = static\n");
  361:         }
  362:         else if ((*l_element_courant).creation_variables_partagees == d_vrai)
  363:         {
  364:             fprintf(flux, "    Variables         = shared\n");
  365:         }
  366:         else
  367:         {
  368:             fprintf(flux, "    Variables         = automatic\n");
  369:         }
  370: 
  371:         if ((*l_element_courant).arret_si_exception == d_vrai)
  372:         {
  373:             fprintf(flux, "    In exception      = abort\n");
  374:         }
  375:         else
  376:         {
  377:             fprintf(flux, "    In exception      = catch\n");
  378:         }
  379: 
  380:         if ((*l_element_courant).clause != ' ')
  381:         {
  382:             fprintf(flux, "    Structure         = ");
  383: 
  384:             switch((*l_element_courant).clause)
  385:             {
  386:                 case 'I':
  387:                     fprintf(flux, "IF\n");
  388:                     break;
  389: 
  390:                 case 'R':
  391:                     fprintf(flux, "IFERR\n");
  392:                     break;
  393: 
  394:                 case 'X':
  395:                     fprintf(flux, "exception caught by IFERR\n");
  396:                     break;
  397: 
  398:                 case 'T':
  399:                     fprintf(flux, "THEN\n");
  400:                     break;
  401:                 
  402:                 case 'E':
  403:                     fprintf(flux, "ELSE\n");
  404:                     break;
  405: 
  406:                 case 'Z':
  407:                     fprintf(flux, "ELSE (false condition)\n");
  408:                     break;
  409: 
  410:                 case 'D':
  411:                     fprintf(flux, "DO\n");
  412:                     break;
  413: 
  414:                 case 'U':
  415:                     fprintf(flux, "UNTIL\n");
  416:                     break;
  417: 
  418:                 case 'W':
  419:                     fprintf(flux, "WHILE\n");
  420:                     break;
  421: 
  422:                 case 'M':
  423:                     fprintf(flux, "WHILE (false condition)\n");
  424:                     break;
  425: 
  426:                 case 'S':
  427:                     fprintf(flux, "SELECT\n");
  428:                     break;
  429: 
  430:                 case 'K':
  431:                     fprintf(flux, "CASE (no true condition)\n");
  432:                     break;
  433: 
  434:                 case 'C':
  435:                     fprintf(flux, "CASE (one or more true conditions)\n");
  436:                     break;
  437: 
  438:                 case 'Q':
  439:                     fprintf(flux, "CASE (treatment of a true condition)\n");
  440:                     break;
  441: 
  442:                 case 'F':
  443:                     fprintf(flux, "CASE (treatment of default case)\n");
  444:                     break;
  445:             }
  446:         }
  447: 
  448:         if ((*l_element_courant).type_cloture != ' ')
  449:         {
  450:             fprintf(flux, "    Next close        = ");
  451: 
  452:             switch((*l_element_courant).type_cloture)
  453:             {
  454:                 case 'C':
  455:                     fprintf(flux, "SELECT\n");
  456:                     break;
  457: 
  458:                 case 'D':
  459:                     fprintf(flux, "DO\n");
  460:                     break;
  461: 
  462:                 case 'I':
  463:                     fprintf(flux, "IF\n");
  464:                     break;
  465: 
  466:                 case 'J':
  467:                     fprintf(flux, "IFERR\n");
  468:                     break;
  469: 
  470:                 case 'K':
  471:                     fprintf(flux, "CASE\n");
  472:                     break;
  473: 
  474:                 case 'W':
  475:                     fprintf(flux, "WHILE\n");
  476:                     break;
  477: 
  478:                 case 'Q':
  479:                     fprintf(flux, "CRITICAL\n");
  480:                     break;
  481: 
  482:                 case 'F':
  483:                     fprintf(flux, "FOR\n");
  484:                     break;
  485: 
  486:                 case 'S':
  487:                     fprintf(flux, "START\n");
  488:                     break;
  489: 
  490:                 case 'L':
  491:                     fprintf(flux, "internal loop\n");
  492:                     break;
  493: 
  494:                 case 'A':
  495:                     fprintf(flux, "FORALL\n");
  496:                     break;
  497:             }
  498:         }
  499: 
  500:         fprintf(flux, "    Level             = %lld\n",
  501:                 (long long int) (*l_element_courant).niveau_courant);
  502: 
  503:         if ((*l_element_courant).retour_definition == 'Y')
  504:         {
  505:             fprintf(flux, "    Return            = yes\n");
  506: 
  507:             if ((*l_element_courant).origine_routine_evaluation == 'Y')
  508:             {
  509:                 if ((*l_element_courant).pointeur_objet_retour != NULL)
  510:                 {
  511:                     fprintf(flux, "    Come from         = compiled code ");
  512:                     fprintf(flux, "(address # %016Xh)\n", (*l_element_courant)
  513:                             .pointeur_objet_retour);
  514: 
  515:                     // Calcul de la routine de départ
  516: 
  517:                     candidat = -1;
  518: 
  519:                     for(j = 0; j < nb_variables; j++)
  520:                     {
  521:                         if (tableau[j].objet != NULL)
  522:                         {
  523:                             // Variable ni partagée ni statique
  524:                             if (((*(tableau[j].objet)).type == RPN) ||
  525:                                     ((*(tableau[j].objet)).type == ALG))
  526:                             {
  527:                                 l_element_expression =
  528:                                         (*(tableau[j].objet)).objet;
  529: 
  530:                                 while(l_element_expression != NULL)
  531:                                 {
  532:                                     if (l_element_expression ==
  533:                                             (*l_element_courant)
  534:                                             .pointeur_objet_retour)
  535:                                     {
  536:                                         candidat = j;
  537:                                         break;
  538:                                     }
  539: 
  540:                                     l_element_expression =
  541:                                             (*l_element_expression).suivant;
  542:                                 }
  543: 
  544:                                 if (candidat != -1)
  545:                                 {
  546:                                     break;
  547:                                 }
  548:                             }
  549:                         }
  550:                     }
  551: 
  552:                     if (candidat != -1)
  553:                     {
  554:                         fprintf(flux, "                      = %s [",
  555:                                 tableau[candidat].nom);
  556:                        
  557:                         if ((*(tableau[candidat].objet)).type == RPN)
  558:                         {
  559:                             fprintf(flux, "definition");
  560:                         }
  561:                         else if ((*(tableau[candidat].objet)).type == ALG)
  562:                         {
  563:                             fprintf(flux, "algebraic");
  564:                         }
  565:                         else if ((*(tableau[candidat].objet)).type == NOM)
  566:                         {
  567:                             fprintf(flux, "name");
  568:                         }
  569:                         else
  570:                         {
  571:                             fprintf(flux, "unknown");
  572:                         }
  573: 
  574:                         fprintf(flux, "]\n");
  575:                     }
  576:                     else
  577:                     {
  578:                         fprintf(flux, "                      = "
  579:                                 "optimized definition\n");
  580:                     }
  581:                 }
  582:                 else
  583:                 {
  584:                     fprintf(flux, "    Come from         = compiled code\n");
  585:                     fprintf(flux, "                      = "
  586:                             "optimized definition\n");
  587:                 }
  588:             }
  589:             else
  590:             {
  591:                 fprintf(flux, "    Come from         = interpreted code ");
  592: 
  593:                 if ((*l_element_courant).adresse_retour != 0)
  594:                 {
  595:                     fprintf(flux, "(offset # %016Xh)\n", (*l_element_courant)
  596:                             .adresse_retour);
  597: 
  598:                     // Calcul de la routine de départ
  599: 
  600:                     candidat8 = (*s_etat_processus)
  601:                             .longueur_definitions_chainees;
  602:                     candidat = -1;
  603: 
  604:                     for(j = 0; j < nb_variables; j++)
  605:                     {
  606:                         if ((*(tableau[j].objet)).type == ADR)
  607:                         {
  608:                             delta = (*l_element_courant).adresse_retour
  609:                                     - (*((integer8 *)
  610:                                     (*(tableau[j].objet)).objet));
  611: 
  612:                             if ((delta >= 0) && (delta < candidat8))
  613:                             {
  614:                                 candidat8 = delta;
  615:                                 candidat = j;
  616:                             }
  617:                         }
  618:                     }
  619: 
  620:                     if (candidat != -1)
  621:                     {
  622:                         fprintf(flux, "                      = %s\n",
  623:                                 tableau[candidat].nom);
  624:                     }
  625:                     else
  626:                     {
  627:                         fprintf(flux, "                      = "
  628:                                 "unknown definition\n");
  629:                     }
  630:                 }
  631:                 else if ((*l_element_courant).niveau_courant == 0)
  632:                 {
  633:                     fprintf(flux, "\n");
  634:                     fprintf(flux, "                      = RPL/2 "
  635:                             "initialization\n");
  636:                 }
  637:                 else
  638:                 {
  639:                     fprintf(flux, "\n");
  640:                 }
  641:             }
  642:         }
  643:         else
  644:         {
  645:             fprintf(flux, "    Return            = no\n");
  646:         }
  647: 
  648:         if (((*l_element_courant).indice_boucle != NULL) &&
  649:                 ((*l_element_courant).type_cloture != 'A'))
  650:         {
  651:             tampon = formateur(s_etat_processus, 24,
  652:                     (*l_element_courant).indice_boucle);
  653:             fprintf(flux, "    Index             = %s\n", tampon);
  654:             free(tampon);
  655:         }
  656: 
  657:         if ((*l_element_courant).limite_indice_boucle != NULL)
  658:         {
  659:             tampon = formateur(s_etat_processus, 24,
  660:                     (*l_element_courant).limite_indice_boucle);
  661:             fprintf(flux, "    Limit             = %s\n", tampon);
  662:             free(tampon);
  663:         }
  664: 
  665:         if ((*l_element_courant).objet_de_test != NULL)
  666:         {
  667:             tampon = formateur(s_etat_processus, 24,
  668:                     (*l_element_courant).objet_de_test);
  669:             fprintf(flux, "    Test object       = %s\n", tampon);
  670:             free(tampon);
  671:         }
  672: 
  673:         if ((*l_element_courant).nom_variable != NULL)
  674:         {
  675:             fprintf(flux, "    Variable name     = %s\n",
  676:                     (*l_element_courant).nom_variable);
  677:         }
  678: 
  679:         fprintf(flux, "\n");
  680: 
  681:         l_element_courant = (*l_element_courant).suivant;
  682:     }
  683: 
  684:     funlockfile(flux);
  685: 
  686:     free(tableau);
  687: 
  688:     return;
  689: }
  690: 
  691: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>