trafi

Transducteurs finis
git clone git://git.asteride.xyz/trafi.git
Journaux | Fichiers | Références

mishka.c (3364B)


      1 #define  _POSIX_C_SOURCE 200809L
      2 
      3 #include <assert.h>
      4 #include <fcntl.h>
      5 #include <stdint.h>
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <sys/types.h>
      9 
     10 #include "itfd.h"
     11 
     12 char *nomprog;
     13 
     14 /* Écrire l’utilisation dans le fichier f. */
     15 static void utilisation(FILE *f);
     16 
     17 /* Faire passer entree dans le transducteur contenu dans le fichier désigné par
     18  * tfd et en écrire le résultat dans sortie.
     19  * Renvoie 0, ou -1 en cas d’erreur. */
     20 static int transductionner(int tfd, FILE *entree, FILE *sortie);
     21 
     22 int
     23 main(int argc, char **argv)
     24 {
     25 	int tfd; /* Descripteur de fichier du transducteur fini. */
     26 
     27 	nomprog = argv[0];
     28 
     29 	if (argc != 2) {
     30 		utilisation(stderr);
     31 		return 1;
     32 	}
     33 
     34 	if ((tfd = open(argv[1], O_RDONLY)) < 0) {
     35 		fprintf(stderr, "%s: impossible d’ouvrir %s\n",
     36 		    nomprog, argv[1]);
     37 		return 1;
     38 	}
     39 
     40 	if (transductionner(tfd, stdin, stdout) < 0) {
     41 		fprintf(stderr, "%s: une erreur est survenue\n", nomprog);
     42 		return 1;
     43 	}
     44 }
     45 
     46 static void
     47 utilisation(FILE *f)
     48 {
     49 	assert(f);
     50 
     51 	fprintf(f, "Utilisation: %s <[mots]\n", nomprog);
     52 }
     53 
     54 static int
     55 transductionner(int tfd, FILE *entree, FILE *sortie)
     56 {
     57 	struct itfd *itfd;
     58 	struct interp *interp;
     59 	char *le; /* Tampon contenant la ligne d’entrée. */
     60 	size_t lelngr; /* Longueur du tampon le. */
     61 	uint16_t *symbs; /* Tampon contenant la chaîne de symboles. */
     62 	size_t symbslngr; /* Longueur du tampon symbs. */
     63 	ssize_t clus; /* Nombre de caractères lus. */
     64 	size_t nsymbs; /* Nombre de symboles segmentés. */
     65 	ssize_t vr; /* Valeur renvoyée. */
     66 	size_t isymb; /* Indice dans la chaîne de symboles. */
     67 	bool esp; /* Afficher un espace? */
     68 
     69 	assert(tfd > 0);
     70 	assert(entree);
     71 	assert(sortie);
     72 
     73 	/* Ouvrir tfd. */
     74 	if ((itfd = itfd_ouvrir(tfd)) == NULL) {
     75 		fprintf(stderr, "%s: impossible d’ouvrir le transducteur\n",
     76 		    nomprog);
     77 		return -1;
     78 	}
     79 
     80 	/* Initialiser l’interpréteur. */
     81 	if ((interp = interp_init(itfd)) == NULL) {
     82 		fprintf(stderr, "%s: erreur\n", nomprog);
     83 		return -1;
     84 	}
     85 
     86 	le = NULL;
     87 	lelngr = 0;
     88 	symbslngr = 64;
     89 	if ((symbs = malloc(symbslngr * sizeof(uint16_t))) == NULL) {
     90 		fprintf(stderr, "%s: malloc(3)\n", nomprog);
     91 		return -1;
     92 	}
     93 
     94 	/* Parcourir les lignes. */
     95 	while ((clus = getline(&le, &lelngr, entree)) > 0) {
     96 		/* Ignorer la nouvelle ligne. */
     97 		clus--;
     98 		/* Assurer que symbs soit assez grand. */
     99 		if ((size_t)clus > symbslngr) {
    100 		    symbslngr *= 2;
    101 		    if ((symbs = realloc(symbs, symbslngr * sizeof(uint16_t)))
    102 		            == NULL) {
    103 		        fprintf(stderr, "%s: malloc(3)\n", nomprog);
    104 		        return -1;
    105 		    }
    106 		}
    107 
    108 		/* Segmenter. */
    109 		nsymbs = segmenter(itfd, (uint8_t *)le, clus, symbs);
    110 
    111 		/* Interpréter. */
    112 		esp = 0;
    113 		while ((vr = interpreter(interp, symbs, nsymbs)) > 0) {
    114 		    if (esp) putc(' ', sortie);
    115 		    for (isymb = 0; isymb < (size_t)vr - 1; isymb++) {
    116 		        if ((interp->css[isymb] & 0x01) == ITFD_SYMB_REC) {
    117 		        fwrite(itfd->symbs + 1 + (interp->css[isymb] >> 1),
    118 		            1,
    119 		            itfd->symbs[interp->css[isymb] >> 1],
    120 		            sortie);
    121 		        } else {
    122 		            putc(interp->css[isymb] >> 1, sortie);
    123 		        }
    124 		    }
    125 		    esp = 1;
    126 		}
    127 		putc('\n', sortie);
    128 		if (interp_reinit(interp, itfd) < 0)
    129 		    return -1;
    130 		if (vr < 0) {
    131 		    fprintf(stderr, "%s: erreur\n", nomprog);
    132 		    return -1;
    133 		}
    134 	}
    135 
    136 
    137 	free(le);
    138 	interp_libr(interp);
    139 	itfd_fermer(itfd);
    140 
    141 	return 0;
    142 }