File:  [local] / rpl / src / interface_cas.cpp
Revision 1.13: download - view: text, annotated - select for diffs - revision graph
Sat Aug 6 10:32:12 2011 UTC (12 years, 8 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Correction des bugs de gpp.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.1.2
    4:   Copyright (C) 1989-2011 Dr. BERTRAND Joël
    5: 
    6:   This file is part of RPL/2.
    7: 
    8:   RPL/2 is free software; you can redistribute it and/or modify it
    9:   under the terms of the CeCILL V2 License as published by the french
   10:   CEA, CNRS and INRIA.
   11:  
   12:   RPL/2 is distributed in the hope that it will be useful, but WITHOUT
   13:   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14:   FITNESS FOR A PARTICULAR PURPOSE.  See the CeCILL V2 License
   15:   for more details.
   16:  
   17:   You should have received a copy of the CeCILL License
   18:   along with RPL/2. If not, write to info@cecill.info.
   19: ================================================================================
   20: */
   21: 
   22: 
   23: #ifdef RPLCAS
   24: #   include "giac.h"
   25: 
   26: #   undef PACKAGE
   27: #   undef PACKAGE_NAME
   28: #   undef PACKAGE_STRING
   29: #   undef PACKAGE_TARNAME
   30: #   undef PACKAGE_VERSION
   31: #   undef VERSION
   32: #endif
   33: 
   34: extern "C"
   35: {
   36: #   define __RPLCAS
   37: #   include "rpl-conv.h"
   38: }
   39: 
   40: #include <iostream>
   41: 
   42: using namespace std;
   43: 
   44: #ifdef RPLCAS
   45:     using namespace giac;
   46: #endif
   47: 
   48: 
   49: static unsigned char *
   50: conversion_rpl_vers_cas(struct_processus *s_etat_processus,
   51:         struct_objet **s_objet)
   52: {
   53:     logical1                drapeau;
   54: 
   55:     struct_liste_chainee    *l_element_courant;
   56:     struct_liste_chainee    *l_element_precedent;
   57: 
   58:     struct_objet            *s_objet_temporaire;
   59: 
   60:     t_8_bits                registre[8];
   61: 
   62:     unsigned char           *resultat;
   63:     unsigned char           *index;
   64: 
   65:     for(int i = 0; i < 8; i++)
   66:     {
   67:         registre[i] = s_etat_processus->drapeaux_etat[i];
   68:     }
   69: 
   70:     sf(s_etat_processus, 35);
   71:     cf(s_etat_processus, 48);
   72:     cf(s_etat_processus, 49);
   73:     cf(s_etat_processus, 50);
   74:     cf(s_etat_processus, 53);
   75:     cf(s_etat_processus, 54);
   76:     cf(s_etat_processus, 55);
   77:     cf(s_etat_processus, 56);
   78: 
   79:     // GIAC considère que les fonctions sont écrites en minuscules. Le RPL/2
   80:     // part de l'hypothèse inverse. Il faut donc convertir en minuscules tous
   81:     // les noms de fonction. Les fonctions ne peuvent apparaître que dans le
   82:     // cas d'un objet de type ALG.
   83: 
   84:     if ((*s_objet)->type == NOM)
   85:     {
   86:         if (strcmp((const char *) reinterpret_cast<unsigned char *>(
   87:                 reinterpret_cast<struct_nom *>((*s_objet)->objet)->nom),
   88:                 "infinity") == 0)
   89:         {
   90:             if (evaluation(s_etat_processus, *s_objet, 'N') == d_erreur)
   91:             {
   92:                 return(NULL);
   93:             }
   94: 
   95:             liberation(s_etat_processus, *s_objet);
   96: 
   97:             if (depilement(s_etat_processus, &(s_etat_processus
   98:                     ->l_base_pile), s_objet) == d_erreur)
   99:             {
  100:                 return(NULL);
  101:             }
  102:         }
  103:     }
  104:     else if ((*s_objet)->type == ALG)
  105:     {
  106:         if ((s_objet_temporaire = copie_objet(s_etat_processus,
  107:                 (*s_objet), 'O')) == NULL)
  108:         {
  109:             s_etat_processus->erreur_systeme = d_es_allocation_memoire;
  110:             return(NULL);
  111:         }
  112: 
  113:         liberation(s_etat_processus, (*s_objet));
  114:         (*s_objet) = s_objet_temporaire;
  115: 
  116:         // Si l'expression contient la fonction infinity, on commence par
  117:         // forcer une évaluation numérique.
  118: 
  119:         l_element_courant = reinterpret_cast<struct_liste_chainee *>(
  120:                 (*s_objet)->objet);
  121:         drapeau = d_faux;
  122: 
  123:         while(l_element_courant != NULL)
  124:         {
  125:             if (l_element_courant->donnee->type == NOM)
  126:             {
  127:                 if (strcmp((const char *) reinterpret_cast<unsigned char *>(
  128:                         reinterpret_cast<struct_nom *>(
  129:                         l_element_courant->donnee->objet)->nom),
  130:                         "infinity") == 0)
  131:                 {
  132:                     drapeau = d_vrai;
  133:                     break;
  134:                 }
  135:             }
  136: 
  137:             l_element_courant = l_element_courant->suivant;
  138:         }
  139: 
  140:         if (drapeau == d_vrai)
  141:         {
  142:             if (evaluation(s_etat_processus, *s_objet, 'N') == d_erreur)
  143:             {
  144:                 return(NULL);
  145:             }
  146: 
  147:             liberation(s_etat_processus, *s_objet);
  148: 
  149:             if (depilement(s_etat_processus, &(s_etat_processus
  150:                     ->l_base_pile), s_objet) == d_erreur)
  151:             {
  152:                 return(NULL);
  153:             }
  154:         }
  155:     }
  156: 
  157:     if ((*s_objet)->type == ALG)
  158:     {
  159: 
  160:         l_element_courant = reinterpret_cast<struct_liste_chainee *>(
  161:                 (*s_objet)->objet);
  162: 
  163:         while(l_element_courant != NULL)
  164:         {
  165:             if (l_element_courant->donnee->type == FCT)
  166:             {
  167:                 unsigned char       *ptr;
  168: 
  169:                 ptr = reinterpret_cast<unsigned char *>(
  170:                         reinterpret_cast<struct_fonction *>(
  171:                         l_element_courant->donnee->objet)->nom_fonction);
  172: 
  173:                 while((*ptr) != d_code_fin_chaine)
  174:                 {
  175:                     int c = (*ptr);
  176: 
  177:                     if (isalpha(c))
  178:                     {
  179:                         c = tolower(c);
  180:                         (*ptr) = (unsigned char) c;
  181:                     }
  182: 
  183:                     ptr++;
  184:                 }
  185:             }
  186: 
  187:             l_element_precedent = l_element_courant;
  188:             l_element_courant = l_element_courant->suivant;
  189:         }
  190:     }
  191: 
  192:     resultat = formateur(s_etat_processus, 0, (*s_objet));
  193: 
  194:     // Il faut remplacer les occurrences de 'relax' par '    +'.
  195: 
  196:     index = resultat;
  197:     while((index = reinterpret_cast<unsigned char *>(
  198:             strstr(reinterpret_cast<char *>(index),
  199:             (const char *) "relax"))) != NULL)
  200:     {
  201:         strncpy(reinterpret_cast<char *>(index), "    +", 5);
  202:     }
  203: 
  204:     // Si le résultat vaut infinity, on rajoute le signe +.
  205: 
  206:     if (strcmp(reinterpret_cast<char *>(resultat), "infinity") == 0)
  207:     {
  208:         if ((resultat = reinterpret_cast<unsigned char *>(
  209:                 realloc(resultat, (strlen(reinterpret_cast<char *>(
  210:                 resultat)) + 2) * sizeof(unsigned char)))) == NULL)
  211:         {
  212:             s_etat_processus->erreur_systeme = d_es_allocation_memoire;
  213:             return(NULL);
  214:         }
  215: 
  216:         strcpy(reinterpret_cast<char *>(resultat), "+infinity");
  217:     }
  218: 
  219:     if (resultat[0] == '\'')
  220:     {
  221:         resultat[0] = ' ';
  222:         resultat[strlen((const char *) resultat) - 1] = ' ';
  223:     }
  224: 
  225:     for(int i = 0; i < 8; i++)
  226:     {
  227:         s_etat_processus->drapeaux_etat[i] = registre[i];
  228:     }
  229: 
  230:     return(resultat);
  231: }
  232: 
  233: 
  234: static void
  235: conversion_cas_vers_rpl(struct_processus *s_etat_processus,
  236:         unsigned char *expression)
  237: {
  238:     logical1                    drapeau;
  239: 
  240:     struct_liste_chainee        *l_element_courant;
  241:     struct_liste_chainee        *l_element_precedent;
  242: 
  243:     struct_objet                *s_objet;
  244: 
  245:     unsigned char               *registre;
  246: 
  247:     registre = s_etat_processus->instruction_courante;
  248:     s_etat_processus->instruction_courante = expression;
  249:     recherche_type(s_etat_processus);
  250:     s_etat_processus->instruction_courante = registre;
  251: 
  252:     if ((s_etat_processus->l_base_pile == NULL) ||
  253:             (s_etat_processus->erreur_execution != d_ex) ||
  254:             (s_etat_processus->erreur_systeme != d_es))
  255:     {
  256:         return;
  257:     }
  258: 
  259:     // Le niveau 1 de la pile opérationnelle contient l'expression
  260:     // à convertir.
  261: 
  262:     if (depilement(s_etat_processus, &(s_etat_processus
  263:             ->l_base_pile), &s_objet) == d_erreur)
  264:     {
  265:         return;
  266:     }
  267: 
  268:     if ((s_objet->type == ALG) || (s_objet->type == RPN))
  269:     {
  270:         // On transcrit les fonctions de GIAC vers le RPL/2.
  271: 
  272:         l_element_courant = reinterpret_cast<struct_liste_chainee *>(
  273:                 s_objet->objet);
  274:         drapeau = d_faux;
  275: 
  276:         // S'il y a une valeur infini, on force l'évaluation de l'expression.
  277: 
  278:         while(l_element_courant != NULL)
  279:         {
  280:             if (l_element_courant->donnee->type == NOM)
  281:             {
  282:                 if (strcmp((const char *) reinterpret_cast<unsigned char *>(
  283:                         reinterpret_cast<struct_nom *>(
  284:                         l_element_courant->donnee->objet)->nom),
  285:                         "infinity") == 0)
  286:                 {
  287:                     drapeau = d_vrai;
  288:                     break;
  289:                 }
  290:             }
  291: 
  292:             l_element_courant = l_element_courant->suivant;
  293:         }
  294: 
  295:         if (drapeau == d_vrai)
  296:         {
  297:             if (evaluation(s_etat_processus, s_objet, 'N') == d_erreur)
  298:             {
  299:                 return;
  300:             }
  301: 
  302:             liberation(s_etat_processus, s_objet);
  303: 
  304:             if (depilement(s_etat_processus, &(s_etat_processus
  305:                     ->l_base_pile), &s_objet) == d_erreur)
  306:             {
  307:                 return;
  308:             }
  309:         }
  310:     }
  311: 
  312:     if ((s_objet->type == ALG) || (s_objet->type == RPN))
  313:     {
  314:         l_element_precedent = NULL;
  315:         l_element_courant = reinterpret_cast<struct_liste_chainee *>(
  316:                 s_objet->objet);
  317: 
  318:         while(l_element_courant != NULL)
  319:         {
  320:             if (l_element_courant->donnee->type == FCT)
  321:             {
  322:                 // Nous sommes en présence d'un nom, donc de quelque chose
  323:                 // qui n'est pas reconnu comme un mot-clef du RPL/2. S'il
  324:                 // s'agit d'un mot-clef de GIAC, on le convertit.
  325: 
  326:                 if ((strcmp((const char *)
  327:                         reinterpret_cast<struct_fonction *>(l_element_courant
  328:                         ->donnee->objet)->nom_fonction, "quote") == 0) ||
  329:                         (strcmp((const char *)
  330:                         reinterpret_cast<struct_fonction *>(l_element_courant
  331:                         ->donnee->objet)->nom_fonction, "nop") == 0))
  332:                 {
  333:                     liberation(s_etat_processus, l_element_courant->donnee);
  334: 
  335:                     if ((l_element_courant->donnee =
  336:                             allocation(s_etat_processus, FCT)) == NULL)
  337:                     {
  338:                         s_etat_processus->erreur_systeme =
  339:                                 d_es_allocation_memoire;
  340:                         return;
  341:                     }
  342: 
  343:                     if ((((struct_fonction *) l_element_courant->donnee->objet)
  344:                             ->nom_fonction = reinterpret_cast<unsigned char *>(
  345:                             malloc(6 * sizeof(unsigned char))))
  346:                             == NULL)
  347:                     {
  348:                         s_etat_processus->erreur_systeme =
  349:                                 d_es_allocation_memoire;
  350:                         return;
  351:                     }
  352: 
  353:                     strcpy(reinterpret_cast<char *>(
  354:                             reinterpret_cast<struct_fonction *>(
  355:                             l_element_courant->donnee->objet)->nom_fonction),
  356:                             "RELAX");
  357:                 }
  358:             }
  359: 
  360:             l_element_precedent = l_element_courant;
  361:             l_element_courant = l_element_courant->suivant;
  362:         }
  363:     }
  364: 
  365:     if (empilement(s_etat_processus, &(s_etat_processus->l_base_pile),
  366:             s_objet) == d_erreur)
  367:     {
  368:         return;
  369:     }
  370: 
  371:     return;
  372: }
  373: 
  374: 
  375: /*
  376: ================================================================================
  377:   Fonction 'interface_cas'
  378: ================================================================================
  379:   Entrées : commande à effectuer.
  380:   Le contrôle des types est effectué dans la fonction appelant interface_cas().
  381: --------------------------------------------------------------------------------
  382:   Sorties : retour par la pile.
  383: --------------------------------------------------------------------------------
  384:   Effets de bord : néant
  385: ================================================================================
  386: */
  387: 
  388: void
  389: interface_cas(struct_processus *s_etat_processus,
  390:         enum t_rplcas_commandes commande)
  391: {
  392: #   ifdef RPLCAS
  393:     struct_objet            *s_objet_argument_1;
  394:     struct_objet            *s_objet_argument_2;
  395:     struct_objet            *s_objet_temporaire;
  396: 
  397:     struct_liste_chainee    *l_element_courant;
  398: 
  399:     unsigned char           *argument_1;
  400:     unsigned char           *argument_2;
  401:     unsigned char           *argument_3;
  402:     unsigned char           *argument_4;
  403: 
  404:     unsigned int            position;
  405: 
  406:     switch(commande)
  407:     {
  408:         case RPLCAS_INTEGRATION:
  409:         {
  410:             if (depilement(s_etat_processus, &(s_etat_processus->l_base_pile),
  411:                     &s_objet_argument_1) == d_erreur)
  412:             {
  413:                 s_etat_processus->erreur_execution = d_ex_manque_argument;
  414:                 return;
  415:             }
  416: 
  417:             if (depilement(s_etat_processus, &(s_etat_processus->l_base_pile),
  418:                     &s_objet_argument_2) == d_erreur)
  419:             {
  420:                 liberation(s_etat_processus, s_objet_argument_1);
  421:                 s_etat_processus->erreur_execution = d_ex_manque_argument;
  422:                 return;
  423:             }
  424: 
  425:             if ((argument_1 = conversion_rpl_vers_cas(s_etat_processus,
  426:                     &s_objet_argument_1)) == NULL)
  427:             {
  428:                 s_etat_processus->erreur_systeme = d_es_allocation_memoire;
  429:                 return;
  430:             }
  431: 
  432:             if ((argument_2 = conversion_rpl_vers_cas(s_etat_processus,
  433:                     &s_objet_argument_2)) == NULL)
  434:             {
  435:                 s_etat_processus->erreur_systeme = d_es_allocation_memoire;
  436:                 return;
  437:             }
  438: 
  439:             liberation(s_etat_processus, s_objet_argument_1);
  440:             liberation(s_etat_processus, s_objet_argument_2);
  441: 
  442:             try
  443:             {
  444:                 giac::context   contexte;
  445: 
  446:                 gen variable(
  447:                         string(reinterpret_cast<const char *>(argument_1)),
  448:                         &contexte);
  449:                 gen expression(
  450:                         string(reinterpret_cast<const char *>(argument_2)),
  451:                         &contexte);
  452: 
  453:                 gen resultat = integrate_gen(expression, variable, &contexte);
  454:                 string chaine = "'" + resultat.print() + "'";
  455: 
  456:                 conversion_cas_vers_rpl(s_etat_processus,
  457:                         reinterpret_cast<unsigned char *>(const_cast<char *>(
  458:                         chaine.c_str())));
  459:             }
  460:             catch(bad_alloc exception)
  461:             {
  462:                 s_etat_processus->erreur_systeme = d_es_allocation_memoire;
  463:             }
  464:             catch(...)
  465:             {
  466:                 s_etat_processus->erreur_execution = d_ex_erreur_interne_rplcas;
  467:             }
  468: 
  469:             free(argument_1);
  470:             free(argument_2);
  471: 
  472:             break;
  473:         }
  474: 
  475:         case RPLCAS_LIMITE:
  476:         {
  477:             if (depilement(s_etat_processus, &(s_etat_processus->l_base_pile),
  478:                     &s_objet_argument_1) == d_erreur)
  479:             {
  480:                 s_etat_processus->erreur_execution = d_ex_manque_argument;
  481:                 return;
  482:             }
  483: 
  484:             if (depilement(s_etat_processus, &(s_etat_processus->l_base_pile),
  485:                     &s_objet_argument_2) == d_erreur)
  486:             {
  487:                 liberation(s_etat_processus, s_objet_argument_1);
  488:                 s_etat_processus->erreur_execution = d_ex_manque_argument;
  489:                 return;
  490:             }
  491: 
  492:             // Fonction
  493: 
  494:             if ((argument_2 = conversion_rpl_vers_cas(s_etat_processus,
  495:                     &s_objet_argument_2)) == NULL)
  496:             {
  497:                 s_etat_processus->erreur_systeme = d_es_allocation_memoire;
  498:                 return;
  499:             }
  500: 
  501:             // On parcourt la liste. Cette liste est tout d'abord copiée
  502:             // car on est susceptible de modifier le second élément.
  503: 
  504:             if ((s_objet_temporaire = copie_objet(s_etat_processus,
  505:                     s_objet_argument_1, 'O')) == NULL)
  506:             {
  507:                 s_etat_processus->erreur_systeme = d_es_allocation_memoire;
  508:                 return;
  509:             }
  510: 
  511:             liberation(s_etat_processus, s_objet_argument_1);
  512:             s_objet_argument_1 = s_objet_temporaire;
  513: 
  514:             l_element_courant = reinterpret_cast<struct_liste_chainee *>
  515:                     (s_objet_argument_1->objet);
  516:             position = 1;
  517:             argument_4 = NULL;
  518: 
  519:             while(l_element_courant != NULL)
  520:             {
  521:                 switch(position)
  522:                 {
  523:                     case 1:
  524:                     {
  525:                         // Variable
  526: 
  527:                         if ((argument_1 = reinterpret_cast<unsigned char *>
  528:                                 (malloc((strlen((const char *)
  529:                                 ((struct_variable *) (l_element_courant
  530:                                 ->donnee->objet))->nom)
  531:                                 + 1) * sizeof(unsigned char)))) == NULL)
  532:                         {
  533:                             s_etat_processus->erreur_systeme =
  534:                                     d_es_allocation_memoire;
  535:                             return;
  536:                         }
  537: 
  538:                         strcpy(reinterpret_cast<char *>(argument_1),
  539:                                 (const char *) ((struct_variable *)
  540:                                 (l_element_courant->donnee->objet))->nom);
  541:                         break;
  542:                     }
  543: 
  544:                     case 2:
  545:                     {
  546:                         // Valeur
  547:                         if ((argument_3 = conversion_rpl_vers_cas(
  548:                                 s_etat_processus,
  549:                                 &(l_element_courant->donnee))) == NULL)
  550:                         {
  551:                             s_etat_processus->erreur_systeme =
  552:                                     d_es_allocation_memoire;
  553:                             return;
  554:                         }
  555: 
  556:                         break;
  557:                     }
  558: 
  559:                     case 3:
  560:                     {
  561:                         // Direction
  562: 
  563:                         if ((argument_4 = reinterpret_cast<unsigned char *>
  564:                                 (malloc((strlen((const char *)
  565:                                 ((struct_fonction *) (l_element_courant
  566:                                 ->donnee->objet))->nom_fonction)
  567:                                 + 1) * sizeof(unsigned char)))) == NULL)
  568:                         {
  569:                             s_etat_processus->erreur_systeme =
  570:                                     d_es_allocation_memoire;
  571:                             return;
  572:                         }
  573: 
  574:                         strcpy(reinterpret_cast<char *>(argument_4),
  575:                                 (const char *) ((struct_fonction *)
  576:                                 (l_element_courant->donnee->objet))
  577:                                 ->nom_fonction);
  578:                         break;
  579:                     }
  580:                 }
  581: 
  582:                 l_element_courant = (*l_element_courant).suivant;
  583:                 position++;
  584:             }
  585: 
  586:             liberation(s_etat_processus, s_objet_argument_1);
  587:             liberation(s_etat_processus, s_objet_argument_2);
  588: 
  589:             try
  590:             {
  591:                 giac::context   contexte;
  592: 
  593:                 int             direction;
  594: 
  595:                 if (argument_4 == NULL)
  596:                 {
  597:                     direction = 0;
  598:                 }
  599:                 else
  600:                 {
  601:                     direction = (strcmp((const char *) argument_4, "+") == 0)
  602:                             ? 1 : -1;
  603:                 }
  604: 
  605:                 gen expression(
  606:                         string(reinterpret_cast<const char *>(argument_2)),
  607:                         &contexte);
  608:                 identificateur variable(
  609:                         string(reinterpret_cast<const char *>(argument_1)));
  610:                 gen valeur(string(reinterpret_cast<const char *>
  611:                         (argument_3)), &contexte);
  612: 
  613:                 gen resultat = limit(expression, variable, valeur, direction,
  614:                         &contexte);
  615:                 string chaine = "'" + resultat.print() + "'";
  616: 
  617:                 conversion_cas_vers_rpl(s_etat_processus,
  618:                         reinterpret_cast<unsigned char *>(const_cast<char *>(
  619:                         chaine.c_str())));
  620:             }
  621:             catch(bad_alloc exception)
  622:             {
  623:                 s_etat_processus->erreur_systeme = d_es_allocation_memoire;
  624:             }
  625:             catch(...)
  626:             {
  627:                 s_etat_processus->erreur_execution = d_ex_erreur_interne_rplcas;
  628:             }
  629: 
  630:             free(argument_1);
  631:             free(argument_2);
  632:             free(argument_3);
  633: 
  634:             if (argument_4 != NULL)
  635:             {
  636:                 free(argument_4);
  637:             }
  638: 
  639:             break;
  640:         }
  641:     }
  642: 
  643:     return;
  644: 
  645: #else
  646: 
  647:     if (s_etat_processus->langue == 'F')
  648:     {
  649:         printf("+++Attention : RPL/CAS non compilé !\n");
  650:     }
  651:     else
  652:     {
  653:         printf("+++Warning : RPL/CAS not available !\n");
  654:     }
  655: 
  656:     fflush(stdout);
  657: 
  658:     return;
  659: 
  660: #endif
  661: }
  662: 
  663: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>