File:  [local] / rpl / src / transliteration.c
Revision 1.3: download - view: text, annotated - select for diffs - revision graph
Wed Feb 10 08:09:30 2010 UTC (14 years, 2 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_0_10, HEAD
Modification du traitement des séquences d'échappement dans les chaînes
de caractères.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.0.10
    4:   Copyright (C) 1989-2010 Dr. BERTRAND Joël
    5: 
    6:   This file is part of RPL/2.
    7: 
    8:   RPL/2 is free software; you can redistribute it and/or modify it
    9:   under the terms of the CeCILL V2 License as published by the french
   10:   CEA, CNRS and INRIA.
   11:  
   12:   RPL/2 is distributed in the hope that it will be useful, but WITHOUT
   13:   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14:   FITNESS FOR A PARTICULAR PURPOSE.  See the CeCILL V2 License
   15:   for more details.
   16:  
   17:   You should have received a copy of the CeCILL License
   18:   along with RPL/2. If not, write to info@cecill.info.
   19: ================================================================================
   20: */
   21: 
   22: 
   23: #include "rpl.conv.h"
   24: #include <stdarg.h>
   25: #undef fprintf
   26: #undef printf
   27: 
   28: 
   29: /*
   30: ================================================================================
   31:   Fonction de translitération
   32: ================================================================================
   33:   Entrées :
   34: --------------------------------------------------------------------------------
   35:   Sorties :
   36: --------------------------------------------------------------------------------
   37:   Effets de bord : néant
   38: ================================================================================
   39: */
   40: 
   41: unsigned char *
   42: transliteration(struct_processus *s_etat_processus,
   43:         unsigned char *chaine_entree,
   44:         unsigned char *codage_entree,
   45:         unsigned char *codage_sortie)
   46: {
   47:     unsigned char       *codage_sortie_transliteral;
   48:     unsigned char       *tampon;
   49: 
   50:     if ((codage_sortie_transliteral = malloc((strlen(codage_sortie)
   51:             + strlen("//TRANSLIT") + 1) * sizeof(unsigned char))) == NULL)
   52:     {
   53:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
   54:         return(NULL);
   55:     }
   56: 
   57:     sprintf(codage_sortie_transliteral, "%s//TRANSLIT", codage_sortie);
   58: 
   59:     tampon = reencodage(s_etat_processus, chaine_entree,
   60:             codage_entree, codage_sortie_transliteral);
   61:     free(codage_sortie_transliteral);
   62: 
   63:     return(tampon);
   64: }
   65: 
   66: 
   67: unsigned char *
   68: reencodage(struct_processus *s_etat_processus,
   69:         unsigned char *chaine_entree,
   70:         unsigned char *codage_entree,
   71:         unsigned char *codage_sortie)
   72: {
   73: #   define              d_LONGUEUR  1024
   74: 
   75:     iconv_t             transcodage;
   76: 
   77:     size_t              ios;
   78:     size_t              longueur_entree;
   79:     size_t              longueur_sortie;
   80: 
   81:     unsigned char       *buffer_entree;
   82:     unsigned char       *buffer_sortie;
   83:     unsigned char       *chaine_sortie;
   84:     unsigned char       *pointeur;
   85:     unsigned char       *tampon;
   86: 
   87:     if ((transcodage = iconv_open(codage_sortie, codage_entree)) ==
   88:             (iconv_t) -1)
   89:     {
   90:         (*s_etat_processus).erreur_execution = d_ex_erreur_transcodage;
   91:         return(NULL);
   92:     }
   93: 
   94:     buffer_entree = chaine_entree;
   95:     longueur_entree = strlen(chaine_entree);
   96: 
   97:     if ((chaine_sortie = malloc(sizeof(unsigned char))) == NULL)
   98:     {
   99:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  100:         return(NULL);
  101:     }
  102: 
  103:     chaine_sortie[0] = d_code_fin_chaine;
  104: 
  105:     if ((buffer_sortie = malloc((d_LONGUEUR + 1) * sizeof(char))) == NULL)
  106:     {
  107:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  108:         return(NULL);
  109:     }
  110: 
  111:     do
  112:     {
  113:         longueur_sortie = d_LONGUEUR;
  114:         pointeur = buffer_sortie;
  115: 
  116:         if ((ios = iconv(transcodage, (char **) &buffer_entree,
  117:                 &longueur_entree, (char **) &pointeur, &longueur_sortie))
  118:                 == (size_t) -1)
  119:         {
  120:             // On autorise les erreurs EINVAL et EILSEQ
  121:             if (errno == EILSEQ)
  122:             {
  123:                 free(buffer_sortie);
  124:                 free(chaine_sortie);
  125: 
  126:                 (*s_etat_processus).erreur_execution = d_ex_erreur_transcodage;
  127:                 return(NULL);
  128:             }
  129:         }
  130: 
  131:         tampon = (unsigned char *) chaine_sortie;
  132:         (*pointeur) = d_code_fin_chaine;
  133: 
  134:         if ((chaine_sortie = malloc((strlen(tampon) + strlen(buffer_sortie) + 1)
  135:                 * sizeof(unsigned char))) == NULL)
  136:         {
  137:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  138:             return(NULL);
  139:         }
  140: 
  141:         sprintf(chaine_sortie, "%s%s", tampon, buffer_sortie);
  142:         free(tampon);
  143:     } while((*buffer_entree) != d_code_fin_chaine);
  144: 
  145:     free(buffer_sortie);
  146:     iconv_close(transcodage);
  147: 
  148:     return(chaine_sortie);
  149: }
  150: 
  151: 
  152: /*
  153: ================================================================================
  154:   Fonctions spécifiques
  155: ================================================================================
  156:   Entrées :
  157: --------------------------------------------------------------------------------
  158:   Sorties :
  159: --------------------------------------------------------------------------------
  160:   Effets de bord : néant
  161: ================================================================================
  162: */
  163: 
  164: void
  165: localisation_courante(struct_processus *s_etat_processus)
  166: {
  167:     char                        **arguments;
  168: 
  169:     int                         ios;
  170:     int                         pipes_entree[2];
  171:     int                         pipes_erreur[2];
  172:     int                         pipes_sortie[2];
  173:     int                         status;
  174: 
  175:     logical1                    drapeau_fin;
  176: 
  177:     long                        i;
  178:     long                        nombre_arguments;
  179: 
  180:     pid_t                       pid;
  181: 
  182:     sigset_t                    oldset;
  183:     sigset_t                    set;
  184: 
  185:     struct sigaction            action_passee;
  186: 
  187:     unsigned char               *tampon;
  188: 
  189:     unsigned long               longueur_lecture;
  190:     unsigned long               nombre_iterations;
  191:     unsigned long               pointeur;
  192: 
  193:     if ((arguments = malloc(3 * sizeof(char **))) == NULL)
  194:     {
  195:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  196:         return;
  197:     }
  198: 
  199:     if ((arguments[0] = malloc((strlen("locale") + 1) * sizeof(char))) == NULL)
  200:     {
  201:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  202:         return;
  203:     }
  204: 
  205:     if ((arguments[1] = malloc((strlen("charmap") + 1) * sizeof(char))) == NULL)
  206:     {
  207:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  208:         return;
  209:     }
  210: 
  211:     strcpy(arguments[0], "locale");
  212:     strcpy(arguments[1], "charmap");
  213:     arguments[2] = NULL;
  214: 
  215:     nombre_arguments = 2;
  216:     drapeau_fin = d_faux;
  217: 
  218:     if (pipe(pipes_entree) != 0)
  219:     {
  220:         (*s_etat_processus).erreur_systeme = d_es_processus;
  221:         return;
  222:     }
  223:         
  224:     if (pipe(pipes_sortie) != 0)
  225:     {
  226:         (*s_etat_processus).erreur_systeme = d_es_processus;
  227:         return;
  228:     }
  229: 
  230:     if (pipe(pipes_erreur) != 0)
  231:     {
  232:         (*s_etat_processus).erreur_systeme = d_es_processus;
  233:         return;
  234:     }
  235: 
  236:     sigfillset(&set);
  237:     pthread_sigmask(SIG_BLOCK, &set, &oldset);
  238: 
  239:     verrouillage_threads_concurrents(s_etat_processus);
  240:     pid = fork();
  241:     deverrouillage_threads_concurrents(s_etat_processus);
  242: 
  243:     pthread_sigmask(SIG_SETMASK, &oldset, NULL);
  244:     sigpending(&set);
  245: 
  246:     if (pid < 0)
  247:     {
  248:         if (close(pipes_entree[0]) != 0)
  249:         {
  250:             (*s_etat_processus).erreur_systeme = d_es_processus;
  251:             return;
  252:         }
  253: 
  254:         if (close(pipes_entree[1]) != 0)
  255:         {
  256:             (*s_etat_processus).erreur_systeme = d_es_processus;
  257:             return;
  258:         }
  259: 
  260:         if (close(pipes_sortie[0]) != 0)
  261:         {
  262:             (*s_etat_processus).erreur_systeme = d_es_processus;
  263:             return;
  264:         }
  265: 
  266:         if (close(pipes_sortie[1]) != 0)
  267:         {
  268:             (*s_etat_processus).erreur_systeme = d_es_processus;
  269:             return;
  270:         }
  271: 
  272:         if (close(pipes_erreur[0]) != 0)
  273:         {
  274:             (*s_etat_processus).erreur_systeme = d_es_processus;
  275:             return;
  276:         }
  277: 
  278:         if (close(pipes_erreur[1]) != 0)
  279:         {
  280:             (*s_etat_processus).erreur_systeme = d_es_processus;
  281:             return;
  282:         }
  283: 
  284:         (*s_etat_processus).erreur_systeme = d_es_processus;
  285:         return;
  286:     }
  287:     else if (pid == 0)
  288:     {
  289:         if (close(pipes_entree[1]) != 0)
  290:         {
  291:             (*s_etat_processus).erreur_systeme = d_es_processus;
  292:             return;
  293:         }
  294: 
  295:         if (close(pipes_sortie[0]) != 0)
  296:         {
  297:             (*s_etat_processus).erreur_systeme = d_es_processus;
  298:             return;
  299:         }
  300: 
  301:         if (close(pipes_erreur[0]) != 0)
  302:         {
  303:             (*s_etat_processus).erreur_systeme = d_es_processus;
  304:             return;
  305:         }
  306: 
  307:         if (pipes_entree[0] != STDIN_FILENO)
  308:         {
  309:             if (dup2(pipes_entree[0], STDIN_FILENO) == -1)
  310:             {
  311:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  312:                 return;
  313:             }
  314:         }
  315: 
  316:         if (pipes_sortie[1] != STDOUT_FILENO)
  317:         {
  318:             if (dup2(pipes_sortie[1], STDOUT_FILENO) == -1)
  319:             {
  320:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  321:                 return;
  322:             }
  323:         }
  324: 
  325:         if (pipes_sortie[1] != STDERR_FILENO)
  326:         {
  327:             if (dup2(pipes_sortie[1], STDERR_FILENO) == -1)
  328:             {
  329:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  330:                 return;
  331:             }
  332:         }
  333: 
  334:         if (nombre_arguments != 0)
  335:         {
  336:             execvp(arguments[0], arguments);
  337:         }
  338:         else
  339:         {
  340:             exit(EXIT_SUCCESS);
  341:         }
  342: 
  343:         /*
  344:          * L'appel système execvp() a généré une erreur et n'a pu exécuter
  345:          * argument[0] (fichier non exécutable ou inexistant).
  346:          */
  347: 
  348:         close(pipes_entree[0]);
  349:         close(pipes_sortie[1]);
  350: 
  351:         for(i = 0; i < nombre_arguments; i++)
  352:         {
  353:             free(arguments[i]);
  354:         }
  355: 
  356:         free(arguments);
  357:         (*s_etat_processus).erreur_systeme = d_es_processus;
  358: 
  359:         /*
  360:          * Envoi d'une erreur dans le pipe idoine. On ne regarde pas
  361:          * le nombre d'octets écrits car l'erreur ne pourra de toute
  362:          * façon pas être traitée.
  363:          */
  364: 
  365:         write_atomic(s_etat_processus, pipes_erreur[1], " ", 1);
  366:         close(pipes_erreur[1]);
  367: 
  368:         exit(EXIT_SUCCESS);
  369:     }
  370:     else
  371:     {
  372:         if (close(pipes_entree[0]) != 0)
  373:         {
  374:             (*s_etat_processus).erreur_systeme = d_es_processus;
  375:             return;
  376:         }
  377: 
  378:         if (close(pipes_sortie[1]) != 0)
  379:         {
  380:             (*s_etat_processus).erreur_systeme = d_es_processus;
  381:             return;
  382:         }
  383: 
  384:         if (close(pipes_erreur[1]) != 0)
  385:         {
  386:             (*s_etat_processus).erreur_systeme = d_es_processus;
  387:             return;
  388:         }
  389: 
  390:         if (close(pipes_entree[1]) != 0)
  391:         {
  392:             (*s_etat_processus).erreur_systeme = d_es_processus;
  393:             return;
  394:         }
  395: 
  396:         do
  397:         {
  398:             if (kill(pid, 0) != 0)
  399:             {
  400:                 break;
  401:             }
  402: 
  403:             /*
  404:              * Récupération de la valeur de retour du processus détaché
  405:              */
  406: 
  407:             if (sem_post(&((*s_etat_processus).semaphore_fork))
  408:                     != 0)
  409:             {
  410:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  411:                 return;
  412:             }
  413: 
  414:             if (waitpid(pid, &status, 0) == -1)
  415:             {
  416:                 if (sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
  417:                 {
  418:                     if (errno != EINTR)
  419:                     {
  420:                         (*s_etat_processus).erreur_systeme = d_es_processus;
  421:                         return;
  422:                     }
  423:                 }
  424: 
  425:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  426:                 return;
  427:             }
  428: 
  429:             if (sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
  430:             {
  431:                 if (errno != EINTR)
  432:                 {
  433:                     (*s_etat_processus).erreur_systeme = d_es_processus;
  434:                     return;
  435:                 }
  436:             }
  437:         } while((!WIFEXITED(status)) && (!WIFSIGNALED(status)));
  438: 
  439:         longueur_lecture = 256;
  440:         pointeur = 0;
  441:         nombre_iterations = 1;
  442: 
  443:         if ((tampon = malloc((longueur_lecture + 1) *
  444:                 sizeof(unsigned char))) == NULL)
  445:         {
  446:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  447:             return;
  448:         }
  449: 
  450:         if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
  451:         {
  452:             (*s_etat_processus).erreur_systeme = d_es_processus;
  453:             return;
  454:         }
  455: 
  456:         while((ios = read_atomic(s_etat_processus,
  457:                 pipes_sortie[0], &(tampon[pointeur]),
  458:                 longueur_lecture)) > 0)
  459:         {
  460:             while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
  461:             {
  462:                 if (errno != EINTR)
  463:                 {
  464:                     (*s_etat_processus).erreur_systeme = d_es_processus;
  465:                     return;
  466:                 }
  467:             }
  468: 
  469:             tampon[pointeur + ios] = d_code_fin_chaine;
  470:             pointeur += longueur_lecture;
  471:             nombre_iterations++;
  472: 
  473:             if ((tampon = realloc(tampon,
  474:                     ((nombre_iterations * longueur_lecture) + 1) *
  475:                     sizeof(unsigned char))) == NULL)
  476:             {
  477:                 (*s_etat_processus).erreur_systeme =
  478:                         d_es_allocation_memoire;
  479:                 return;
  480:             }
  481: 
  482:             if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
  483:             {
  484:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  485:                 return;
  486:             }
  487:         }
  488: 
  489:         while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
  490:         {
  491:             if (errno != EINTR)
  492:             {
  493:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  494:                 return;
  495:             }
  496:         }
  497: 
  498:         if (strlen(tampon) == 0)
  499:         {
  500:             (*s_etat_processus).erreur_systeme = d_es_processus;
  501:             return;
  502:         }
  503: 
  504:         tampon[strlen(tampon) - 1] = d_code_fin_chaine;
  505: 
  506:         if (ios == -1)
  507:         {
  508:             (*s_etat_processus).erreur_systeme = d_es_processus;
  509:             return;
  510:         }
  511: 
  512:         if (close(pipes_sortie[0]) != 0)
  513:         {
  514:             (*s_etat_processus).erreur_systeme = d_es_processus;
  515:             return;
  516:         }
  517: 
  518:         (*s_etat_processus).localisation = tampon;
  519: 
  520:         if (sigaction(SIGINT, &action_passee, NULL) != 0)
  521:         {
  522:             for(i = 0; i < nombre_arguments; i++)
  523:             {
  524:                 free(arguments[i]);
  525:             }
  526: 
  527:             free(arguments);
  528:             (*s_etat_processus).erreur_systeme = d_es_signal;
  529:             return;
  530:         }
  531: 
  532:         for(i = 0; i < nombre_arguments; i++)
  533:         {
  534:             free(arguments[i]);
  535:         }
  536: 
  537:         free(arguments);
  538: 
  539:         if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
  540:         {
  541:             (*s_etat_processus).erreur_systeme = d_es_processus;
  542:             return;
  543:         }
  544: 
  545:         if (read_atomic(s_etat_processus, pipes_erreur[0], tampon, 1) > 0)
  546:         {
  547:             // Le processus fils renvoie une erreur.
  548: 
  549:             while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
  550:             {
  551:                 if (errno != EINTR)
  552:                 {
  553:                     (*s_etat_processus).erreur_systeme = d_es_processus;
  554:                     return;
  555:                 }
  556:             }
  557: 
  558:             (*s_etat_processus).erreur_execution = d_ex_erreur_processus;
  559:             return;
  560:         }
  561: 
  562:         while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
  563:         {
  564:             if (errno != EINTR)
  565:             {
  566:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  567:                 return;
  568:             }
  569:         }
  570: 
  571:         if (close(pipes_erreur[0]) != 0)
  572:         {
  573:             (*s_etat_processus).erreur_systeme = d_es_processus;
  574:             return;
  575:         }
  576:     }
  577: 
  578:     return;
  579: }
  580: 
  581: static int
  582: vtransliterated_sprintf(char **strp, const char *fmt, va_list ap)
  583: {
  584:     size_t bs, s;
  585:     char *b = NULL;
  586:     va_list cap;
  587: 
  588:     va_copy(cap, ap);
  589: 
  590:     for(bs = 256;; bs *= 2)
  591:     {
  592:         va_copy(ap, cap);
  593:         if (b != NULL) free(b);
  594:         if ((b = malloc(sizeof(*b) * bs)) == NULL) return -1;
  595:         if (((int) (s = vsnprintf(b, bs, fmt, ap))) < 0)
  596:                 { va_end(ap); free(b); return -1; }
  597:         va_end(ap);
  598:         if (s < bs) break;
  599:     }
  600: 
  601:     if (((*strp) = realloc(b, ((s = strlen(b)) + 1) * sizeof(*b)))
  602:             == NULL) { free(b); return -1; }
  603:     return s;
  604: }
  605: 
  606: int
  607: transliterated_fprintf(struct_processus *s_etat_processus, file *flux,
  608:         const char *format, ...)
  609: {
  610:     int             ios;
  611:     char            *tampon;
  612:     unsigned char   *tampon2;
  613:     va_list         arguments;
  614: 
  615:     va_start(arguments, format);
  616: 
  617:     if (vtransliterated_sprintf(&tampon, format, arguments) < 0)
  618:     {
  619:         va_end(arguments);
  620: 
  621:         if (s_etat_processus != NULL)
  622:         {
  623:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  624:         }
  625: 
  626:         return(-1);
  627:     }
  628: 
  629:     va_end(arguments);
  630: 
  631:     if (s_etat_processus != NULL)
  632:     {
  633:         if ((tampon2 = transliteration(s_etat_processus, tampon,
  634:                 d_locale, (*s_etat_processus).localisation)) == NULL)
  635:         {
  636:             free(tampon);
  637:             return(-1);
  638:         }
  639: 
  640:         free(tampon);
  641:     }
  642:     else
  643:     {
  644:         tampon2 = tampon;
  645:     }
  646: 
  647: #   ifdef SunOS
  648:     while((ios = fprintf(flux, "%s", tampon2)) < 0)
  649:     {
  650:         if ((errno != EINTR) && (errno != 0))
  651:         {
  652:             break;
  653:         }
  654:     }
  655: #   else
  656:     ios = fprintf(flux, "%s", tampon2);
  657: #   endif
  658: 
  659:     free(tampon2);
  660: 
  661:     return(ios);
  662: }
  663: 
  664: #define fprintf NULL
  665: #define printf NULL
  666: 
  667: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>