commit c8b59f1564489e8a877a1058e11ea74fd3819123
parent ce229984182cf0c50e4e57bbe6c6a743567665c1
Auteur: Selve <selve@asteride.xyz>
Date: Fri, 22 Mar 2024 15:25:18 -0400
changements importants
Diffstat:
M | aplat.c | | | 350 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- |
M | changements.txt | | | 10 | ++++++++++ |
M | tampon.c | | | 78 | ++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------- |
M | tampon.h | | | 19 | +++++++++++-------- |
4 files changed, 240 insertions(+), 217 deletions(-)
diff --git a/aplat.c b/aplat.c
@@ -1,75 +1,77 @@
#include <assert.h>
#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
+
+#ifdef __OpenBSD__
+ #include <unistd.h>
+#endif
#include <libintl.h>
#include <locale.h>
#include "tampon.h"
-#define TLL_ETQ 4096 /* taille initiale du tampon à étiquettes */
-#define TLL_CTN 4096 /* taille initiale du tampon à texte */
-
#define DRAP_OUV 01 /* parenthèse ouvrante */
#define DRAP_FRM 02 /* parenthèse fermante */
-#define NGUI_BLOC 3 /* nombre de guillemets pour ouvrir ou fermer un bloc */
-
-#define TP_TYPE_ETQ 0 /* tampon contenant des étiquettes */
-#define TP_TYPE_CTN 1 /* tampon contenant du « contenu » */
+#define CTN_TLL 4096 /* taille initiale du tampon contenu */
+#define ETQ_TLL 256 /* taille initiale du tampon de l'étiquette */
+#define PILE_TLL 128 /* profondeur initiale de la pile */
#define JT_OUV 0 /* parenthèse ouvrante */
#define JT_FRM 1 /* parenthèse fermante */
-#define JT_FCT 2 /* séparateur fictif */
-#define JT_ATM 3 /* atome */
+#define JT_ATM 2 /* atome */
-#define _(c) gettext(c)
+#define _(c) gettext(c)
static void utilisation(void);
-static int transformer(FILE *);
-static int prch_jeton(FILE *, struct tampon *, int);
-static int afficher_ligne(struct tampon *, struct tampon *, int *);
-static int guillemets(FILE *, struct tampon *);
-static int bloc(FILE *, struct tampon *);
+static int aplatir(FILE *);
+static int obt_jeton(FILE *, struct tampon *);
+static int mang_blancs(FILE *);
+static void aff_ligne(int *, struct tampon *, struct tampon *);
+static int echapp(FILE *, struct tampon *);
+static int echapp_guillemets(FILE *, struct tampon *);
+static int echapp_bloc(FILE *, struct tampon *);
-char *nom_prog; /* nom du programme */
+char *prog_nom; /* nom du programme */
-struct tampon etq; /* tampon à étiquettes */
-struct tampon ctn; /* tampon à texte */
+struct tampon ctn; /* tampon du contenu */
+struct tampon etq; /* tampon de l'étiquette du domaine cadet */
+struct tampon pile; /* pile */
int
main(int argc, char **argv)
{
- if ((nom_prog = argv[0]) == NULL || nom_prog[0] == '\0')
- nom_prog = "aplat";
+ if ((prog_nom = argv[0]) == NULL || prog_nom[0] == '\0')
+ prog_nom = "aplat";
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(I18N_DOMAINE, I18N_DOS);
+ textdomain(I18N_DOMAINE);
#ifdef __OpenBSD__
if (unveil(I18N_DOS, "r") < 0 ||
unveil("/usr/share/locale/UTF-8/LC_CTYPE", "r") < 0) {
- fprintf(stderr, _("%s: erreur avec unveil()\n"), nom_prog);
+ fprintf(stderr, _("%s: erreur avec unveil()\n"), prog_nom);
return 1;
}
if (pledge("stdio rpath", NULL) < 0) {
- fprintf(stderr, _("%s: erreur avec pledge()\n"), nom_prog);
+ fprintf(stderr, _("%s: erreur avec pledge()\n"), prog_nom);
return 1;
}
#endif
- setlocale(LC_ALL, "");
- bindtextdomain(I18N_DOMAINE, I18N_DOS);
- textdomain(I18N_DOMAINE);
-
if (argc > 1) {
utilisation();
return 1;
}
/* initialiser les tampons */
- if (tp_init(&etq, TLL_ETQ) < 0 || tp_init(&ctn, TLL_CTN) < 0)
+ if (tp_init(&etq, ETQ_TLL) < 0
+ || tp_init(&ctn, CTN_TLL) < 0
+ || tp_init(&pile, PILE_TLL))
return 1;
- if (transformer(stdin) < 0)
+ if (aplatir(stdin) < 0)
return 1;
return 0;
@@ -78,55 +80,56 @@ main(int argc, char **argv)
static void
utilisation(void)
{
- printf(_("Utilisation: %s <[fichier]\n"), nom_prog);
+ printf(_("Utilisation: %s <[fichier]\n"), prog_nom);
}
static int
-transformer(FILE *f)
+aplatir(FILE *f)
{
- int prfd; /* profondeur */
- int draps; /* drapeaux */
- int c;
+ int prfd; /* profondeur */
+ int draps; /* drapeaux */
+ size_t nc; /* nombre de caractères */
+ size_t tp_nc; /* nombre de caractères dans un tampon */
+ char *tp_c; /* pointeur vers un caractère du tampon */
assert(f != NULL);
prfd = 0;
draps = 0;
- switch (prch_jeton(f, &etq, TP_TYPE_ETQ)) {
- case JT_OUV:
+ switch (mang_blancs(f)) {
+ case '(':
break;
case EOF:
return 0;
default:
- fprintf(stderr,
- _("%s: le premier caractère non blanc "
- "doit être « ( »\n"),
- nom_prog);
+ fprintf(stderr, _("%s: le premier caractère non blanc doit "
+ "être « ( »\n"), prog_nom);
return -1;
}
ouv:
prfd++;
+ tp_ecr(0, &pile);
+ draps |= DRAP_OUV;
- tp_ecr(':', &etq);
-
- switch (prch_jeton(f, &etq, TP_TYPE_ETQ)) {
+ switch (obt_jeton(f, &etq)) {
case JT_OUV:
- draps |= DRAP_OUV;
- afficher_ligne(&etq, &ctn, &draps);
+ aff_ligne(&draps, &etq, &ctn);
goto ouv;
case JT_FRM:
- draps |= DRAP_OUV | DRAP_FRM;
- afficher_ligne(&etq, &ctn, &draps);
- goto ferm;
- case JT_FCT:
- draps |= DRAP_OUV;
- afficher_ligne(&etq, &ctn, &draps);
- tp_ecr('\\', &etq);
- goto ouv;
+ goto frm;
case JT_ATM:
- draps |= DRAP_OUV;
+ tp_c = tp_tp(&etq);
+ tp_nc = tp_ncar(&etq);
+ for (nc = 1; tp_nc > 0; tp_nc--, tp_c++, nc++)
+ if (*tp_c == ':') {
+ tp_ecr(1, &pile);
+ *tp_c = '\0';
+ printf("(\t%s\t\n", tp_tp(&etq));
+ prfd++;
+ tp_deb(&etq, nc);
+ }
goto ctn;
case EOF:
goto deseq;
@@ -134,14 +137,12 @@ ouv:
assert(0);
ctn:
- switch (prch_jeton(f, &ctn, TP_TYPE_CTN)) {
+ switch (obt_jeton(f, &ctn)) {
case JT_OUV:
- afficher_ligne(&etq, &ctn, &draps);
+ aff_ligne(&draps, &etq, &ctn);
goto ouv;
case JT_FRM:
- draps |= DRAP_FRM;
- afficher_ligne(&etq, &ctn, &draps);
- goto ferm;
+ goto frm;
case JT_ATM:
goto ctn;
case EOF:
@@ -149,25 +150,21 @@ ctn:
}
assert(0);
-ferm:
- if (--prfd == 0)
- goto fin;
- assert(prfd > 0);
-
- while (tp_etq_rec(&etq) != ETQ_SEP_REL) {
+frm:
+ do {
draps |= DRAP_FRM;
- afficher_ligne(&etq, &ctn, &draps);
- if (--prfd == 0)
- goto fin;
- }
+ aff_ligne(&draps, &etq, &ctn);
+ prfd--;
+ } while (tp_rec(&pile) != 0);
+
+ if (prfd == 0)
+ goto fin;
- switch (prch_jeton(f, &ctn, TP_TYPE_CTN)) {
+ switch (obt_jeton(f, &ctn)) {
case JT_OUV:
goto ouv;
case JT_FRM:
- draps |= DRAP_FRM;
- afficher_ligne(&etq, &ctn, &draps);
- goto ferm;
+ goto frm;
case JT_ATM:
goto ctn;
case EOF:
@@ -176,33 +173,27 @@ ferm:
assert(0);
fin:
- while ((c = getc(f)) == ' ' || c == '\n' || c == '\t')
- ;
- if (c == EOF)
+ if (mang_blancs(f) == EOF)
return 0;
fprintf(stderr, _("%s: aucun caractère non blanc ne peut suivre "
- "le dernier « ) »\n"),
- nom_prog);
+ "le dernier « ) »\n"), prog_nom);
return -1;
deseq:
- fprintf(stderr, _("%s: parenthèses déséquilibrées\n"), nom_prog);
+ fprintf(stderr, _("%s: parenthèses déséquilibrées\n"), prog_nom);
return -1;
}
static int
-prch_jeton(FILE *f, struct tampon *tp, int tp_type)
+obt_jeton(FILE *f, struct tampon *tp)
{
int c;
- int ngui; /* nombre de guillemets */
- assert(f != NULL);
- assert(tp != NULL);
- assert(tp_type == TP_TYPE_ETQ || tp_type == TP_TYPE_CTN);
+ assert(f != NULL);
+ assert(tp != NULL);
- while ((c = getc(f)) == ' ' || c == '\n' || c == '\t')
- if (c == EOF)
- return EOF;
+ if ((c = mang_blancs(f)) == EOF)
+ return EOF;
switch (c) {
case '(':
@@ -219,105 +210,101 @@ prch_jeton(FILE *f, struct tampon *tp, int tp_type)
case ' ': case '\t': case '\n':
return JT_ATM;
case '"':
- /* compter le nombre de guillemets */
- for (ngui = 1; (c = getc(f)) == '"'; ngui++)
- if (c == EOF)
- return EOF;
- if (ngui == NGUI_BLOC) {
- /* ignorer le reste de la ligne */
- while (c != '\n')
- if ((c = getc(f)) == EOF)
+ if ((c = getc(f)) == '"') {
+ if ((c = getc(f)) == '"') {
+ if (echapp_bloc(f, tp) == EOF)
return EOF;
- if (bloc(f, tp) == EOF)
- return EOF;
- continue;
- }
- ungetc(c, f);
- if (ngui % 2 == 1) { /* nombre impaire de guillemets */
- if (guillemets(f, tp) == EOF)
+ } else {
+ ungetc(c, f);
+ }
+ } else {
+ ungetc(c, f);
+ if (echapp_guillemets(f, tp) == EOF)
return EOF;
}
continue;
- case ':':
- if (tp_type == TP_TYPE_ETQ)
- return JT_FCT;
- tp_ecr(':', tp);
case '\\':
- switch (c = getc(f)) {
- case '\\':
- tp_ecr('\\', tp);
- break;
- case '\t':
- tp_ecr('\\', tp);
- tp_ecr('t', tp);
- continue;
- case '\n':
- continue;
- case EOF:
+ if (echapp(f, tp) == EOF)
return EOF;
- }
- /* CASCADE */
+ continue;
default:
tp_ecr(c, tp);
}
} while ((c = getc(f)) != EOF);
+
return EOF;
}
static int
-afficher_ligne(struct tampon *etq, struct tampon *ctn, int *draps)
+mang_blancs(FILE *f)
{
- char *c;
-
- assert(etq != NULL);
- assert(ctn != NULL);
- assert(draps != NULL);
- assert(etq->tp != NULL);
- assert(ctn->tp != NULL);
- assert(etq->pc != NULL);
- assert(ctn->pc != NULL);
-
- /* étiquettes */
- for (c = etq->tp; c < etq->pc; c++) {
- if (*c == '\\')
- /* les autres /\\./ doivent être préservés */
- if (*++c != ':')
- putc('\\', stdout);
- if (putc(*c, stdout) < 0)
- return -1;
- }
- putc(':', stdout); /* ajouter le point final */
- putc('\t', stdout);
+ int c;
+ while ((c = getc(f)) == ' ' || c == '\n' || c == '\t')
+ ;
+ return c;
+}
+
+static void
+aff_ligne(int *draps, struct tampon *etq, struct tampon *ctn)
+{
+ assert(draps != NULL);
+ assert(etq != NULL);
+ assert(ctn != NULL);
- /* drapeaux */
if (*draps & DRAP_OUV)
putc('(', stdout);
if (*draps & DRAP_FRM)
putc(')', stdout);
- *draps = 0;
- putc('\t', stdout);
+ tp_ecr('\0', etq);
+ tp_ecr('\0', ctn);
- /* contenu */
- for (c = ctn->tp; c < ctn->pc; c++)
- if (putc(*c, stdout) < 0)
- return -1;
+ printf("\t%s\t%s\n", tp_tp(etq), tp_tp(ctn));
+ *draps = 0;
+ tp_eff(etq);
tp_eff(ctn);
- putc('\n', stdout);
+}
+
+static int
+echapp(FILE *f, struct tampon *tp)
+{
+ int c;
+
+ assert(f != NULL);
+ assert(tp != NULL);
+
+ switch (c = getc(f)) {
+ case '\n':
+ break;
+ case '\t':
+ tp_ecr('\\', tp);
+ tp_ecr('t', tp);
+ break;
+ case EOF:
+ return EOF;
+ case '\\':
+ tp_ecr('\\', tp);
+ /* CASCADE */
+ default:
+ tp_ecr(c, tp);
+ }
+
return 0;
}
static int
-guillemets(FILE *f, struct tampon *tp)
+echapp_guillemets(FILE *f, struct tampon *tp)
{
int c;
- assert(f != NULL);
+ assert(f != NULL);
assert(tp != NULL);
- while ((c = getc(f)) != '"' && c != EOF) {
- switch (c) {
+ for (;;) {
+ switch ((c = getc(f))) {
+ case '"':
+ return 0;
case '\n':
tp_ecr('\\', tp);
tp_ecr('n', tp);
@@ -327,41 +314,36 @@ guillemets(FILE *f, struct tampon *tp)
tp_ecr('t', tp);
continue;
case '\\':
- switch (c = getc(f)) {
- case '\\':
- tp_ecr('\\', tp);
- break;
- case '\n':
- continue;
- case '\t':
- tp_ecr('\\', tp);
- tp_ecr('t', tp);
+ if (echapp(f, tp) != EOF)
continue;
- case EOF:
- return EOF;
- }
/* CASCADE */
+ case EOF:
+ return EOF;
default:
tp_ecr(c, tp);
}
}
- return c;
}
static int
-bloc(FILE *f, struct tampon *tp)
+echapp_bloc(FILE *f, struct tampon *tp)
{
int c;
int ngui;
size_t ncar;
- assert(f != NULL);
+ assert(f != NULL);
assert(tp != NULL);
+ /* ignorer le reste de la ligne */
+ while ((c = getc(f)) != '\n')
+ if (c == EOF)
+ return EOF;
+
ncar = tp_ncar(tp);
- while ((c = getc(f)) != EOF) {
- switch (c) {
+ for (;;) {
+ switch (c = getc(f)) {
case '\n':
tp_ecr('\\', tp);
tp_ecr('n', tp);
@@ -371,23 +353,26 @@ bloc(FILE *f, struct tampon *tp)
tp_ecr('t', tp);
continue;
case '"':
- /* compter le nombre de guillemets */
- for (ngui = 1; (c = getc(f)) == '"' && ngui < NGUI_BLOC;
- ngui++)
- ;
- if (c != '!' || ngui < NGUI_BLOC)
- ungetc(c, f);
- if (ngui == NGUI_BLOC) {
- if (c != '!') {
- /* si le bloc n'est pas vide */
+ ngui = 1;
+ while ((c = getc(f)) == '"') {
+ if (++ngui == 3) {
+ if ((c = getc(f)) == '!')
+ goto afficher;
+ ungetc(c, f);
if (ncar != tp_ncar(tp))
- tp_bloc_rec(tp);
- return c;
+ tp_eff_ligne(tp);
+ return 0;
}
}
+ /* retourner au flux le caractère lu en trop */
+ ungetc(c, f);
+ /* écrire au tampon les guillemets lus */
+afficher:
while (ngui-- > 0)
tp_ecr('"', tp);
continue;
+ case EOF:
+ return EOF;
case '\\':
tp_ecr('\\', tp);
/* CASCADE */
@@ -395,5 +380,4 @@ bloc(FILE *f, struct tampon *tp)
tp_ecr(c, tp);
}
}
- return EOF;
}
diff --git a/changements.txt b/changements.txt
@@ -1,6 +1,16 @@
Changements
===========
+Version ?.?
+-----------
+
+* plat(5): Permutation du champ des drapeaux et de celui des étiquettes. Le
+ champ des drapeaux est maintenant premier et celui des étiquettes second.
+* plat(5): Seule l'étiquette du domaine cadet est maintenant affichée dans le
+ champ des étiquettes, plutôt que la hiérarchie complète.
+* aplat(1): Correction d'un problème où le deux-points d'une étiquette n'était
+ pas interprété comme il faut lorsque placé entre guillemets ou dans un bloc.
+
Version 1.0
-----------
diff --git a/tampon.c b/tampon.c
@@ -11,7 +11,9 @@
assert((t)->tll >= 1), \
assert((t)->pc - (t)->tp >= 0), \
assert((size_t) ((t)->pc - (t)->tp) <= (t)->tll), \
- assert((t)->tll * TP_FACT_AGR > (t)->tll))
+ assert((t)->tll * TP_FACT_AGR > (t)->tll), \
+ assert((t)->deb < (t)->tll), \
+ assert((size_t) ((t)->pc - (t)->tp) >= (t)->deb))
static int tp_plein(char, struct tampon *);
@@ -20,11 +22,12 @@ int
tp_init(struct tampon *tp, size_t tll)
{
assert(tll >= 1);
- assert(tp != NULL);
+ assert(tp != NULL);
if ((tp->pc = tp->tp = malloc(tll)) == NULL)
return -1;
tp->tll = tll;
+ tp->deb = 0;
INVARIANTS_TP(tp);
@@ -73,49 +76,72 @@ tp_eff(struct tampon *tp)
INVARIANTS_TP(tp);
tp->pc = tp->tp;
+ tp->deb = 0;
INVARIANTS_TP(tp);
}
+/* obtenir le nombre de caractères dans un tampon */
+size_t
+tp_ncar(struct tampon *tp)
+{
+ INVARIANTS_TP(tp);
+
+ return tp->pc - (tp->tp + tp->deb);
+}
+
+/* obtenir un pointeur vers le début du tampon */
+char *
+tp_tp(struct tampon *tp)
+{
+ INVARIANTS_TP(tp);
+
+ return tp->tp + tp->deb;
+}
+
/* effacer les caractères du tampon tp jusqu'à la dernière nouvelle ligne,
* inclusivement */
void
-tp_bloc_rec(struct tampon *tp)
+tp_eff_ligne(struct tampon *tp)
{
+ int echapp;
+
INVARIANTS_TP(tp);
- while (tp->pc > tp->tp) {
- if (*--tp->pc == 'n' && *--tp->pc == '\\')
- break;
- }
+ /* problème dans le cas de \\n */
+ while (tp->pc > tp->tp)
+ if (*--tp->pc == 'n') {
+ echapp = 0;
+ while (*(tp->pc - 1) == '\\') {
+ echapp = !echapp;
+ tp->pc--;
+ }
+ if (echapp == 1)
+ break;
+ }
INVARIANTS_TP(tp);
}
-/* supprimer le domaine cadet */
-int
-tp_etq_rec(struct tampon *tp)
+/* supprimer le dernier caractère d'un tampon */
+char
+tp_rec(struct tampon *tp)
{
INVARIANTS_TP(tp);
- assert(tp->pc - tp->tp > 1);
- assert(*tp->tp == ':');
-
- while (*--tp->pc != ':')
- ;
- if (tp->pc - tp->tp != 0 && *(tp->pc-1) == '\\') {
- --tp->pc;
- assert(tp->pc - tp->tp > 0);
- return ETQ_SEP_FCT;
- }
- assert(tp->pc - tp->tp > 0);
- return ETQ_SEP_REL;
+
+ --tp->pc;
+
+ INVARIANTS_TP(tp);
+
+ return *tp->pc;
}
-/* obtenir le nombre de caractères dans un tampon */
-size_t
-tp_ncar(struct tampon *tp)
+void
+tp_deb(struct tampon *tp, size_t deb)
{
INVARIANTS_TP(tp);
- return tp->pc - tp->tp;
+ tp->deb = deb;
+
+ INVARIANTS_TP(tp);
}
diff --git a/tampon.h b/tampon.h
@@ -1,22 +1,25 @@
#ifndef TAMPON_H
#define TAMPON_H
-#define TP_FACT_AGR 2 /* facteur d'agrandissement d'un tampon */
+#include <stddef.h>
-#define ETQ_SEP_REL 0 /* séparateur réel */
-#define ETQ_SEP_FCT 1 /* séparateur fictif (échappé) */
+#define TP_FACT_AGR 2 /* facteur d'agrandissement d'un tampon */
struct tampon {
- char *tp; /* le tampon lui-même */
- char *pc; /* ptr vers la prochaine cellule libre */
- size_t tll; /* taille du tampon */
+ char *tp; /* le tampon lui-même */
+ char *pc; /* ptr vers la prochaine cellule libre */
+ size_t tll; /* taille du tampon */
+ size_t deb; /* début logique du tampon */
};
int tp_init(struct tampon *, size_t);
int tp_ecr(char, struct tampon *);
+char tp_rec(struct tampon *);
void tp_eff(struct tampon *);
-void tp_bloc_rec(struct tampon *);
-int tp_etq_rec(struct tampon *);
+void tp_eff_ligne(struct tampon *);
size_t tp_ncar(struct tampon *);
+char *tp_tp(struct tampon *);
+void tp_deb(struct tampon *tp, size_t deb);
+
#endif