aroplat

Utilitaire pour manipuler le format aroplat (métaformat de plat)
git clone git://git.asteride.xyz/~ldp/aroplat.git
Journaux | Fichiers | Références | LICENCE

commit f93b9b8fb1cf00e4bce186f1f80d0c0cd7c4d17b
parent 68edfcc5dce129b5050b2ec62531257e4496bdda
Auteur: Selve <selve@asteride.xyz>
Date:   Wed, 14 Feb 2024 17:38:17 -0500

création d'un dépôt central pour aroplat

Bloquer change encore de nom: abattre.

Diffstat:
M.gitignore | 2+-
MLICENCE | 6+++---
MMakefile | 14+++++++-------
Aabattre.c | 444+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dbloquer.c | 444-------------------------------------------------------------------------------
5 files changed, 455 insertions(+), 455 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,3 +1,3 @@ *.o *.core -bloquer +abattre diff --git a/LICENCE b/LICENCE @@ -631,8 +631,8 @@ to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - bloquer, filtrage conditionnel pour aplat - Copyright (C) 2023 Selve + aroplat, utilitaires pour le format aroplat (variante d'aplat) + Copyright (C) 2023-2024, Selve This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: - bloquer Copyright (C) 2023 Selve + aroplat Copyright (C) 2023-2024, Selve This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. diff --git a/Makefile b/Makefile @@ -9,16 +9,16 @@ COPTS = -Wall -Wextra -Werror -Wpedantic --std=c89 ${COPTS_SPCL} .c.o: ${CC} ${COPTS} -c "$<" -all: bloquer +all: abattre -bloquer: bloquer.o meta.o tampon.o - ${CC} ${COPTS} -o "$@" bloquer.o meta.o tampon.o +abattre: abattre.o meta.o tampon.o + ${CC} ${COPTS} -o "$@" abattre.o meta.o tampon.o -install: bloquer - install -m 755 bloquer ${BIN_DOS}/bloquer +install: abattre + install -m 755 abattre ${BIN_DOS}/abattre uninstall: - rm -f ${PREFIX}/bloquer + rm -f ${PREFIX}/abattre clean: - rm -f bloquer *.o + rm -f abattre *.o diff --git a/abattre.c b/abattre.c @@ -0,0 +1,444 @@ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> + +#include "tampon.h" +#include "meta.h" + +#define MAX_VARS 32 /* nombre maximal de variables */ +#define TLL_VAR 32 /* taille initiale du tampon à variable */ +#define TLL_META 64 /* taille initiale du tampon à métadonnées */ +#define TLL_PLS 16 /* taille des piles */ + +/* drapeaux */ +#define DRAP_DEB 01 +#define DRAP_FIN 02 + +/* types d'étiquette*/ +#define ETQ_RIEN 0 +#define ETQ_SI 1 +#define ETQ_A 2 +#define ETQ_COND 3 + +/* opérateurs */ +/* en ordre de priorité */ +#define OP_OU 0 +#define OP_ET 1 +#define OP_NON 2 +#define OP_PAR 3 + +struct pl { + int ctn[TLL_PLS]; + int tete; +}; + +struct vars { + char *vars[MAX_VARS]; + int prch; +}; + +static int valider_var(char *); +static int noter_var(char *); +static int filtrer(FILE *); +static int valider_etqs(struct meta *); +static int trv_type_cadet(struct meta *); +static int ana_draps(struct meta *); +static void aff_etq(struct meta *); +static int evaluer(char *); +static int val_var(char **); +static int appliquer(int); +static int ign_bloc(FILE *); +static void utilisation(FILE *); + +struct tampon tamp_var; +struct meta tamp_meta; + +struct vars pl_vars = { {0}, 0 }; +struct pl pl_vals = { {0}, -1 }; +struct pl pl_ops = { {0}, -1 }; + +char *nom_prog; + +int +main(int argc, char **argv) +{ + int c; + + if ((nom_prog = argv[0]) == NULL || nom_prog[0] == '\0') + nom_prog = "abattre"; + + if (m_init(&tamp_meta, TLL_META) < 0 || tp_init(&tamp_var, TLL_VAR) < 0) + return 1; + + while ((c = getopt(argc, argv, "v:h")) != -1) { + switch (c) { + case 'v': + if (valider_var(optarg) < 0) + return 1; + if (noter_var(optarg) < 0) + return 1; + break; + case 'h': + utilisation(stdout); + return 0; + default: + utilisation(stderr); + return 1; + } + } + + if (filtrer(stdin) < 0) + return 1; + exit(0); +} + +static int +noter_var(char *arg) +{ + int i, j; + + for (i = 0; i < pl_vars.prch; i++) + for (j = 0; pl_vars.vars[i][j] == arg[j]; j++) + if (arg[j] == '=' || arg[j+1] == '\0') { + pl_vars.vars[i] = arg; + return 0; + } + if (pl_vars.prch < MAX_VARS) { + pl_vars.vars[pl_vars.prch++] = arg; + return 0; + } + + fprintf(stderr, "%s: trop de variables (maximum: %d)\n", + nom_prog, MAX_VARS); + return -1; +} + +static int +valider_var(char *arg) +{ + char *c; + + if (*arg == '=') { + fprintf(stderr, "%s: une variable ne peut commencer par « = »\n", + nom_prog); + return -1; + } + for (c = arg; *c != '\0'; c++) { + switch (*c) { + case '!': case '&': case '|': case ':': case '(': case ')': + fprintf(stderr, "%s: « %c » est un caractère réservé\n", + nom_prog, *c); + return -1; + } + } + + return 0; +} + +static int +filtrer(FILE *f) +{ + int c; + int draps; + int trouve; + char *pc; + + trouve = 0; + while (m_lire(f, &tamp_meta) > 0) { + if (valider_etqs(&tamp_meta) < 0) + return -1; + switch (trv_type_cadet(&tamp_meta)) { + case ETQ_RIEN: + aff_etq(&tamp_meta); + goto afficher; + case ETQ_SI: + draps = ana_draps(&tamp_meta); + if (draps & DRAP_DEB) + trouve = 0; + aff_etq(&tamp_meta); + if (trouve == 0) { + if (draps & DRAP_FIN) + trouve = 1; + goto afficher; + } + putc('\n', stdout); + break; + case ETQ_A: + break; + case ETQ_COND: + draps = ana_draps(&tamp_meta); + if (trouve == 1 && draps & DRAP_DEB) { + ign_bloc(f); + break; + } + pc = tp_deb(&tamp_meta.tp) + tamp_meta.draps - 2; + while (*--pc != '#') + ; + if (evaluer(pc+1)) { + trouve = 1; + aff_etq(&tamp_meta); + goto afficher; + } else { + ign_bloc(f); + } + break; + } + while ((c = getc(f)) != '\n') + if (c == EOF) + return 0; + continue; +afficher: + while ((c = putc(getc(f), stdout)) != '\n') + if (c == EOF) + return 0; + } + return 0; +} + +static int +valider_etqs(struct meta *m) +{ + if (*tp_deb(&m->tp) != ':') { + fprintf(stderr, "%s: fichier corrompu: le premier champ ne " + "commence pas par « : »\n", nom_prog); + return -1; + } + if (*(tp_deb(&m->tp) + m->draps - 2) != ':') { + fprintf(stderr, "%s: fichier corrompu: le dernier champ ne se " + "termine pas par « : »\n", nom_prog); + } + return 0; +} + +/* trouver le type de l'étiquette du domaine cadet */ +/* l'étiquette ne peut contenir « : » */ +static int +trv_type_cadet(struct meta *m) +{ + char *c = tp_deb(&m->tp) + m->draps - 2; + int n = 0; + if (c == tp_deb(&m->tp)) + return 0; + while (*--c != ':') + ; + c++; + if (*c == '#') { + c -= 2; + n++; + } + if (c - tp_deb(&m->tp) < 4) + return 0; + if (*c == '@') { + c -= 3; + n++; + } + else if (n == 1) + return 0; + if (*(c-1) == ':' && *c == 's' && *(c+1) == 'i' && *(c+2) == ':') + return n + 1; + return 0; +} + +static int +ana_draps(struct meta *m) +{ + char *c; + int draps; + for (draps = 0, c = tp_deb(&m->tp) + m->draps; *c != '\0'; c++) { + switch (*c) { + case '(': + draps |= DRAP_DEB; + break; + case ')': + draps |= DRAP_FIN; + break; + } + } + return draps; +} + +static void +aff_etq(struct meta *m) +{ + char *c; + int fini; /* si on fini avec « :si », « :@ » ou « :#* » */ + + fini = 0; + for (c = tp_deb(&m->tp); *c != '\0'; c++) { + fini = 0; + if (*c == ':') { + if (strncmp(c+1, "si:", 3) == 0) { + fini = 1; + c += 3; + if (strncmp(c+1, "@:", 2) == 0) { + c += 2; + if (*(c+1) == '#') { + for (c += 2; *c != ':'; c++) + ; + if (*(c+1) != '\0') { + c--; + continue; + } + } + } + } + } + putc(*c, stdout); + } + if (fini) + putc('\t', stdout); + else + printf("\t%s", tp_deb(&m->tp) + m->draps); +} + +/* ps doit pointer vers un '#' */ +static int +evaluer(char *ps) +{ + int op; + char *s = ps; + for (;;s++) { + switch (*s) { + case '!': + op = OP_NON; + break; + case '&': + op = OP_ET; + break; + case '|': + op = OP_OU; + break; + case '(': + op = OP_PAR; + break; + case ')': + while (pl_ops.tete >= 0) { + if (pl_ops.ctn[pl_ops.tete] == OP_PAR) { + pl_ops.tete--; + goto sortie; + } + if (appliquer(pl_ops.ctn[pl_ops.tete--]) < 0) + return -1; + } + return -1; +sortie: + continue; + case ':': + while (pl_ops.tete >= 0) + if (appliquer(pl_ops.ctn[pl_ops.tete--]) < 0) + return -1; + if (pl_vals.tete != 0) + return -1; + return pl_vals.ctn[pl_vals.tete--]; + default: + if (++pl_vals.tete >= TLL_PLS) { + fprintf(stderr, "%s: expression trop " + "complexe\n", nom_prog); + return -1; + } + if ((pl_vals.ctn[pl_vals.tete] = val_var(&s)) < 0) + return -1; + continue; + } + while (pl_ops.tete >= 0 && pl_ops.ctn[pl_ops.tete] != OP_PAR && + pl_ops.ctn[pl_ops.tete] != OP_NON && + pl_ops.ctn[pl_ops.tete] >= op) { + if (appliquer(pl_ops.ctn[pl_ops.tete--]) < 0) + return -1; + } + if (++pl_ops.tete >= TLL_PLS) + return -1; + pl_ops.ctn[pl_ops.tete] = op; + } + return -1; +} + +static int +val_var(char **ps) +{ + int i, j; + char *s = *ps; + tp_eff(&tamp_var); + for (i = 0; *s != '\0'; i++, s++) { + switch (*s) { + case '!': case '&': case '|': case ':': case '(': case ')': + goto trouver; + } + tp_ecr(*s, &tamp_var); + } + fprintf(stderr, "%s: le premier champ ne se termine pas par « : »\n", + nom_prog); + return -1; +trouver: + tp_ecr('\0', &tamp_var); + + *ps = --s; + for (i = 0; i < pl_vars.prch; i++) { + for (j = 0; pl_vars.vars[i][j] == tamp_var.tp[j]; j++) + if (tamp_var.tp[j] == '\0') + return 1; + } + return 0; +} + +static int +appliquer(int op) +{ + switch (op) { + case OP_NON: + if (pl_vals.tete >= 0) { + pl_vals.ctn[pl_vals.tete] = !pl_vals.ctn[pl_vals.tete]; + return 0; + } + break; + case OP_ET: + if (pl_vals.tete >=1) { + pl_vals.ctn[pl_vals.tete-1] = + pl_vals.ctn[pl_vals.tete-1] && + pl_vals.ctn[pl_vals.tete]; + pl_vals.tete--; + return 0; + } + break; + case OP_OU: + if (pl_vals.tete >= 1) { + pl_vals.ctn[pl_vals.tete-1] = + pl_vals.ctn[pl_vals.tete-1] || + pl_vals.ctn[pl_vals.tete]; + pl_vals.tete--; + return 0; + } + break; + } + fprintf(stderr, "%s: trop d'opérateurs\n", nom_prog); + return -1; +} + +static int +ign_bloc(FILE *f) +{ + int draps; + int c; + int niveau = 0; + do { + draps = ana_draps(&tamp_meta); + if (draps & DRAP_DEB) + niveau++; + if (draps & DRAP_FIN) + niveau--; + if (niveau == 0) + break; + while ((c = getc(f)) != '\n') + if (c == EOF) + return 0; + } while (m_lire(f, &tamp_meta) > 0); + return 0; +} + +static void +utilisation(FILE *f) +{ + fprintf(f, "UTILISATION: %s -v[variable][=valeur] [...] <[fichier]\n", + nom_prog); +} diff --git a/bloquer.c b/bloquer.c @@ -1,444 +0,0 @@ -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> - -#include "tampon.h" -#include "meta.h" - -#define MAX_VARS 32 /* nombre maximal de variables */ -#define TLL_VAR 32 /* taille initiale du tampon à variable */ -#define TLL_META 64 /* taille initiale du tampon à métadonnées */ -#define TLL_PLS 16 /* taille des piles */ - -/* drapeaux */ -#define DRAP_DEB 01 -#define DRAP_FIN 02 - -/* types d'étiquette*/ -#define ETQ_RIEN 0 -#define ETQ_SI 1 -#define ETQ_A 2 -#define ETQ_COND 3 - -/* opérateurs */ -/* en ordre de priorité */ -#define OP_OU 0 -#define OP_ET 1 -#define OP_NON 2 -#define OP_PAR 3 - -struct pl { - int ctn[TLL_PLS]; - int tete; -}; - -struct vars { - char *vars[MAX_VARS]; - int prch; -}; - -static int valider_var(char *); -static int noter_var(char *); -static int filtrer(FILE *); -static int valider_etqs(struct meta *); -static int trv_type_cadet(struct meta *); -static int ana_draps(struct meta *); -static void aff_etq(struct meta *); -static int evaluer(char *); -static int val_var(char **); -static int appliquer(int); -static int ign_bloc(FILE *); -static void utilisation(FILE *); - -struct tampon tamp_var; -struct meta tamp_meta; - -struct vars pl_vars = { {0}, 0 }; -struct pl pl_vals = { {0}, -1 }; -struct pl pl_ops = { {0}, -1 }; - -char *nom_prog; - -int -main(int argc, char **argv) -{ - int c; - - if ((nom_prog = argv[0]) == NULL || nom_prog[0] == '\0') - nom_prog = "bloquer"; - - if (m_init(&tamp_meta, TLL_META) < 0 || tp_init(&tamp_var, TLL_VAR) < 0) - return 1; - - while ((c = getopt(argc, argv, "v:h")) != -1) { - switch (c) { - case 'v': - if (valider_var(optarg) < 0) - return 1; - if (noter_var(optarg) < 0) - return 1; - break; - case 'h': - utilisation(stdout); - return 0; - default: - utilisation(stderr); - return 1; - } - } - - if (filtrer(stdin) < 0) - return 1; - exit(0); -} - -static int -noter_var(char *arg) -{ - int i, j; - - for (i = 0; i < pl_vars.prch; i++) - for (j = 0; pl_vars.vars[i][j] == arg[j]; j++) - if (arg[j] == '=' || arg[j+1] == '\0') { - pl_vars.vars[i] = arg; - return 0; - } - if (pl_vars.prch < MAX_VARS) { - pl_vars.vars[pl_vars.prch++] = arg; - return 0; - } - - fprintf(stderr, "%s: trop de variables (maximum: %d)\n", - nom_prog, MAX_VARS); - return -1; -} - -static int -valider_var(char *arg) -{ - char *c; - - if (*arg == '=') { - fprintf(stderr, "%s: une variable ne peut commencer par « = »\n", - nom_prog); - return -1; - } - for (c = arg; *c != '\0'; c++) { - switch (*c) { - case '!': case '&': case '|': case ':': case '(': case ')': - fprintf(stderr, "%s: « %c » est un caractère réservé\n", - nom_prog, *c); - return -1; - } - } - - return 0; -} - -static int -filtrer(FILE *f) -{ - int c; - int draps; - int trouve; - char *pc; - - trouve = 0; - while (m_lire(f, &tamp_meta) > 0) { - if (valider_etqs(&tamp_meta) < 0) - return -1; - switch (trv_type_cadet(&tamp_meta)) { - case ETQ_RIEN: - aff_etq(&tamp_meta); - goto afficher; - case ETQ_SI: - draps = ana_draps(&tamp_meta); - if (draps & DRAP_DEB) - trouve = 0; - aff_etq(&tamp_meta); - if (trouve == 0) { - if (draps & DRAP_FIN) - trouve = 1; - goto afficher; - } - putc('\n', stdout); - break; - case ETQ_A: - break; - case ETQ_COND: - draps = ana_draps(&tamp_meta); - if (trouve == 1 && draps & DRAP_DEB) { - ign_bloc(f); - break; - } - pc = tp_deb(&tamp_meta.tp) + tamp_meta.draps - 2; - while (*--pc != '#') - ; - if (evaluer(pc+1)) { - trouve = 1; - aff_etq(&tamp_meta); - goto afficher; - } else { - ign_bloc(f); - } - break; - } - while ((c = getc(f)) != '\n') - if (c == EOF) - return 0; - continue; -afficher: - while ((c = putc(getc(f), stdout)) != '\n') - if (c == EOF) - return 0; - } - return 0; -} - -static int -valider_etqs(struct meta *m) -{ - if (*tp_deb(&m->tp) != ':') { - fprintf(stderr, "%s: fichier corrompu: le premier champ ne " - "commence pas par « : »\n", nom_prog); - return -1; - } - if (*(tp_deb(&m->tp) + m->draps - 2) != ':') { - fprintf(stderr, "%s: fichier corrompu: le dernier champ ne se " - "termine pas par « : »\n", nom_prog); - } - return 0; -} - -/* trouver le type de l'étiquette du domaine cadet */ -/* l'étiquette ne peut contenir « : » */ -static int -trv_type_cadet(struct meta *m) -{ - char *c = tp_deb(&m->tp) + m->draps - 2; - int n = 0; - if (c == tp_deb(&m->tp)) - return 0; - while (*--c != ':') - ; - c++; - if (*c == '#') { - c -= 2; - n++; - } - if (c - tp_deb(&m->tp) < 4) - return 0; - if (*c == '@') { - c -= 3; - n++; - } - else if (n == 1) - return 0; - if (*(c-1) == ':' && *c == 's' && *(c+1) == 'i' && *(c+2) == ':') - return n + 1; - return 0; -} - -static int -ana_draps(struct meta *m) -{ - char *c; - int draps; - for (draps = 0, c = tp_deb(&m->tp) + m->draps; *c != '\0'; c++) { - switch (*c) { - case '(': - draps |= DRAP_DEB; - break; - case ')': - draps |= DRAP_FIN; - break; - } - } - return draps; -} - -static void -aff_etq(struct meta *m) -{ - char *c; - int fini; /* si on fini avec « :si », « :@ » ou « :#* » */ - - fini = 0; - for (c = tp_deb(&m->tp); *c != '\0'; c++) { - fini = 0; - if (*c == ':') { - if (strncmp(c+1, "si:", 3) == 0) { - fini = 1; - c += 3; - if (strncmp(c+1, "@:", 2) == 0) { - c += 2; - if (*(c+1) == '#') { - for (c += 2; *c != ':'; c++) - ; - if (*(c+1) != '\0') { - c--; - continue; - } - } - } - } - } - putc(*c, stdout); - } - if (fini) - putc('\t', stdout); - else - printf("\t%s", tp_deb(&m->tp) + m->draps); -} - -/* ps doit pointer vers un '#' */ -static int -evaluer(char *ps) -{ - int op; - char *s = ps; - for (;;s++) { - switch (*s) { - case '!': - op = OP_NON; - break; - case '&': - op = OP_ET; - break; - case '|': - op = OP_OU; - break; - case '(': - op = OP_PAR; - break; - case ')': - while (pl_ops.tete >= 0) { - if (pl_ops.ctn[pl_ops.tete] == OP_PAR) { - pl_ops.tete--; - goto sortie; - } - if (appliquer(pl_ops.ctn[pl_ops.tete--]) < 0) - return -1; - } - return -1; -sortie: - continue; - case ':': - while (pl_ops.tete >= 0) - if (appliquer(pl_ops.ctn[pl_ops.tete--]) < 0) - return -1; - if (pl_vals.tete != 0) - return -1; - return pl_vals.ctn[pl_vals.tete--]; - default: - if (++pl_vals.tete >= TLL_PLS) { - fprintf(stderr, "%s: expression trop " - "complexe\n", nom_prog); - return -1; - } - if ((pl_vals.ctn[pl_vals.tete] = val_var(&s)) < 0) - return -1; - continue; - } - while (pl_ops.tete >= 0 && pl_ops.ctn[pl_ops.tete] != OP_PAR && - pl_ops.ctn[pl_ops.tete] != OP_NON && - pl_ops.ctn[pl_ops.tete] >= op) { - if (appliquer(pl_ops.ctn[pl_ops.tete--]) < 0) - return -1; - } - if (++pl_ops.tete >= TLL_PLS) - return -1; - pl_ops.ctn[pl_ops.tete] = op; - } - return -1; -} - -static int -val_var(char **ps) -{ - int i, j; - char *s = *ps; - tp_eff(&tamp_var); - for (i = 0; *s != '\0'; i++, s++) { - switch (*s) { - case '!': case '&': case '|': case ':': case '(': case ')': - goto trouver; - } - tp_ecr(*s, &tamp_var); - } - fprintf(stderr, "%s: le premier champ ne se termine pas par « : »\n", - nom_prog); - return -1; -trouver: - tp_ecr('\0', &tamp_var); - - *ps = --s; - for (i = 0; i < pl_vars.prch; i++) { - for (j = 0; pl_vars.vars[i][j] == tamp_var.tp[j]; j++) - if (tamp_var.tp[j] == '\0') - return 1; - } - return 0; -} - -static int -appliquer(int op) -{ - switch (op) { - case OP_NON: - if (pl_vals.tete >= 0) { - pl_vals.ctn[pl_vals.tete] = !pl_vals.ctn[pl_vals.tete]; - return 0; - } - break; - case OP_ET: - if (pl_vals.tete >=1) { - pl_vals.ctn[pl_vals.tete-1] = - pl_vals.ctn[pl_vals.tete-1] && - pl_vals.ctn[pl_vals.tete]; - pl_vals.tete--; - return 0; - } - break; - case OP_OU: - if (pl_vals.tete >= 1) { - pl_vals.ctn[pl_vals.tete-1] = - pl_vals.ctn[pl_vals.tete-1] || - pl_vals.ctn[pl_vals.tete]; - pl_vals.tete--; - return 0; - } - break; - } - fprintf(stderr, "%s: trop d'opérateurs\n", nom_prog); - return -1; -} - -static int -ign_bloc(FILE *f) -{ - int draps; - int c; - int niveau = 0; - do { - draps = ana_draps(&tamp_meta); - if (draps & DRAP_DEB) - niveau++; - if (draps & DRAP_FIN) - niveau--; - if (niveau == 0) - break; - while ((c = getc(f)) != '\n') - if (c == EOF) - return 0; - } while (m_lire(f, &tamp_meta) > 0); - return 0; -} - -static void -utilisation(FILE *f) -{ - fprintf(f, "UTILISATION: %s -v[variable][=valeur] [...] <[fichier]\n", - nom_prog); -}