File:  [local] / rpl / src / interface_cas.cpp
Revision 1.12: download - view: text, annotated - select for diffs - revision graph
Wed Aug 3 09:26:47 2011 UTC (12 years, 9 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Ajout de la fonction LIMIT.

    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:         struct_objet *s_objet)
  237: {
  238:     struct_liste_chainee        *l_element_courant;
  239:     struct_liste_chainee        *l_element_precedent;
  240: 
  241:     if ((s_objet->type == ALG) || (s_objet->type == RPN))
  242:     {
  243:         // On transcrit les fonctions de GIAC vers le RPL/2.
  244: 
  245:         l_element_precedent = NULL;
  246:         l_element_courant = reinterpret_cast<struct_liste_chainee *>(
  247:                 s_objet->objet);
  248: 
  249:         while(l_element_courant != NULL)
  250:         {
  251:             if (l_element_courant->donnee->type == FCT)
  252:             {
  253:                 // Nous sommes en présence d'un nom, donc de quelque chose
  254:                 // qui n'est pas reconnu comme un mot-clef du RPL/2. S'il
  255:                 // s'agit d'un mot-clef de GIAC, on le convertit.
  256: 
  257:                 if ((strcmp((const char *)
  258:                         reinterpret_cast<struct_fonction *>(l_element_courant
  259:                         ->donnee->objet)->nom_fonction, "quote") == 0) ||
  260:                         (strcmp((const char *)
  261:                         reinterpret_cast<struct_fonction *>(l_element_courant
  262:                         ->donnee->objet)->nom_fonction, "nop") == 0))
  263:                 {
  264:                     liberation(s_etat_processus, l_element_courant->donnee);
  265: 
  266:                     if ((l_element_courant->donnee =
  267:                             allocation(s_etat_processus, FCT)) == NULL)
  268:                     {
  269:                         s_etat_processus->erreur_systeme =
  270:                                 d_es_allocation_memoire;
  271:                         return;
  272:                     }
  273: 
  274:                     if ((((struct_fonction *) l_element_courant->donnee->objet)
  275:                             ->nom_fonction = reinterpret_cast<unsigned char *>(
  276:                             malloc(6 * sizeof(unsigned char))))
  277:                             == NULL)
  278:                     {
  279:                         s_etat_processus->erreur_systeme =
  280:                                 d_es_allocation_memoire;
  281:                         return;
  282:                     }
  283: 
  284:                     strcpy(reinterpret_cast<char *>(
  285:                             reinterpret_cast<struct_fonction *>(
  286:                             l_element_courant->donnee->objet)->nom_fonction),
  287:                             "RELAX");
  288:                 }
  289:             }
  290: 
  291:             l_element_precedent = l_element_courant;
  292:             l_element_courant = l_element_courant->suivant;
  293:         }
  294:     }
  295: 
  296:     return;
  297: }
  298: 
  299: 
  300: /*
  301: ================================================================================
  302:   Fonction 'interface_cas'
  303: ================================================================================
  304:   Entrées : commande à effectuer.
  305:   Le contrôle des types est effectué dans la fonction appelant interface_cas().
  306: --------------------------------------------------------------------------------
  307:   Sorties : retour par la pile.
  308: --------------------------------------------------------------------------------
  309:   Effets de bord : néant
  310: ================================================================================
  311: */
  312: 
  313: void
  314: interface_cas(struct_processus *s_etat_processus,
  315:         enum t_rplcas_commandes commande)
  316: {
  317: #   ifdef RPLCAS
  318:     struct_objet            *s_objet_argument_1;
  319:     struct_objet            *s_objet_argument_2;
  320:     struct_objet            *s_objet_temporaire;
  321: 
  322:     struct_liste_chainee    *l_element_courant;
  323: 
  324:     unsigned char           *argument_1;
  325:     unsigned char           *argument_2;
  326:     unsigned char           *argument_3;
  327:     unsigned char           *argument_4;
  328:     unsigned char           *registre;
  329: 
  330:     unsigned int            position;
  331: 
  332:     switch(commande)
  333:     {
  334:         case RPLCAS_INTEGRATION:
  335:         {
  336:             if (depilement(s_etat_processus, &(s_etat_processus->l_base_pile),
  337:                     &s_objet_argument_1) == d_erreur)
  338:             {
  339:                 s_etat_processus->erreur_execution = d_ex_manque_argument;
  340:                 return;
  341:             }
  342: 
  343:             if (depilement(s_etat_processus, &(s_etat_processus->l_base_pile),
  344:                     &s_objet_argument_2) == d_erreur)
  345:             {
  346:                 liberation(s_etat_processus, s_objet_argument_1);
  347:                 s_etat_processus->erreur_execution = d_ex_manque_argument;
  348:                 return;
  349:             }
  350: 
  351:             if ((argument_1 = conversion_rpl_vers_cas(s_etat_processus,
  352:                     &s_objet_argument_1)) == NULL)
  353:             {
  354:                 s_etat_processus->erreur_systeme = d_es_allocation_memoire;
  355:                 return;
  356:             }
  357: 
  358:             if ((argument_2 = conversion_rpl_vers_cas(s_etat_processus,
  359:                     &s_objet_argument_2)) == NULL)
  360:             {
  361:                 s_etat_processus->erreur_systeme = d_es_allocation_memoire;
  362:                 return;
  363:             }
  364: 
  365:             liberation(s_etat_processus, s_objet_argument_1);
  366:             liberation(s_etat_processus, s_objet_argument_2);
  367: 
  368:             try
  369:             {
  370:                 giac::context   contexte;
  371: 
  372:                 gen variable(
  373:                         string(reinterpret_cast<const char *>(argument_1)),
  374:                         &contexte);
  375:                 gen expression(
  376:                         string(reinterpret_cast<const char *>(argument_2)),
  377:                         &contexte);
  378: 
  379:                 gen resultat = integrate_gen(expression, variable, &contexte);
  380:                 string chaine = "'" + resultat.print() + "'";
  381: 
  382:                 registre = s_etat_processus->instruction_courante;
  383:                 s_etat_processus->instruction_courante =
  384:                         reinterpret_cast<unsigned char *>(const_cast<char *>
  385:                         (chaine.c_str()));
  386: 
  387:                 recherche_type(s_etat_processus);
  388: 
  389:                 if (s_etat_processus->l_base_pile != NULL)
  390:                 {
  391:                     conversion_cas_vers_rpl(s_etat_processus,
  392:                             s_etat_processus->l_base_pile->donnee);
  393:                 }
  394: 
  395:                 s_etat_processus->instruction_courante = registre;
  396:             }
  397:             catch(bad_alloc exception)
  398:             {
  399:                 s_etat_processus->erreur_systeme = d_es_allocation_memoire;
  400:             }
  401:             catch(...)
  402:             {
  403:                 s_etat_processus->erreur_execution = d_ex_erreur_interne_rplcas;
  404:             }
  405: 
  406:             free(argument_1);
  407:             free(argument_2);
  408: 
  409:             break;
  410:         }
  411: 
  412:         case RPLCAS_LIMITE:
  413:         {
  414:             if (depilement(s_etat_processus, &(s_etat_processus->l_base_pile),
  415:                     &s_objet_argument_1) == d_erreur)
  416:             {
  417:                 s_etat_processus->erreur_execution = d_ex_manque_argument;
  418:                 return;
  419:             }
  420: 
  421:             if (depilement(s_etat_processus, &(s_etat_processus->l_base_pile),
  422:                     &s_objet_argument_2) == d_erreur)
  423:             {
  424:                 liberation(s_etat_processus, s_objet_argument_1);
  425:                 s_etat_processus->erreur_execution = d_ex_manque_argument;
  426:                 return;
  427:             }
  428: 
  429:             // Fonction
  430: 
  431:             if ((argument_2 = conversion_rpl_vers_cas(s_etat_processus,
  432:                     &s_objet_argument_2)) == NULL)
  433:             {
  434:                 s_etat_processus->erreur_systeme = d_es_allocation_memoire;
  435:                 return;
  436:             }
  437: 
  438:             // On parcourt la liste. Cette liste est tout d'abord copiée
  439:             // car on est susceptible de modifier le second élément.
  440: 
  441:             if ((s_objet_temporaire = copie_objet(s_etat_processus,
  442:                     s_objet_argument_1, 'O')) == NULL)
  443:             {
  444:                 s_etat_processus->erreur_systeme = d_es_allocation_memoire;
  445:                 return;
  446:             }
  447: 
  448:             liberation(s_etat_processus, s_objet_argument_1);
  449:             s_objet_argument_1 = s_objet_temporaire;
  450: 
  451:             l_element_courant = reinterpret_cast<struct_liste_chainee *>
  452:                     (s_objet_argument_1->objet);
  453:             position = 1;
  454:             argument_4 = NULL;
  455: 
  456:             while(l_element_courant != NULL)
  457:             {
  458:                 switch(position)
  459:                 {
  460:                     case 1:
  461:                     {
  462:                         // Variable
  463: 
  464:                         if ((argument_1 = reinterpret_cast<unsigned char *>
  465:                                 (malloc((strlen((const char *)
  466:                                 ((struct_variable *) (l_element_courant
  467:                                 ->donnee->objet))->nom)
  468:                                 + 1) * sizeof(unsigned char)))) == NULL)
  469:                         {
  470:                             s_etat_processus->erreur_systeme =
  471:                                     d_es_allocation_memoire;
  472:                             return;
  473:                         }
  474: 
  475:                         strcpy(reinterpret_cast<char *>(argument_1),
  476:                                 (const char *) ((struct_variable *)
  477:                                 (l_element_courant->donnee->objet))->nom);
  478:                         break;
  479:                     }
  480: 
  481:                     case 2:
  482:                     {
  483:                         // Valeur
  484:                         if ((argument_3 = conversion_rpl_vers_cas(
  485:                                 s_etat_processus,
  486:                                 &(l_element_courant->donnee))) == NULL)
  487:                         {
  488:                             s_etat_processus->erreur_systeme =
  489:                                     d_es_allocation_memoire;
  490:                             return;
  491:                         }
  492: 
  493:                         break;
  494:                     }
  495: 
  496:                     case 3:
  497:                     {
  498:                         // Direction
  499: 
  500:                         if ((argument_4 = reinterpret_cast<unsigned char *>
  501:                                 (malloc((strlen((const char *)
  502:                                 ((struct_fonction *) (l_element_courant
  503:                                 ->donnee->objet))->nom_fonction)
  504:                                 + 1) * sizeof(unsigned char)))) == NULL)
  505:                         {
  506:                             s_etat_processus->erreur_systeme =
  507:                                     d_es_allocation_memoire;
  508:                             return;
  509:                         }
  510: 
  511:                         strcpy(reinterpret_cast<char *>(argument_4),
  512:                                 (const char *) ((struct_fonction *)
  513:                                 (l_element_courant->donnee->objet))
  514:                                 ->nom_fonction);
  515:                         break;
  516:                     }
  517:                 }
  518: 
  519:                 l_element_courant = (*l_element_courant).suivant;
  520:                 position++;
  521:             }
  522: 
  523:             liberation(s_etat_processus, s_objet_argument_1);
  524:             liberation(s_etat_processus, s_objet_argument_2);
  525: 
  526:             try
  527:             {
  528:                 giac::context   contexte;
  529: 
  530:                 int             direction;
  531: 
  532:                 if (argument_4 == NULL)
  533:                 {
  534:                     direction = 0;
  535:                 }
  536:                 else
  537:                 {
  538:                     direction = (strcmp((const char *) argument_4, "+") == 0)
  539:                             ? 1 : -1;
  540:                 }
  541: 
  542:                 gen expression(
  543:                         string(reinterpret_cast<const char *>(argument_2)),
  544:                         &contexte);
  545:                 identificateur variable(
  546:                         string(reinterpret_cast<const char *>(argument_1)));
  547:                 gen valeur(string(reinterpret_cast<const char *>
  548:                         (argument_3)), &contexte);
  549: 
  550:                 gen resultat = limit(expression, variable, valeur, direction,
  551:                         &contexte);
  552:                 string chaine = "'" + resultat.print() + "'";
  553: 
  554:                 registre = s_etat_processus->instruction_courante;
  555:                 s_etat_processus->instruction_courante =
  556:                         reinterpret_cast<unsigned char *>(const_cast<char *>
  557:                         (chaine.c_str()));
  558: 
  559:                 recherche_type(s_etat_processus);
  560: 
  561:                 if (s_etat_processus->l_base_pile != NULL)
  562:                 {
  563:                     conversion_cas_vers_rpl(s_etat_processus,
  564:                             s_etat_processus->l_base_pile->donnee);
  565:                 }
  566: 
  567:                 s_etat_processus->instruction_courante = registre;
  568:             }
  569:             catch(bad_alloc exception)
  570:             {
  571:                 s_etat_processus->erreur_systeme = d_es_allocation_memoire;
  572:             }
  573:             catch(...)
  574:             {
  575:                 s_etat_processus->erreur_execution = d_ex_erreur_interne_rplcas;
  576:             }
  577: 
  578:             free(argument_1);
  579:             free(argument_2);
  580:             free(argument_3);
  581: 
  582:             if (argument_4 != NULL)
  583:             {
  584:                 free(argument_4);
  585:             }
  586: 
  587:             break;
  588:         }
  589:     }
  590: 
  591:     return;
  592: 
  593: #else
  594: 
  595:     if (s_etat_processus->langue == 'F')
  596:     {
  597:         printf("+++Attention : RPL/CAS non compilé !\n");
  598:     }
  599:     else
  600:     {
  601:         printf("+++Warning : RPL/CAS not available !\n");
  602:     }
  603: 
  604:     fflush(stdout);
  605: 
  606:     return;
  607: 
  608: #endif
  609: }
  610: 
  611: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>