commit c9dc5b7b93c6b562aedfb90cf1bc914a110170e8
parent dcbe1426ea6217b983631500641676c60077c719
Auteur: Loïc Daignault-Pichette <loic@asteride.xyz>
Date: Fri, 10 Apr 2026 22:14:29 -0400
Réintégrer les listes d’identifiants de symbole
Il s’agit des liste d’identifiants de symbole d’entrée et de sortie.
Diffstat:
| M | itfd.c | | | 19 | +++++++++++-------- |
| M | itfd.h | | | 24 | ++++++++++++++---------- |
| M | tfd.c | | | 163 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ |
| M | tfd.h | | | 25 | ++++++++++++++++++------- |
4 fichiers modifiés, 156 insertions(+), 75 suppressions(-)
diff --git a/itfd.c b/itfd.c
@@ -57,15 +57,18 @@ itfd_ouvrir(int df)
/* Lire les informations sur les segments. */
itfd->symbs = itfd->f + LIRE_32(itfd->f, 0x06);
itfd->symbs_lngr = LIRE_32(itfd->f, 0x0A);
- itfd->segm = itfd->f + LIRE_32(itfd->f, 0x0E);
- itfd->segm_lngr = LIRE_32(itfd->f, 0x12);
- itfd->trans = itfd->f + LIRE_32(itfd->f, 0x16);
- itfd->trans_lngr = LIRE_32(itfd->f, 0x1A);
- if (itfd->symbs + itfd->symbs_lngr != itfd->segm)
- goto erreur2;
- if (itfd->segm + itfd->segm_lngr != itfd->trans)
- goto erreur2;
+ itfd->se = itfd->f + LIRE_32(itfd->f, 0x0E);
+ itfd->se_lngr = LIRE_32(itfd->f, 0x12);
+
+ itfd->ss = itfd->f + LIRE_32(itfd->f, 0x16);
+ itfd->ss_lngr = LIRE_32(itfd->f, 0x1A);
+
+ itfd->segm = itfd->f + LIRE_32(itfd->f, 0x1E);
+ itfd->segm_lngr = LIRE_32(itfd->f, 0x22);
+
+ itfd->trans = itfd->f + LIRE_32(itfd->f, 0x26);
+ itfd->trans_lngr = LIRE_32(itfd->f, 0x2A);
return itfd;
diff --git a/itfd.h b/itfd.h
@@ -6,16 +6,20 @@
/* Interpréter un transducteur fini sur le disque. */
struct itfd {
- int df; /* Descripteur de fichier. */
- uint8_t *f; /* Contenu du fichier. */
- off_t lngr; /* Longueur du fichier, en octets. */
- int version; /* Version du format tfd. */
- uint8_t *symbs; /* Position de la liste de symboles. */
- size_t symbs_lngr; /* Longueur de la liste de symboles. */
- uint8_t *segm; /* Position du segmenteur. */
- size_t segm_lngr; /* Longueur du segmenteur. */
- uint8_t *trans; /* Position du transducteur. */
- size_t trans_lngr; /* Longueur du transducteur. */
+ int df; /* Descripteur de fichier. */
+ uint8_t *f; /* Contenu du fichier. */
+ off_t lngr; /* Longueur du fichier, en octets. */
+ int version; /* Version du format tfd. */
+ uint8_t *symbs; /* Position de la liste de symboles. */
+ size_t symbs_lngr; /* Longueur de la liste de symboles. */
+ uint8_t *se; /* Position de la liste de symboles d’entrée. */
+ size_t se_lngr; /* Longueur de la liste de symboles d’entrée. */
+ uint8_t *ss; /* Position de la liste de symboles de sortie. */
+ size_t ss_lngr; /* Longueur de la liste de symboles de sortie. */
+ uint8_t *segm; /* Position du segmenteur. */
+ size_t segm_lngr; /* Longueur du segmenteur. */
+ uint8_t *trans; /* Position du transducteur. */
+ size_t trans_lngr; /* Longueur du transducteur. */
};
/* Ouvrir un fichier tfd pour l’interpréter.
diff --git a/tfd.c b/tfd.c
@@ -24,7 +24,7 @@ static void *ecrire_32(void *tp, uint32_t val);
/* Créer le segmenteur de symboles.
* Renvoie un pointeur vers un tampex, ou NULL en cas d’erreur. */
-static void *segmenteur(struct tfm *tfm);
+static void *segmenteur(struct tfm *tfm, uint16_t *se);
/* Trouver une paire libre dans le segmenteur.
* Renvoie l’indice de la paire trouvée, ou -1 en cas d’erreur. */
@@ -43,14 +43,16 @@ static int segmenteur_tlibre(uint16_t (**segm)[2], size_t i);
/* Créer un automate au format tfm à partir d’une liste de symboles d’entrée.
* Renvoie un pointeur vers un tfm, ou NULL en cas d’erreur. */
-static struct tfm *automate_symbs(struct tfm *tfm, uint32_t **finaux);
+static struct tfm *automate_symbs(struct tfm *tfm, uint16_t *se,
+ uint32_t **finaux);
-/* Créer la liste des identifiants de symbole utilisés comme symboles d’entrée.
- * Renvoie un pointeur vers un tampex, ou NULL en cas d’erreur. */
-static uint16_t *symboles_entree(struct tfm *tfm);
+/* Obtenir la liste des identifiants de symbole d’entrée (se) et de sortie (ss)
+ * du tranducteur tfm.
+ * Renvoie 0, ou -1 en cas d’erreur. */
+static int symboles_id(struct tfm *tfm, uint16_t **se, uint16_t **ss);
/* Afficher un segmenteur en sortie standard. */
-static void segmenteur_afficher(struct tfm *tfm);
+static void segmenteur_afficher(struct tfm *tfm, uint16_t *se);
/* Créer le transducteur à parir d’un tfm.
* Renvoie un pointeur vers un tampex, ou NULL en cas d’erreur. */
@@ -63,6 +65,7 @@ tfd_ecrire(FILE *f, struct tfm *tfm)
uint8_t *pent; /* Pointeur vers l’entête. */
size_t dec; /* Décalage courant dans le fichier. */
void *te; /* Pointeur réutilisable vers un tampon extensible. */
+ void *se; /* Liste d’identifiants de symboles d’entrée. */
size_t lngr; /* Longueur d’un tampon. */
assert(f);
@@ -98,15 +101,57 @@ tfd_ecrire(FILE *f, struct tfm *tfm)
if (fseek(f, dec, SEEK_SET) != 0)
return -1;
+ /* Écrire la liste d’identifiants de symbole d’entrée. */
+ if (symboles_id(tfm, (uint16_t **)&se, (uint16_t **)&te) < 0)
+ return -1;
+ lngr = tampex_esp(se);
+ if (fwrite(se, 1, lngr, f) != lngr) {
+ tampex_libr(se);
+ tampex_libr(te);
+ return -1;
+ }
+ pent = ecrire_32(pent, dec);
+ pent = ecrire_32(pent, lngr);
+
+ dec += lngr;
+ dec = ALIGNER(dec, 2);
+ if (fseek(f, dec, SEEK_SET) != 0) {
+ tampex_libr(se);
+ tampex_libr(te);
+ return -1;
+ }
+
+ /* Écrire la liste d’identifiants de symbole de sortie. */
+ lngr = tampex_esp(te);
+ if (fwrite(te, 1, lngr, f) != lngr) {
+ tampex_libr(se);
+ tampex_libr(te);
+ return -1;
+ }
+ tampex_libr(te);
+ pent = ecrire_32(pent, dec);
+ pent = ecrire_32(pent, lngr);
+
+ dec += lngr;
+ dec = ALIGNER(dec, 2);
+ if (fseek(f, dec, SEEK_SET) != 0) {
+ tampex_libr(se);
+ return -1;
+ }
+
/* Écrire le segmenteur. */
- if ((te = segmenteur(tfm)) == NULL)
+ if ((te = segmenteur(tfm, se)) == NULL) {
+ tampex_libr(se);
return -1;
+ }
lngr = tampex_esp(te);
if (fwrite(te, 1, lngr, f) != lngr) {
tampex_libr(te);
+ tampex_libr(se);
return -1;
}
tampex_libr(te);
+ tampex_libr(se);
pent = ecrire_32(pent, dec);
pent = ecrire_32(pent, lngr);
@@ -157,7 +202,7 @@ ecrire_32(void *tp, uint32_t val)
}
static void *
-segmenteur(struct tfm *tfm)
+segmenteur(struct tfm *tfm, uint16_t *se)
{
uint16_t (*segm)[2]; /* Segmenteur (base, origine). */
struct tfm *symbs; /* Automate des symboles. */
@@ -179,7 +224,7 @@ segmenteur(struct tfm *tfm)
goto erreur1;
/* Créer l’automate de symboles. */
- if ((symbs = automate_symbs(tfm, &finaux)) == NULL)
+ if ((symbs = automate_symbs(tfm, se, &finaux)) == NULL)
goto erreur2;
/* Le premier état ne peut être final; car un symbole doit avoir une
@@ -222,13 +267,13 @@ segmenteur(struct tfm *tfm)
ntrans--;
itrans = symbs->trans[itrans].prch) {
assert((symbs->trans[itrans].se & 0x01) ==
- TFM_SNORMAL);
+ TFM_SNORMAL);
if (tfm_symb_obt(symbs, symbs->trans[itrans].se,
(char *)&c, 1) != 1)
goto erreur3;
segm[base + c][0] = 1; /* Réserver la paire. */
segm[base + c][1] = (isegm << 1) | 0x00;
- bmax = MAX(isegm, bmax);
+ bmax = MAX(isegm, bmax);
if ((ipile = tampex_empl((void **)&pile)) < 0)
goto erreur3;
pile[ipile][0] = base + c;
@@ -249,7 +294,7 @@ segmenteur(struct tfm *tfm)
/* Désactiver les paires vides. */
for (isegm = 0; tampex_dedans(segm, isegm); isegm++)
if (segm[isegm][0] == 0)
- segm[isegm][1] = (0 << 1) | 0x01;
+ segm[isegm][1] = (0 << 1) | 0x01;
return segm;
@@ -329,7 +374,7 @@ segmenteur_tlibre(uint16_t (**segm)[2], size_t i)
}
static void
-segmenteur_afficher(struct tfm *tfm)
+segmenteur_afficher(struct tfm *tfm, uint16_t *se)
{
size_t i;
uint16_t (*segm)[2];
@@ -337,7 +382,7 @@ segmenteur_afficher(struct tfm *tfm)
assert(tfm);
assert(segm);
- segm = segmenteur(tfm);
+ segm = segmenteur(tfm, se);
for (i = 0; tampex_dedans(segm, i); i++) {
printf("%lu\t%s%u\t%s%u",
@@ -362,10 +407,9 @@ segmenteur_afficher(struct tfm *tfm)
* premier état et passe d’état en état en suivant les caractères du symbole et
* en ajoutant les transitions manquantes. */
static struct tfm *
-automate_symbs(struct tfm *tfm, uint32_t **finaux)
+automate_symbs(struct tfm *tfm, uint16_t *se, uint32_t **finaux)
{
struct tfm *symbs;
- uint16_t *se; /* Liste de symboles d’entrée. */
size_t pos; /* Position courante dans la liste de symboles. */
uint16_t isymb; /* Indice d’un symbole. */
ssize_t id; /* Identifiant de symbole. */
@@ -382,16 +426,13 @@ automate_symbs(struct tfm *tfm, uint32_t **finaux)
if ((symbs = tfm_init()) == NULL)
return NULL;
- if ((se = symboles_entree(tfm)) == NULL)
- goto erreur1;
-
/* Initialiser *finaux. */
if ((*finaux = tampex_init(TAMPON_LNGR_DEF, sizeof(uint32_t))) == NULL)
- goto erreur2;
+ goto erreur1;
/* Créer le premier état. */
if (tampex_minim((void **)&symbs->etats, 0) < 0)
- goto erreur3;
+ goto erreur2;
/* Parcourir les symboles. */
for (isymb = 0; tampex_dedans(se, isymb); isymb++) {
@@ -410,7 +451,7 @@ automate_symbs(struct tfm *tfm, uint32_t **finaux)
itrans = symbs->trans[itrans].prch) {
if (tfm_symb_obt(symbs, symbs->trans[itrans].se,
&c, 1) != 1)
- goto erreur3;
+ goto erreur2;
if (c == tfm->symbs[pos]) {
/* La bonne transition a été trouvée. Passer au
* prochain caractère et au prochain état. */
@@ -424,53 +465,54 @@ automate_symbs(struct tfm *tfm, uint32_t **finaux)
ietatp = ietat;
ietat = tampex_nelem(symbs->etats);
if (tampex_minim((void **)&symbs->etats, ietat) < 0)
- goto erreur3;
+ goto erreur2;
if ((id = tfm_symb_id(symbs, tfm->symbs + pos, 1)) < 0)
- goto erreur3;
+ goto erreur2;
if (tfm_ajt(symbs, ietatp, ietat, id, id) < 0)
- goto erreur3;
+ goto erreur2;
pcar:;
}
/* Marquer le dernier état d’un symbole comme final. */
if (tfm_mfinal(symbs, ietat) < 0)
- goto erreur3;
+ goto erreur2;
if (tampex_minim((void **)finaux, ietat) < 0)
- goto erreur3;
+ goto erreur2;
(*finaux)[ietat] = se[isymb];
}
- tampex_libr(se);
return symbs;
-erreur3:
- tampex_libr(*finaux);
erreur2:
- tampex_libr(se);
+ tampex_libr(*finaux);
erreur1:
tfm_libr(symbs);
return NULL;
}
-static uint16_t *
-symboles_entree(struct tfm *tfm)
+static int
+symboles_id(struct tfm *tfm, uint16_t **se, uint16_t **ss)
{
- uint16_t *se;
- size_t i; /* Indice dans se. */
- bool *dejala; /* Indique si l’identifiant est déjà dans se. */
+ size_t ise, iss; /* Indices dans se et ss. */
+ char *dejala; /* Indique si l’identifiant est déjà dans se (& 0x01) ou
+ dans ss (& 0x02). */
size_t ietat, ntrans, itrans;
size_t isymb; /* Identifiant de symbole. */
assert(tfm);
+ assert(se);
+ assert(ss);
- /* Initialiser se et dejala. */
- if ((se = tampex_init(TAMPON_LNGR_DEF, sizeof(uint16_t))) == NULL)
- return NULL;
- if ((dejala = tampex_init(TAMPON_LNGR_DEF, sizeof *dejala)) == NULL)
+ /* Initialiser se, ss et dejala. */
+ if ((*se = tampex_init(TAMPON_LNGR_DEF, sizeof(uint16_t))) == NULL)
+ return -1;
+ if ((*ss = tampex_init(TAMPON_LNGR_DEF, sizeof(uint16_t))) == NULL)
goto erreur1;
+ if ((dejala = tampex_init(TAMPON_LNGR_DEF, sizeof *dejala)) == NULL)
+ goto erreur2;
- i = 0;
+ ise = iss = 0;
/* Parcourir les états. */
for (ietat = 0; tampex_dedans(tfm->etats, ietat); ietat++) {
@@ -478,6 +520,8 @@ symboles_entree(struct tfm *tfm)
for (itrans = tfm->etats[ietat].trans,
ntrans = tfm->etats[ietat].ntrans;
ntrans--; itrans = tfm->trans[itrans].prch) {
+
+ /* Symbole d’entrée. */
/* Ignorer les symboles spéciaux. */
if (((isymb = tfm->trans[itrans].se) & 0x01) ==
TFM_SSPECIAL)
@@ -485,25 +529,44 @@ symboles_entree(struct tfm *tfm)
isymb >>= 1;
/* Ne pas ajouter le symbole s’il est déjà la. */
if (tampex_minim((void **)&dejala, isymb) < 0)
- goto erreur2;
- if (dejala[isymb])
+ goto erreur3;
+ if (dejala[isymb] & 0x01)
continue;
/* Ajouter le symbole. */
- if (tampex_minim((void **)&se, i) < 0)
- goto erreur2;
- se[i++] = isymb;
- dejala[isymb] = 1;
+ if (tampex_minim((void **)se, ise) < 0)
+ goto erreur3;
+ (*se)[ise++] = isymb;
+ dejala[isymb] |= 0x01;
+
+ /* Symbole de sortie. */
+ /* Ignorer les symboles spéciaux. */
+ if (((isymb = tfm->trans[itrans].ss) & 0x01) ==
+ TFM_SSPECIAL)
+ continue;
+ isymb >>= 1;
+ /* Ne pas ajouter le symbole s’il est déjà la. */
+ if (tampex_minim((void **)&dejala, isymb) < 0)
+ goto erreur3;
+ if (dejala[isymb] & 0x02)
+ continue;
+ /* Ajouter le symbole. */
+ if (tampex_minim((void **)ss, iss) < 0)
+ goto erreur3;
+ (*ss)[iss++] = isymb;
+ dejala[isymb] |= 0x02;
}
}
tampex_libr(dejala);
- return se;
+ return 0;
-erreur2:
+erreur3:
tampex_libr(dejala);
+erreur2:
+ tampex_libr(ss);
erreur1:
tampex_libr(se);
- return NULL;
+ return -1;
}
static void *
diff --git a/tfd.h b/tfd.h
@@ -12,10 +12,11 @@
* de presque toutes les valeurs qu’il contient suivent le boutisme de l’hôte
* qui l’a compilé.
*
- * Le format comprend une entête et trois segments. L’entête contient des
+ * Le format comprend une entête et cinq segments. L’entête contient des
* informations sur le fichier, de même que l’emplacement et la longueur de
* chacun des trois segments. Les segments sont les suivants: liste des
- * symboles, segmenteur et transducteur.
+ * symboles, liste d’identifiants de symbole d’entrée, liste d’identifiant de
+ * symbole de sortie, segmenteur et transducteur.
*
* L’entête contient les champs suivants:
*
@@ -24,10 +25,14 @@
* 04 05 Témoin de boutisme (0h00FF)
* 06 09 Emplacement de la liste des symboles
* 0A 0D Longueur de la liste des symboles
- * 0e 11 Emplacement du segmenteur
- * 12 15 Longueur du segmenteur
- * 16 19 Emplacement du transducteur
- * 1A 1D Longueur du transducteur
+ * 0E 11 Emplacement de la liste d’identifiants de symbole d’entrée
+ * 12 15 Longueur de la liste d’identifiants de symbole d’entrée
+ * 16 19 Emplacement de la liste d’identifiants de symbole de sortie
+ * 1A 1D Longueur de la liste d’identifiants de symbole de sortie
+ * 1E 21 Emplacement du segmenteur
+ * 22 25 Longueur du segmenteur
+ * 26 29 Emplacement du transducteur
+ * 2A 2D Longueur du transducteur
*
* Le nombre magique (0h5407) sert à identifier un fichier comme un fichier au
* format tfd. Le champ suivant indique la version du format utilisé. Le témoin
@@ -42,13 +47,19 @@
#define TFD_MAGIQUE 0x5407 /* Nombre magique. */
#define TFD_VERSION 0 /* Version courante. */
#define TFD_TEMOIN 0x00FF /* Témoin de boutisme. */
-#define TFD_ENTETE_TLL 0x1E /* Taille de l’entête. */
+#define TFD_ENTETE_TLL 0x2E /* Taille de l’entête. */
/* La liste de symboles et le segmenteur de symboles permettent au transducteur
* de manipuler des symboles de plusieurs octets. Les identifiants de symbole
* renvoyés par le segmenteur et reçus et renvoyés par le transducteur sont des
* indices dans la liste de symboles.
*
+ * La liste d’identifiants de symbole d’entrée est incluse pour permettre la
+ * génération de mots d’entrée.
+ *
+ * La liste d’identifiants de symbole de sortie est incluse pour permettre la
+ * génération de mots de sortie en présence du symbole spécial AUTRE.
+ *
* La liste des symboles se présente comme une suite chaînes de caractères
* encodées à la Pascal, dans lesquelles les chaînes sont immédiatement
* précédées d’un octet non-signé donnant la taille de la chaîne le suivant. La