aplat

Documents structurés pour Unix
git clone git://git.asteride.xyz/~ldp/aplat.git
Journaux | Fichiers | Références | LISEZ-MOI | LICENCE

commit 7b89929da8e5b0899c841889b4357bb3f0ce64eb
parent 6b5107d01f93dba4f34d6e0ccb3e9a558686eec2
Auteur: Selve <selve@asteride.xyz>
Date:   Fri, 17 Nov 2023 22:49:26 -0500

réécriture de aplat

Diffstat:
MMakefile | 4++--
Maplat.c | 212++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Aetq.c | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Aetq.h | 12++++++++++++
Mtampon.c | 79+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mtampon.h | 23++++++++---------------
Atxt.c | 21+++++++++++++++++++++
Atxt.h | 8++++++++
8 files changed, 260 insertions(+), 148 deletions(-)

diff --git a/Makefile b/Makefile @@ -8,8 +8,8 @@ PREFIX = "/usr/local/bin" all: aplat -aplat: aplat.o tampon.o - ${CC} ${COPT} -o "$@" aplat.o tampon.o +aplat: aplat.o tampon.o etq.o txt.o + ${CC} ${COPT} -o "$@" aplat.o tampon.o etq.o txt.o install: aplat install -m 755 aplat ${PREFIX}/aplat diff --git a/aplat.c b/aplat.c @@ -1,26 +1,40 @@ #include <assert.h> #include <stdio.h> #include <stdlib.h> -#include <unistd.h> #include "tampon.h" +#include "etq.h" +#include "txt.h" -#define TAILLE_ETQ 4096 /* taille initiale du tampon à étiquettes */ -#define TAILLE_TXT 4096 /* taille initiale du tampon à texte */ +#define TLL_ETQ 4096 /* taille initiale du tampon à étiquettes */ +#define TLL_TXT 4096 /* taille initiale du tampon à texte */ -struct tampon etq; /* tampon à étiquettes */ -struct tampon txt; /* tampon à texte */ +#define PENTE_DESC 0 +#define PENTE_EMRG 1 -int rec_etq(void); -int manger_espaces(FILE *f); -int transformer(FILE *f);; -int guillemets(FILE *f, struct tampon *); +void utilisation(void); +int transformer(FILE *); +int manger_espaces(FILE *); +int guillemets(FILE *, struct tampon *); + +char *nom_prog; /* nom du programme */ + +struct tampon etq; /* tampon à étiquettes */ +struct tampon txt; /* tampon à texte */ int -main(void) +main(int argc, char **argv) { + if ((nom_prog = argv[0]) == NULL || nom_prog[0] == '\0') + nom_prog = "aplat"; + + if (argc > 1) { + utilisation(); + return 1; + } + /* initialiser les tampons */ - if (t_init(&txt, TAILLE_TXT) < 0 || t_init(&etq, TAILLE_ETQ) < 0) + if (tp_init(&etq, TLL_ETQ) < 0 || tp_init(&txt, TLL_TXT) < 0) return 1; if (transformer(stdin) < 0) @@ -29,103 +43,90 @@ main(void) return 0; } -/* effacer le domaine cadet */ -int -rec_etq(void) +void +utilisation(void) { - assert(etq.pcar > etq.t); - /* prend aussi pour acquis que le format des domaines est respecté */ - while (--etq.pcar > etq.t) - if (*etq.pcar == ':' && *--etq.pcar == '\\') { - if (etq.pcar != etq.t && *(etq.pcar-1) == '\\') - continue; - break; - } - etq.ncar = etq.pcar - etq.t; - assert(etq.pcar >= etq.t); - return 0; + printf("UTILISATION: %s <[fichier]\n", nom_prog); } int transformer(FILE *f) { int c; - int prfd = 0; /* profondeur */ - int aff = 0; /* si étiquettes ont été affichées */ - int pente; + int prfd; /* profondeur */ + + assert(f != NULL); + + prfd = 0; if ((c = manger_espaces(f)) == EOF) return 0; if (c != '(') { - fprintf(stderr, "aplat: le premier caractère doit être \"(\"\n"); + fprintf(stderr, + "%s: le premier caractère affichable doit être « ( »\n", + nom_prog); return -1; } - + ouv: prfd++; - pente = 1; - if (aff) { - putc('\t', stdout); - t_aff(&txt); - t_eff(&txt); - putc('\n', stdout); - aff = 0; - } - t_ecr('\\', &etq); - t_ecr(':', &etq); + tp_ecr(':', &etq); if ((c = manger_espaces(f)) == EOF) goto deseq; do { switch (c) { - case ' ': case '\n': case '\t': + case ' ': case '\t': case '\n': + tp_etq_aff(&etq); + fputs("\t(", stdout); goto val; case '(': + tp_etq_aff(&etq); + fputs("\t(\t\n", stdout); goto ouv; case ')': - t_aff(&etq); - printf(":\t()\n"); + tp_etq_aff(&etq); + fputs("\t()\t\n", stdout); goto ferm; case '"': if (guillemets(f, &etq) == EOF) goto deseq; - break; + continue; case '\\': if ((c = getc(f)) == EOF) goto deseq; if (c == '\\') - t_ecr(c, &etq); - /* passe à default */ + tp_ecr('\\', &etq); + tp_ecr(c, &etq); + continue; + case ':': + tp_etq_aff(&etq); + fputs("\t(\t\n", stdout); + prfd++; + tp_ecr('\\', &etq); default: - t_ecr(c, &etq); + tp_ecr(c, &etq); } } while ((c = getc(f)) != EOF); - goto deseq; val: - if ((c = manger_espaces(f)) == EOF) - goto deseq; - - if (c != '(' || pente > 0) { - t_aff(&etq); - putc(':', stdout); - aff = 1; - putc('\t', stdout); - if (pente > 0) { - putc('(', stdout); - pente = 0; /* ??? */ - } - } - do { switch (c) { - case ' ': case '\n': case '\t': /* ignorer les espaces */ + case ' ': case '\t': case '\n': continue; case '(': + putc('\t', stdout); + tp_txt_aff(&txt); + tp_eff(&txt); + putc('\n', stdout); goto ouv; case ')': + fputs(")\t", stdout); + tp_txt_aff(&txt); + tp_eff(&txt); + putc('\n', stdout); goto ferm; case '"': if (guillemets(f, &txt) == EOF) @@ -135,37 +136,58 @@ val: if ((c = getc(f)) == EOF) goto deseq; if (c == '\\') - t_ecr('\\', &txt); - /* passe à default */ + tp_ecr('\\', &txt); + /* CASCADE */ default: - t_ecr(c, &txt); + tp_ecr(c, &txt); } } while ((c = getc(f)) != EOF); goto deseq; ferm: - if (aff) { - putc(')', stdout); + if (--prfd == 0) + goto fin; + assert(prfd > 0); + + while (tp_etq_rec(&etq) != ETQ_SEP_REEL) { + tp_etq_aff(&etq); + fputs("\t)\t\n", stdout); + if (--prfd == 0) + goto fin; + } + + if ((c = manger_espaces(f)) == EOF) + goto deseq; + switch (c) { + case '(': + goto ouv; + case ')': + tp_etq_aff(&etq); + fputs("\t)\t\n", stdout); + goto ferm; + default: + tp_etq_aff(&etq); putc('\t', stdout); - t_aff(&txt); - t_eff(&txt); - putc('\n', stdout); - aff = 0; + goto val; } - rec_etq(); - pente = -1; - if (--prfd == 0) - goto verif; + goto val; -verif: - if (manger_espaces(f) != EOF) { - fprintf(stderr, "aplat: le dernier caractère doit être \")\"\n"); +fin: + switch (manger_espaces(f)) { + case EOF: + return 0; + case '(': case ')': + goto deseq; + default: + fprintf(stderr, + "%s: le dernier caractère affichable doit être « ) »\n", + nom_prog); return -1; } - return 0; + deseq: - fprintf(stderr, "aplat: parenthèses déséquilibrées (%d)\n", prfd); + fprintf(stderr, "%s: parenthèses déséquilibrées\n", nom_prog); return -1; } @@ -173,37 +195,41 @@ int manger_espaces(FILE *f) { int c; + assert(f != NULL); - while ((c = getc(f)) == ' '|| c == '\n' || c == '\t') - if (c == EOF) break; + + while ((c = getc(f)) == ' ' || c == '\n' || c == '\t') + if (c == EOF) + break; return c; } int -guillemets(FILE *f, struct tampon *t) +guillemets(FILE *f, struct tampon *tp) { int c; + assert(f != NULL); - assert(t != NULL); + assert(tp != NULL); + while ((c = getc(f)) != '"' && c != EOF) { switch (c) { case '\n': - t_ecr('\\', t); - t_ecr('n', t); + tp_ecr('\\', tp); + tp_ecr('n', tp); continue; case '\t': - t_ecr('\\', t); - t_ecr('t', t); + tp_ecr('\\', tp); + tp_ecr('t', tp); continue; case '\\': if ((c = getc(f)) == EOF) return EOF; if (c == '\\') - t_ecr('\\', t); - /* passe à default */ + tp_ecr('\\', tp); + /* CASCADE */ default: - t_ecr(c, t); - continue; + tp_ecr(c, tp); } } return c; diff --git a/etq.c b/etq.c @@ -0,0 +1,49 @@ +#include <assert.h> +#include <stdio.h> + +#include "etq.h" +#include "tampon.h" + +/* afficher le contenu d'un tampon etq en sortie standard */ +int +tp_etq_aff(struct tampon *tp) +{ + char *c; + + assert(tp != NULL); + assert(tp->tp != NULL); + assert(tp->pc != NULL); + assert(tp->pc - tp->tp > 0); + assert(*tp->tp == ':'); + + for (c = tp->tp; c < tp->pc; c++) { + if (*c == '\\') + /* les autres /\\./ doivent être préservés */ + if (*++c != ':') + putc('\\', stdout); + if (putc(*c, stdout) < 0) + return -1; + } + putc(':', stdout); + return 0; +} + +/* supprimer le domaine cadet */ +int +tp_etq_rec(struct tampon *tp) +{ + assert(tp != NULL); + assert(tp->tp != NULL); + assert(tp->pc != NULL); + assert(tp->pc - tp->tp > 1); + assert(*tp->tp == ':'); + + --tp->pc; + while (*--tp->pc != ':') + ; + if (tp->pc - tp->tp != 0 && *(tp->pc-1) == '\\') { + --tp->pc; + return ETQ_SEP_FICT; + } + return ETQ_SEP_REEL; +} diff --git a/etq.h b/etq.h @@ -0,0 +1,12 @@ +#ifndef ETQ_H +#define ETQ_H + +#include "tampon.h" + +#define ETQ_SEP_REEL 0 /* séparateur réel */ +#define ETQ_SEP_FICT 1 /* séparateur fictif (échappé) */ + +int tp_etq_aff(struct tampon *); +int tp_etq_rec(struct tampon *); + +#endif diff --git a/tampon.c b/tampon.c @@ -1,61 +1,64 @@ -#include <stdio.h> +#include <assert.h> #include <stdlib.h> #include "tampon.h" -#undef t_ecr -/* initialiser un tampon t de taille taille */ +/* initialiser le tampon tp de taille tll */ int -t_init(struct tampon *t, size_t taille) +tp_init(struct tampon *tp, size_t tll) { - if ((t->t = malloc(taille)) == NULL) + assert(tll >= 1); + assert(tp != NULL); + + if ((tp->tp = tp->pc = malloc(tll)) == NULL) return -1; - t->taille = taille; - t->pcar = t->t; - t->ncar = 0; + tp->tll = tll; return 0; } -/* ajouter un caractère au tampon t */ +/* ajouter le caractère c au tampon tp */ int -t_ecr(char c, struct tampon *t) +tp_ecr(char c, struct tampon *tp) { - return ((++t->ncar > t->taille) ? t_plein(c, t) : - (*t->pcar++ = c, (unsigned char) c)); + assert(tp != NULL); + assert(tp->tp != NULL); + assert(tp->pc != NULL); + assert(tp->pc - tp->tp >= 0); + assert((size_t) (tp->pc - tp->tp) <= tp->tll); + + if ((size_t) (tp->pc - tp->tp) == tp->tll) /* le tampon est-il plein? */ + return tp_plein(c, tp); + return (unsigned char) (*tp->pc++ = c); } -/* agrandir le tampon t par T_FACT_AGR */ +/* agrandir le tampon tp et y ajouter le caractère c */ int -t_plein(char c, struct tampon *t) +tp_plein(char c, struct tampon *tp) { - if ((t->t = realloc(t->t, t->taille * T_FACT_AGR)) == NULL) + size_t diff; + + assert(tp != NULL); + assert(tp->tp != NULL); + assert(tp->pc != NULL); + assert(tp->pc - tp->tp >= 0); + assert(tp->tll >= 1); + assert(tp->tll * TP_FACT_AGR > tp->tll); /* doit grandir */ + + diff = tp->pc - tp->tp; + if ((tp->tp = realloc(tp->tp, tp->tll * TP_FACT_AGR)) == NULL) return -1; - t->taille *= T_FACT_AGR; - t->pcar = t->t + t->ncar - 1; - *t->pcar++ = c; - return (unsigned char) c; + tp->tll *= TP_FACT_AGR; + tp->pc = tp->tp + diff; /* tp->tp pourrait avoir changé */ + return (unsigned char) (*tp->pc++ = c); } -/* afficher le contenu du tampon t */ +/* effacer le contenu du tampon tp */ void -t_aff(struct tampon *t) +tp_eff(struct tampon *tp) { - char *pcar = t->t; - int ncar = t->ncar; - while (ncar-- > 0) { - if (*pcar == '\\') { - ncar--; - if (*++pcar != ':') - putc('\\', stdout); - } - putc(*pcar++, stdout); - } -} + assert(tp != NULL); + assert(tp->tp != NULL); + assert(tp->pc != NULL); -/* effacer le contenu du tampon t */ -void -t_eff(struct tampon *t) -{ - t->pcar = t->t; - t->ncar = 0; + tp->pc = tp->tp; } diff --git a/tampon.h b/tampon.h @@ -1,24 +1,17 @@ #ifndef TAMPON_H #define TAMPON_H -#define T_FACT_AGR 2 /* facteur d'agrandissement d'un tampon */ +#define TP_FACT_AGR 2 /* facteur d'agrandissement d'un tampon */ struct tampon { - char *t; /* le tampon lui-même */ - char *pcar; /* ptr vers le prochain caractère */ - size_t taille; /* taille du tampon */ - size_t ncar; /* nombre de caractères écrits */ + char *tp; /* le tampon lui-même */ + char *pc; /* ptr vers la prochaine cellule libre */ + size_t tll; /* taille du tampon */ }; -int t_init(struct tampon *, size_t taille); -int t_ecr(char c, struct tampon *); -void t_aff(struct tampon *); -void t_eff(struct tampon *); -int t_plein(char c, struct tampon *); - -#define t_ecr(c, t) \ - ((++(t)->ncar > (t)->taille) ? \ - t_plein((c), (t)) : \ - (*(t)->pcar++ = (c), (unsigned char) (c))) +int tp_init(struct tampon *, size_t taille); +int tp_ecr(char c, struct tampon *); +int tp_plein(char c,struct tampon *); +void tp_eff(struct tampon *); #endif diff --git a/txt.c b/txt.c @@ -0,0 +1,21 @@ +#include <assert.h> +#include <stdio.h> + +#include "tampon.h" +#include "txt.h" + +/* afficher le contenu d'un tampon txt en sortie standard */ +int +tp_txt_aff(struct tampon *tp) +{ + char *c; + + assert(tp != NULL); + assert(tp->tp != NULL); + assert(tp->pc != NULL); + + for (c = tp->tp; c < tp->pc; c++) + if (putc(*c, stdout) < 0) + return -1; + return 0; +} diff --git a/txt.h b/txt.h @@ -0,0 +1,8 @@ +#ifndef TXT_H +#define TXT_H + +#include "tampon.h" + +int tp_txt_aff(struct tampon *); + +#endif