File:  [local] / rpl / src / interface_cas.cpp
Revision 1.14: download - view: text, annotated - select for diffs - revision graph
Tue Aug 9 10:30:37 2011 UTC (12 years, 9 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_2, HEAD
Mise à jour de RPL/CAS et meilleure gestion des contextes.

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

CVSweb interface <joel.bertrand@systella.fr>