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 }