summaryrefslogtreecommitdiff
path: root/lib/meta.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/meta.c')
-rw-r--r--lib/meta.c560
1 files changed, 560 insertions, 0 deletions
diff --git a/lib/meta.c b/lib/meta.c
new file mode 100644
index 0000000..7aa5add
--- /dev/null
+++ b/lib/meta.c
@@ -0,0 +1,560 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+#define _(x) x
+void exception(int, char *);
+char * Estrdup(char *);
+void * Emalloc(size_t);
+#endif
+#include "global.h"
+#include "numbers.h"
+#include "meta.h"
+
+static char meta_ops[] = ":.;(){}[=, ";
+static char meta_firsts[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_";
+static char meta_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789";
+
+phon_t *phons = NULL;
+field_t *fields = NULL;
+pattern_t *patterns = NULL;
+instruct_t *instructs = NULL;
+
+static int isident(char *word)
+{
+ if (!strchr(meta_firsts, *word)) {
+ return 0;
+ }
+ while (*word) {
+ if (!strchr(meta_chars, *(word++))) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static char *getword(char *line, char *p)
+{
+ char o;
+
+ do {
+ o = *(p++) = *line;
+ line++;
+ } while ((*line) && (!strchr(meta_ops, o)) && (!strchr(meta_ops, *line)));
+ *p = '\0';
+ return line;
+}
+
+void meta_parse_line(char *line)
+{
+ char buffer[BUFSIZ], *first = NULL, m = 0, *p1 = NULL, *p2 = NULL, *Fnames[MAXF], *Fimplicits[MAXF],
+ *Snames[MAXF], *Sinames[MAXF], gotname = 0, goteoi = 0;
+ phon_t *phon = NULL;
+ field_t *field = NULL;
+ pattern_t *pattern = NULL;
+ instruct_t *instruct = NULL;
+ metaexpr_t *metaexpr = NULL, *tmetaexpr, *tabmetaexpr[MAXM];
+ int Fsizes[MAXF], Fvalues[MAXF], Itypes[MAXF], Etypes[MAXF], nbfields = 0, valid, i, nbimplicit = 0;
+
+ if (*line == '#') {
+ return;
+ }
+ while (*line) {
+ line = getword(line, buffer);
+ if (!m) {
+ if (*line != ':') {
+ exception(1, _("Missing operator ':'"));
+ }
+ line++;
+ switch (buffer[0]) {
+ case 'F':
+ first = Estrdup(&buffer[1]);
+ m = 1;
+ break;
+ case 'P':
+ first = Estrdup(&buffer[1]);
+ pattern = (pattern_t *) Emalloc(sizeof(pattern_t));
+ pattern->name = first;
+ pattern->next = NULL;
+ m = 2;
+ break;
+ case 'p':
+ m = 3;
+ break;
+ case 'I':
+ m = 4;
+ break;
+ }
+ } else {
+ switch (m) {
+ case 1: /* Champ */
+ if (gotname) {
+ Fsizes[nbfields++] = char_to_number(buffer, &valid);
+ if (!valid) {
+ exception(1, _("Invalid number."));
+ }
+ if (*line) {
+ if (*line != ';') {
+ exception(1, _("Expecting ';' for field separator."));
+ }
+ line++;
+ gotname = 0;
+ } else {
+ field = (field_t *) Emalloc(sizeof(field_t));
+ field->next = fields->next;
+ fields->next = field;
+ field->name = first;
+ field->names = (char **) Emalloc(nbfields * sizeof(char *));
+ field->sizes = (int *) Emalloc(nbfields * sizeof(int));
+ for (i = 0; i < nbfields; i++) {
+ field->names[i] = Fnames[i];
+ field->sizes[i] = Fsizes[i];
+ }
+ field->nbr = nbfields;
+ }
+ } else {
+ if (*line != ',') {
+ exception(1, _("Expecting ',' for field separator."));
+ }
+ line++;
+ Fnames[nbfields] = Estrdup(buffer);
+ gotname = 1;
+ }
+ break;
+ case 2: /* Pattern */
+ if (*buffer == '[') {
+ tmetaexpr = (metaexpr_t *) Emalloc(sizeof(metaexpr_t));
+ tmetaexpr->name = NULL;
+ tmetaexpr->string = NULL;
+ tmetaexpr->left = metaexpr;
+ metaexpr = tmetaexpr;
+ } else {
+ tmetaexpr = (metaexpr_t *) Emalloc(sizeof(metaexpr_t));
+ tmetaexpr->left = tmetaexpr->right = NULL;
+ tmetaexpr->type = 0;
+ if (*buffer == '.') {
+ tmetaexpr->type = 1;
+ line = getword(line, buffer);
+ }
+ if (!isident(buffer)) {
+ exception(1, _("Identifier incorrect."));
+ }
+ tmetaexpr->name = Estrdup(buffer);
+ if (*line == '=') {
+ if (*(++line) != '.') {
+ exception(1, _("Error: Expecting a . after a ="));
+ }
+ line = getword(++line, buffer);
+ if (!isident(buffer)) {
+ exception(1, _("Identifier incorrect."));
+ }
+ tmetaexpr->string = Estrdup(buffer);
+ } else {
+ tmetaexpr->string = NULL;
+ }
+
+ if (metaexpr) {
+ metaexpr->right = tmetaexpr;
+ } else {
+ metaexpr = tmetaexpr;
+ }
+ if (*line == ';' || !*line) {
+ tabmetaexpr[nbfields++] = metaexpr;
+ if (*line) line++;
+ metaexpr = NULL;
+ }
+ if (!*line) {
+ pattern = (pattern_t *) Emalloc(sizeof(pattern_t));
+ pattern->next = patterns->next;
+ patterns->next = pattern;
+ pattern->name = first;
+ pattern->expr = (metaexpr_t **) Emalloc(nbfields * sizeof(metaexpr_t *));
+ for (i = 0; i < nbfields; i++) {
+ pattern->expr[i] = tabmetaexpr[i];
+ }
+ pattern->nbr = nbfields;
+ }
+ }
+ break;
+ case 3: /* Phonème */
+ if (p1) {
+ if (p2) {
+ exception(1, _("Extra parameters for field 'p'."));
+ } else {
+ if (isident(buffer)) {
+ p2 = Estrdup(buffer);
+ } else {
+ exception(1, _("Identifier incorrect."));
+ }
+ if (*line) {
+ exception(1, _("Unexpected char at end of line."));
+ }
+
+ phon = (phon_t *) Emalloc(sizeof(phon_t));
+ phon->next = phons->next;
+ phons->next = phon;
+ phon->p1 = p1;
+ phon->p2 = p2;
+ }
+ } else {
+ if (isident(buffer)) {
+ p1 = Estrdup(buffer);
+ if (*line != '=') {
+ exception(1, _("Expecting operator '=' for field 'p'."));
+ }
+ line++;
+ } else {
+ exception(1, _("Identifier incorrect."));
+ }
+ }
+ break;
+ case 4: /* Instruction */
+ if (!goteoi) {
+ if (isident(buffer) || (*buffer == '.')) {
+ Etypes[nbfields] = 0;
+ if (*buffer == '.') {
+ Etypes[nbfields] = 1;
+ line = getword(line, buffer);
+ }
+ Fnames[nbfields] = Estrdup(buffer);
+ if (*line == '=') {
+ if (*(++line) != '.') {
+ exception(1, _("Error: character . expected."));
+ }
+ line = getword(++line, buffer);
+ if (!isident(buffer)) {
+ exception(1, _("Identifier incorrect."));
+ }
+ Snames[nbfields] = Estrdup(buffer);
+ } else {
+ Snames[nbfields] = NULL;
+ }
+ nbfields++;
+ if (*line == ';') {
+ goteoi = 1;
+ line++;
+ }
+ }
+ } else {
+ if (!isident(buffer)) {
+ exception(1, _("Identifier incorrect."));
+ }
+ Fimplicits[nbimplicit] = Estrdup(buffer);
+ if (*line != '=') {
+ exception(1, _("= expected after an implicit name"));
+ }
+ line = getword(++line, buffer);
+
+ if (*buffer == '.') {
+ Itypes[nbimplicit] = 1;
+ line = getword(line, buffer);
+ if (!isident(buffer)) {
+ exception(1, _("Identifier incorrect"));
+ }
+ Sinames[nbimplicit] = Estrdup(buffer);
+ } else {
+ Sinames[nbimplicit] = NULL;
+ Itypes[nbimplicit] = 2;
+ Fvalues[nbimplicit] = char_to_number(buffer, &valid);
+ if (!valid) {
+ if (!isident(buffer)) {
+ exception(1, _("Identifier incorrect"));
+ }
+ Sinames[nbimplicit] = Estrdup(buffer);
+ Itypes[nbimplicit] = 0;
+ }
+ }
+ nbimplicit++;
+
+ if (*line) {
+ if (*line != ';') {
+ exception(1, _("expecting ; as field separator"));
+ }
+ line++;
+ } else {
+ instruct = (instruct_t *) Emalloc(sizeof(instruct_t));
+ instruct->next = instructs->next;
+ instructs->next = instruct;
+ instruct->names = (char **) Emalloc(nbfields * sizeof(char *));
+ instruct->strings = (char **) Emalloc(nbfields * sizeof(char *));
+ instruct->etypes = (int *) Emalloc(nbfields * sizeof(int));
+ instruct->implicits = (char **) Emalloc(nbimplicit * sizeof(char *));
+ instruct->ivalues = (int *) Emalloc(nbimplicit * sizeof(int));
+ instruct->istrings = (char **) Emalloc(nbimplicit * sizeof(char *));
+ instruct->itypes = (int *) Emalloc(nbimplicit * sizeof(int));
+ for (i = 0; i < nbfields; i++) {
+ instruct->names[i] = Fnames[i];
+ instruct->strings[i] = Snames[i];
+ instruct->etypes[i] = Etypes[i];
+ }
+ instruct->nbexplicit = nbfields;
+ for (i = 0; i < nbimplicit; i++) {
+ instruct->implicits[i] = Fimplicits[i];
+ instruct->ivalues[i] = Fvalues[i];
+ instruct->istrings[i] = Sinames[i];
+ instruct->itypes[i] = Itypes[i];
+ }
+ instruct->nbimplicit = nbimplicit;
+ goteoi = 0;
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+int meta_init(void)
+{
+ if (!(phons = (phon_t *) malloc(sizeof(phon_t)))) {
+ return -1;
+ }
+ phons->p1 = phons->p2 = NULL;
+ phons->next = NULL;
+
+ if (!(fields = (field_t *) malloc(sizeof(field_t)))) {
+ return -1;
+ }
+ fields->name = NULL;
+ fields->names = NULL;
+ fields->sizes = NULL;
+ fields->next = NULL;
+
+ if (!(patterns = (pattern_t *) malloc(sizeof(pattern_t)))) {
+ return -1;
+ }
+ patterns->name = NULL;
+ patterns->expr = NULL;
+ patterns->next = NULL;
+
+ if (!(instructs = (instruct_t *) malloc(sizeof(instruct_t)))) {
+ return -1;
+ }
+ instructs->names = NULL;
+ instructs->strings = NULL;
+ instructs->etypes = NULL;
+ instructs->implicits = NULL;
+ instructs->ivalues = NULL;
+ instructs->istrings = NULL;
+ instructs->itypes = NULL;
+
+ return 0;
+}
+
+static void recurs_free_phon(phon_t * phon) {
+ if (phon->next) {
+ recurs_free_phon(phon->next);
+ }
+
+ free(phon->p1);
+ free(phon->p2);
+ free(phon);
+}
+
+static void recurs_free_field(field_t * field) {
+ int i;
+
+ if (field->next) {
+ recurs_free_field(field->next);
+ }
+
+ free(field->name);
+ for (i = 0; i < field->nbr; i++) {
+ free(field->names[i]);
+ }
+ free(field->names);
+ free(field->sizes);
+ free(field);
+}
+
+static void recurs_free_metaexpr(metaexpr_t * metaexpr) {
+ if (metaexpr->left) {
+ recurs_free_metaexpr(metaexpr->left);
+ }
+
+ if (metaexpr->right) {
+ recurs_free_metaexpr(metaexpr->right);
+ }
+
+ if (metaexpr->name) {
+ free(metaexpr->name);
+ }
+
+ if (metaexpr->string) {
+ free(metaexpr->string);
+ }
+
+ free(metaexpr);
+}
+
+static void recurs_free_pattern(pattern_t * pattern) {
+ int i;
+
+ if (pattern->next) {
+ recurs_free_pattern(pattern->next);
+ }
+
+ free(pattern->name);
+ for (i = 0; i < pattern->nbr; i++) {
+ recurs_free_metaexpr(pattern->expr[i]);
+ }
+ free(pattern->expr);
+ free(pattern);
+}
+
+static void recurs_free_instruct(instruct_t * instruct) {
+ int i;
+
+ if (instruct->next) {
+ recurs_free_instruct(instruct->next);
+ }
+
+ for (i = 0; i < instruct->nbexplicit; i++) {
+ free(instruct->names[i]);
+ if (instruct->strings[i]) {
+ free(instruct->strings[i]);
+ }
+ }
+
+ for (i = 0; i < instruct->nbimplicit; i++) {
+ free(instruct->implicits[i]);
+ free(instruct->istrings[i]);
+ }
+
+ free(instruct->names);
+ free(instruct->strings);
+ free(instruct->etypes);
+ free(instruct->implicits);
+ free(instruct->istrings);
+ free(instruct->itypes);
+ free(instruct);
+}
+
+void meta_flush(void) {
+ if (phons->next) recurs_free_phon(phons->next);
+ if (fields->next) recurs_free_field(fields->next);
+ if (patterns->next) recurs_free_pattern(patterns->next);
+ if (instructs->next) recurs_free_instruct(instructs->next);
+ free(phons);
+ free(fields);
+ free(patterns);
+ free(instructs);
+ phons = NULL;
+ fields = NULL;
+ patterns = NULL;
+ instructs = NULL;
+}
+
+#ifndef HAVE_CONFIG_H
+char * Estrdup(char * o) {
+ char * r;
+
+ if (!(r = strdup(o))) {
+ exception(1, _("Out of memory."));
+ }
+ return r;
+}
+
+void * Emalloc(size_t s) {
+ void * r;
+
+ if (!(r = malloc(s))) {
+ exception(1, _("Out of memory."));
+ }
+ return r;
+}
+
+void exception(int level, char *msg)
+{
+ fprintf(stderr, "%s\n", msg);
+ exit(level);
+}
+
+void main(void)
+{
+ FILE *f;
+ char buf[BUFSIZ], *p;
+ phon_t *phon;
+ field_t *field;
+ pattern_t *pattern;
+ instruct_t *instruct;
+ int i;
+
+ if (meta_init())
+ exception(1, _("Meta parser init failed."));
+
+ f = fopen("instructions.txt", "r");
+ while (fgets(buf, BUFSIZ, f)) {
+ if ((p = strchr(buf, '\n'))) {
+ *p = '\0';
+ }
+ meta_parse_line(buf);
+ }
+
+ fprintf(stderr, "\nListe des phonèmes:\n");
+ for (phon = phons->next; phon; phon = phon->next) {
+ fprintf(stderr, " o %s <===> %s\n", phon->p1, phon->p2);
+ }
+
+ fprintf(stderr, "\nListe des champs:\n");
+ for (field = fields->next; field; field = field->next) {
+ fprintf(stderr, " o Champ nommé %s, contenant %i parties:\n", field->name, field->nbr);
+ for (i = 0; i < field->nbr; i++) {
+ fprintf(stderr, " + %s (%i bits)\n", field->names[i], field->sizes[i]);
+ }
+ }
+
+ fprintf(stderr, "\nListe des patterns:\n");
+ for (pattern = patterns->next; pattern; pattern = pattern->next) {
+ fprintf(stderr, " o Pattern nommée %s, contenant %i metaexpressions:\n", pattern->name, pattern->nbr);
+ for (i = 0; i < pattern->nbr; i++) {
+ fprintf(stderr, " + %s (%s) type: %s\n",
+ pattern->expr[i]->name ? pattern->expr[i]->name : "Opérateur [",
+ pattern->expr[i]->string ? pattern->expr[i]->string : "Aucune chaîne associée",
+ pattern->expr[i]->type ? "Constante prédéfinie" : pattern->expr[i]->left ? "Binaire" : pattern->expr[i]->right ? "Unaire" : "Feuille");
+ if (pattern->expr[i]->left) {
+ fprintf(stderr, " - gauche: %s (%s) type: %s\n",
+ pattern->expr[i]->left->name ? pattern->expr[i]->left->name : "Opérateur [",
+ pattern->expr[i]->left->string ? pattern->expr[i]->left->string : "Aucune chaîne associée",
+ pattern->expr[i]->left->type ? "Constante prédéfinie" : "Feuille");
+ }
+ if (pattern->expr[i]->right) {
+ fprintf(stderr, " - droite: %s (%s) type: %s\n",
+ pattern->expr[i]->right->name ? pattern->expr[i]->right->name : "Opérateur [",
+ pattern->expr[i]->right->string ? pattern->expr[i]->right->string : "Aucune chaîne associée",
+ pattern->expr[i]->right->type ? "Constante prédéfinie" : "Feuille");
+ }
+ }
+ }
+
+ fprintf(stderr, "\nListe des instructions:\n");
+ for (instruct = instructs->next; instruct; instruct = instruct->next) {
+ fprintf(stderr, " o Instruction contenant %i champs explicites et %i champs implicites.\n", instruct->nbexplicit, instruct->nbimplicit);
+ fprintf(stderr, " => Champs explicites.\n");
+ for (i = 0; i < instruct->nbexplicit; i++) {
+ fprintf(stderr, " + %s <= %s (type %s)\n",
+ instruct->names[i],
+ instruct->strings[i] ? instruct->strings[i] : "Pas de chaîne associée",
+ instruct->etypes[i] ? "prédéfinit" : "direct");
+ }
+ fprintf(stderr, " => Champs implicites.\n");
+ for (i = 0; i < instruct->nbimplicit; i++) {
+ switch (instruct->itypes[i]) {
+ case 0:
+ fprintf(stderr, " + %s <= %s (type direct)\n", instruct->implicits[i], instruct->istrings[i]);
+ break;
+ case 1:
+ fprintf(stderr, " + %s <= %i (type prédéfinit)\n", instruct->implicits[i], instruct->istrings[i]);
+ break;
+ case 2:
+ fprintf(stderr, " + %s <= %i (type valeur)\n", instruct->implicits[i], instruct->ivalues[i]);
+ break;
+ }
+ }
+ }
+}
+
+#endif