aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2004-02-13 14:21:02 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2004-02-13 14:21:02 +0000
commitcf6bfb57a877b35ffae958c2baa11fc4bebd93e5 (patch)
tree93f0d7b92a513a4b02bb6111675235fa5a8301d4 /src
parenteb7a03ba9271bf0956686e9e3ecad5b511b1d637 (diff)
downloadellinika-cf6bfb57a877b35ffae958c2baa11fc4bebd93e5.tar.gz
ellinika-cf6bfb57a877b35ffae958c2baa11fc4bebd93e5.tar.bz2
Initial revision
git-svn-id: file:///home/puszcza/svnroot/ellinika/trunk@2 941c8c0f-9102-463b-b60b-cd22ce0e6858
Diffstat (limited to 'src')
-rw-r--r--src/.gdbinit1
-rw-r--r--src/Makefile20
-rw-r--r--src/emit.c109
-rw-r--r--src/gram.y181
-rw-r--r--src/input.l54
-rw-r--r--src/list.c317
-rw-r--r--src/list.h48
-rw-r--r--src/main.c270
-rw-r--r--src/mem.h2
-rw-r--r--src/sql.c107
-rw-r--r--src/trans.h49
-rw-r--r--src/xcript.c137
12 files changed, 1295 insertions, 0 deletions
diff --git a/src/.gdbinit b/src/.gdbinit
new file mode 100644
index 0000000..9f53896
--- /dev/null
+++ b/src/.gdbinit
@@ -0,0 +1 @@
+set args -v -d ellinika ../data/dict.1
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..cfd269d
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,20 @@
+CFLAGS=-ggdb -I.
+
+trans: y.tab.o lex.yy.o main.c list.o sql.o xcript.o
+ cc -otrans -ggdb main.c y.tab.o lex.yy.o list.o sql.o xcript.o -ll -L/usr/local/lib/mysql -lmysqlclient
+
+y.tab.c y.tab.h: gram.y
+ yacc -vtd gram.y
+
+lex.yy.c: input.l
+ lex input.l
+
+lex.yy.o: lex.yy.c y.tab.h trans.h
+
+y.tab.o: trans.h
+
+list.o: list.c list.h
+
+sql.o: sql.c trans.h
+
+xcript.o: xcript.c trans.h \ No newline at end of file
diff --git a/src/emit.c b/src/emit.c
new file mode 100644
index 0000000..ff99700
--- /dev/null
+++ b/src/emit.c
@@ -0,0 +1,109 @@
+#include "trans.h"
+#include <unistd.h>
+
+static unsigned long dict_index;
+static unsigned long article_index;
+
+static RAD_LIST *antonym_list;
+
+int
+_emit_headers(void *item, void *data)
+{
+ struct header *hp = item;
+ if (hp->forms)
+ sql_query("INSERT INTO dict VALUES(%lu,'%s','%s','%s')",
+ dict_index, hp->key, hp->pos, hp->forms);
+ else
+ sql_query("INSERT INTO dict (ident,word,pos) VALUES(%lu,'%s','%s')",
+ dict_index, hp->key, hp->pos);
+ return 0;
+}
+
+static int
+_antonym_cmp(const void *item, const void *data)
+{
+ const struct antonym *a = item, *b = data;
+ return !(a->index == b->index && strcmp(a->value, b->value) == 0);
+}
+
+int
+insert_antonym(unsigned long dict_index, u_char *value)
+{
+ unsigned long index;
+ if (sql_query_n(&index,
+ "SELECT ident FROM dict WHERE word='%s'",
+ value) == 0) {
+ sql_query("REPLACE INTO antonym VALUES (%lu,%lu)",
+ index, dict_index);
+ sql_query("REPLACE INTO antonym VALUES (%lu,%lu)",
+ dict_index, index);
+ return 0;
+ }
+ return 1;
+}
+
+int
+_emit_descr(void *item, void *data)
+{
+ struct descr *descr = item;
+ unsigned long index;
+
+ switch (descr->type) {
+ case descr_topic:
+ if (sql_query_n(&index,
+ "SELECT ident FROM topic WHERE title='%s'",
+ descr->value)) {
+ sql_query("INSERT INTO topic (title) VALUES ('%s')",
+ descr->value);
+ sql_query_n(&index, "SELECT LAST_INSERT_ID()");
+ }
+ sql_query("INSERT INTO topic_tab VALUES(%lu,%lu)",
+ index, dict_index);
+ break;
+
+ case descr_meaning:
+ sql_query("INSERT INTO articles VALUES (%lu, %lu, '%s')",
+ dict_index,
+ article_index++,
+ descr->value);
+ break;
+
+ case descr_antonym:
+ if (insert_antonym(dict_index, descr->value)) {
+ struct antonym *p = emalloc(sizeof(*p));
+ p->index = dict_index;
+ p->value = descr->value;
+ list_append(antonym_list, p);
+ }
+ }
+ return 0;
+}
+
+static int
+cmp_descr_type(const void *a, const void *b)
+{
+ const struct descr *da = a, *db = b;
+ return da->type != db->type;
+}
+
+void
+emit_node(RAD_LIST *hdr, RAD_LIST *descr)
+{
+ article_index = 0;
+
+ list_iterate(hdr, _emit_headers, NULL);
+ list_iterate(descr, _emit_descr, NULL);
+
+ dict_index++;
+}
+
+int
+_antonym_fixup(void *item, void *data)
+{
+ struct antonym *ant = item;
+ if (insert_antonym(ant->index, ant->value)) {
+ fprintf(stderr, "unhandled antonym: %lu - \"%s\"\n",
+ ant->index, ant->value);
+ }
+ return 0;
+}
diff --git a/src/gram.y b/src/gram.y
new file mode 100644
index 0000000..c065bcf
--- /dev/null
+++ b/src/gram.y
@@ -0,0 +1,181 @@
+%{
+#include "trans.h"
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+#include <obstack.h>
+
+struct obstack stk;
+
+struct descr *make_descr(enum descr_type type, u_char *value);
+
+%}
+
+%token NODE POS END MEANING ALIAS ANT TOPIC FORMS XREF
+%token <string> STRING
+
+%type <string> string pos forms
+%type <header> nodehdr alias
+%type <descr> descr
+%type <list> aliases descrlist header
+
+%union {
+ u_char *string;
+ struct header *header;
+ struct descr *descr;
+ RAD_LIST *list;
+};
+
+
+%%
+
+input : list
+ ;
+
+list : node
+ | list node
+ ;
+
+node : header descrlist end
+ {
+ register_node($1, $2);
+ }
+ ;
+
+end : END
+ ;
+
+header : nodehdr
+ {
+ $$ = list_create();
+ list_append($$, $1);
+ }
+ | nodehdr aliases
+ {
+ list_prepend($2, $1);
+ $$ = $2;
+ }
+ ;
+
+nodehdr : NODE string pos forms
+ {
+ $$ = emalloc(sizeof(*$$));
+ $$->key = $2;
+ $$->pos = $3;
+ $$->forms = $4;
+ }
+ ;
+
+pos : /* empty */
+ {
+ $$ = NULL;
+ }
+ | POS string
+ {
+ $$ = $2;
+ }
+ ;
+
+forms : /* empty */
+ {
+ $$ = NULL;
+ }
+ | FORMS string
+ {
+ $$ = $2;
+ }
+ ;
+
+aliases : alias
+ {
+ $$ = list_create();
+ list_append($$, $1);
+ }
+ | aliases alias
+ {
+ list_append($1, $2);
+ $$ = $1;
+ }
+ ;
+
+alias : ALIAS string pos forms
+ {
+ $$ = emalloc(sizeof(*$$));
+ $$->key = $2;
+ $$->pos = $3;
+ $$->forms = $4;
+ }
+ ;
+
+descrlist: descr
+ {
+ $$ = list_create();
+ list_append($$, $1);
+ }
+ | descrlist descr
+ {
+ list_append($1, $2);
+ $$ = $1;
+ }
+ ;
+
+descr : TOPIC string
+ {
+ $$ = make_descr(descr_topic, $2);
+ }
+ | MEANING string
+ {
+ $$ = make_descr(descr_meaning, $2);
+ }
+ | ANT string
+ {
+ $$ = make_descr(descr_antonym, $2);
+ }
+ | XREF string
+ {
+ $$ = make_descr(descr_xref, $2);
+ }
+ ;
+
+string : mstring
+ {
+ obstack_1grow(&stk, 0);
+ $$ = obstack_finish(&stk);
+ }
+ ;
+
+mstring : STRING
+ {
+ obstack_grow(&stk, $1, strlen($1));
+ }
+ | mstring STRING
+ {
+ obstack_1grow(&stk, '\n');
+ obstack_grow(&stk, $2, strlen($2));
+ }
+ ;
+
+%%
+
+yyerror(char *s)
+{
+ fprintf (stderr, "%s:%d: %s\n",
+ file_name, input_line, s);
+}
+
+int
+parse(char *name)
+{
+ if (name)
+ open_input(name);
+ obstack_init(&stk);
+ return yyparse();
+}
+
+struct descr *
+make_descr(enum descr_type type, u_char *value)
+{
+ struct descr *p = emalloc(sizeof(*p));
+ p->type = type;
+ p->value = value;
+ return p;
+}
diff --git a/src/input.l b/src/input.l
new file mode 100644
index 0000000..542c897
--- /dev/null
+++ b/src/input.l
@@ -0,0 +1,54 @@
+%{
+#include "trans.h"
+#include "y.tab.h"
+
+char *file_name = "<stdin>";
+int input_line = 1;
+
+#define isws(c) ((c)==' ' || (c)=='\t')
+%}
+
+MWS [ \t]*
+WS [ \t]+
+%%
+#.*\n input_line++;
+^[nN][oO][dD][eE] return NODE;
+^[pP][oO][sS] return POS;
+^[eE][nN][dD] return END;
+^[mM][eE][aA][nN][iI][nN][gG] return MEANING;
+^[aA][lL][iI][aA][sS] return ALIAS;
+^[aA][nN][tT] return ANT;
+^[tT][oO][pP][iI][cC] return TOPIC;
+^[fF][oO][rR][mM][sS] return FORMS;
+^[xX][rR][eE][fF] return XREF;
+\n input_line++;
+{WS}[^\n]+\n {
+ char *p, *q;
+
+ for (p = yytext + yyleng - 1; p > yytext && isspace(*p); p--)
+ ;
+ p[1] = 0;
+ input_line++;
+ yylval.string = yytext+1;
+ return STRING;
+}
+. { fprintf (stderr, "%s:%d: stray character %c\n",
+ file_name, input_line, yytext[0]);
+ exit(1); }
+
+%%
+
+void
+open_input(char *name)
+{
+ yyin = fopen(name, "r");
+ if (!yyin) {
+ fprintf (stderr, "cannot open ");
+ perror (name);
+ exit (1);
+ }
+ file_name = name;
+}
+
+
+
diff --git a/src/list.c b/src/list.c
new file mode 100644
index 0000000..5d25a74
--- /dev/null
+++ b/src/list.c
@@ -0,0 +1,317 @@
+/* This file is part of GNU Radius.
+ Copyright (C) 2003 Free Software Foundation
+
+ GNU Radius is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ GNU Radius is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Radius; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <sys/types.h>
+#include <stdlib.h>
+#include <mem.h>
+#include <list.h>
+
+struct list_entry {
+ struct list_entry *next;
+ void *data;
+};
+
+struct list {
+ size_t count;
+ struct list_entry *head, *tail;
+ struct iterator *itr;
+};
+
+struct iterator {
+ struct iterator *next;
+ RAD_LIST *list;
+ struct list_entry *cur;
+ int advanced;
+};
+
+struct list *
+list_create()
+{
+ struct list *p = emalloc(sizeof(*p));
+ p->head = p->tail = NULL;
+ p->itr = NULL;
+ return p;
+}
+
+void
+list_destroy(struct list **plist, list_iterator_t user_free, void *data)
+{
+ struct list_entry *p;
+
+ if (!*plist)
+ return;
+
+ p = (*plist)->head;
+ while (p) {
+ struct list_entry *next = p->next;
+ if (user_free)
+ user_free(p->data, data);
+ efree(p);
+ p = next;
+ }
+ efree(*plist);
+ *plist = NULL;
+}
+
+void *
+iterator_current(ITERATOR *ip)
+{
+ if (!ip)
+ return NULL;
+ return ip->cur ? ip->cur->data : NULL;
+}
+
+ITERATOR *
+iterator_create(RAD_LIST *list)
+{
+ ITERATOR *itr;
+
+ if (!list)
+ return NULL;
+ itr = emalloc(sizeof(*itr));
+ itr->list = list;
+ itr->cur = NULL;
+ itr->next = list->itr;
+ itr->advanced = 0;
+ list->itr = itr;
+ return itr;
+}
+
+void
+iterator_destroy(ITERATOR **ip)
+{
+ ITERATOR *itr, *prev;
+
+ if (!ip || !*ip)
+ return;
+ for (itr = (*ip)->list->itr, prev = NULL;
+ itr;
+ prev = itr, itr = itr->next)
+ if (*ip == itr)
+ break;
+ if (itr) {
+ if (prev)
+ prev->next = itr->next;
+ else
+ itr->list->itr = itr->next;
+ efree(itr);
+ *ip = NULL;
+ }
+
+}
+
+void *
+iterator_first(ITERATOR *ip)
+{
+ if (!ip)
+ return NULL;
+ ip->cur = ip->list->head;
+ ip->advanced = 0;
+ return iterator_current(ip);
+}
+
+void *
+iterator_next(ITERATOR *ip)
+{
+ if (!ip || !ip->cur)
+ return NULL;
+ if (!ip->advanced)
+ ip->cur = ip->cur->next;
+ ip->advanced = 0;
+ return iterator_current(ip);
+}
+
+static void
+_iterator_advance(ITERATOR *ip, struct list_entry *e)
+{
+ for (; ip; ip = ip->next) {
+ if (ip->cur == e) {
+ ip->cur = e->next;
+ ip->advanced++;
+ }
+ }
+}
+
+void *
+list_item(struct list *list, size_t n)
+{
+ struct list_entry *p;
+ if (n >= list->count)
+ return NULL;
+ for (p = list->head; n > 0 && p; p = p->next, n--)
+ ;
+ return p->data;
+}
+
+size_t
+list_count(struct list *list)
+{
+ if (!list)
+ return 0;
+ return list->count;
+}
+
+void
+list_concat(struct list *a, struct list *b)
+{
+ if (a->tail)
+ a->tail->next = b->head;
+ else
+ a->head = b->head;
+ a->tail = b->tail;
+ a->count += b->count;
+
+ b->count = 0;
+ b->head = b->tail = NULL;
+}
+
+void
+list_append(struct list *list, void *data)
+{
+ struct list_entry *ep;
+
+ if (!list)
+ return;
+ ep = emalloc(sizeof(*ep));
+ ep->next = NULL;
+ ep->data = data;
+ if (list->tail)
+ list->tail->next = ep;
+ else
+ list->head = ep;
+ list->tail = ep;
+ list->count++;
+}
+
+void
+list_prepend(struct list *list, void *data)
+{
+ struct list_entry *ep;
+
+ if (!list)
+ return;
+ ep = emalloc(sizeof(*ep));
+ ep->data = data;
+ ep->next = list->head;
+ list->head = ep;
+ if (!list->tail)
+ list->tail = list->head;
+ list->count++;
+}
+
+static int
+cmp_ptr(const void *a, const void *b)
+{
+ return a != b;
+}
+
+void *
+list_remove(struct list *list, void *data, list_comp_t cmp)
+{
+ struct list_entry *p, *prev;
+
+ if (!list)
+ return NULL;
+ if (!list->head)
+ return NULL;
+ if (!cmp)
+ cmp = cmp_ptr;
+ for (p = list->head, prev = NULL; p; prev = p, p = p->next)
+ if (cmp(p->data, data) == 0)
+ break;
+
+ if (!p)
+ return 0;
+ _iterator_advance(list->itr, p);
+ if (p == list->head) {
+ list->head = list->head->next;
+ if (!list->head)
+ list->tail = NULL;
+ } else
+ prev->next = p->next;
+
+ if (p == list->tail)
+ list->tail = prev;
+
+ efree(p);
+ list->count--;
+
+ return data;
+}
+
+void
+list_iterate(struct list *list, list_iterator_t func, void *data)
+{
+ ITERATOR *itr;
+ void *p;
+
+ if (!list)
+ return;
+ itr = iterator_create(list);
+ if (!itr)
+ return;
+ for (p = iterator_first(itr); p; p = iterator_next(itr)) {
+ if (func(p, data))
+ break;
+ }
+ iterator_destroy(&itr);
+}
+
+void *
+list_locate(struct list *list, void *data, list_comp_t cmp)
+{
+ struct list_entry *cur;
+ if (!list)
+ return NULL;
+ if (!cmp)
+ cmp = cmp_ptr;
+ for (cur = list->head; cur; cur = cur->next)
+ if (cmp(cur->data, data) == 0)
+ break;
+ return cur ? cur->data : NULL;
+}
+
+int
+list_insert_sorted(struct list *list, void *data, list_comp_t cmp)
+{
+ struct list_entry *cur, *prev;
+
+ if (!list)
+ return -1;
+ if (!cmp)
+ return -1;
+
+ for (cur = list->head, prev = NULL; cur; prev = cur, cur = cur->next)
+ if (cmp(cur->data, data) > 0)
+ break;
+
+ if (!prev) {
+ list_prepend(list, data);
+ } else if (!cur) {
+ list_append(list, data);
+ } else {
+ struct list_entry *ep = emalloc(sizeof(*ep));
+ ep->data = data;
+ ep->next = cur;
+ prev->next = ep;
+ }
+ return 0;
+}
+
diff --git a/src/list.h b/src/list.h
new file mode 100644
index 0000000..ee79cd1
--- /dev/null
+++ b/src/list.h
@@ -0,0 +1,48 @@
+/* This file is part of GNU Radius
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+ Written by Sergey Poznyakoff
+
+ GNU Radius is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ GNU Radius is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Radius; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef LIST_H
+#define LIST_H
+
+typedef struct list RAD_LIST;
+typedef struct iterator ITERATOR;
+
+typedef int (*list_iterator_t)(void *item, void *data);
+typedef int (*list_comp_t)(const void *, const void *);
+
+RAD_LIST *list_create();
+void list_destroy(RAD_LIST **list, list_iterator_t free, void *data);
+void list_iterate(RAD_LIST *list, list_iterator_t itr, void *data);
+void *list_item(RAD_LIST *list, size_t n);
+size_t list_count(RAD_LIST *list);
+void list_append(RAD_LIST *list, void *data);
+void list_prepend(RAD_LIST *list, void *data);
+int list_insert_sorted(struct list *list, void *data, list_comp_t cmp);
+void *list_locate(RAD_LIST *list, void *data, list_comp_t cmp);
+void *list_remove(RAD_LIST *list, void *data, list_comp_t cmp);
+
+void *iterator_current(ITERATOR *ip);
+ITERATOR *iterator_create(RAD_LIST *list);
+void iterator_destroy(ITERATOR **ip);
+void *iterator_first(ITERATOR *ip);
+void *iterator_next(ITERATOR *ip);
+
+
+#endif
+
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..b0ced55
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,270 @@
+#include "trans.h"
+#include <unistd.h>
+
+char *sql_database;
+char *sql_host;
+int sql_port = 3306;
+char *sql_password;
+char *sql_user;
+int debug;
+int compile_only;
+static int error_count;
+
+void *
+emalloc(size_t size)
+{
+ void *ptr;
+ ptr = malloc(size);
+ if (!ptr) {
+ fprintf(stderr, "not enough memory\n");
+ exit(1);
+ }
+ return ptr;
+}
+
+void
+efree(void *ptr)
+{
+ free(ptr);
+}
+
+static RAD_LIST *node_list;
+
+void
+register_node(RAD_LIST *hdr, RAD_LIST *descr)
+{
+ struct node *node = emalloc(sizeof(*node));
+ struct header *prev = NULL;
+ int i;
+
+ for (i = list_count(hdr)-1; i >= 0; i--) {
+ struct header *dp = list_item(hdr, i);
+ if (!dp->pos) {
+ if (prev)
+ dp->pos = prev->pos;
+ else {
+ fprintf(stderr,
+ "%s:%d: no POS is set for \"%s\"\n",
+ file_name,
+ input_line,
+ dp->key);
+ error_count++;
+ }
+ }
+ if (dp->pos)
+ prev = dp;
+ }
+ node->header = hdr;
+ node->descr = descr;
+ list_append(node_list, node);
+}
+
+
+
+static unsigned long dict_index;
+static unsigned long article_index;
+
+static RAD_LIST *antonym_list;
+static RAD_LIST *xref_list;
+
+int
+_emit_headers(void *item, void *data)
+{
+ struct header *hp = item;
+ char *sound;
+
+ if (debug)
+ fprintf(stderr, "Emitting %s\n", hp->key);
+ sound = greek_to_transcription(hp->key);
+ if (hp->forms)
+ sql_query("INSERT INTO dict VALUES(%lu,\"%s\",\"%s\",\"%s\",\"%s\")",
+ dict_index, hp->key, sound, hp->pos, hp->forms);
+ else
+ sql_query("INSERT INTO dict (ident,word,sound,pos) VALUES(%lu,\"%s\",\"%s\",\"%s\")",
+ dict_index, hp->key, sound, hp->pos);
+ efree(sound);
+ return 0;
+}
+
+int
+insert_antonym(unsigned long dict_index, u_char *value)
+{
+ unsigned long index;
+ if (sql_query_n(&index,
+ "SELECT ident FROM dict WHERE word=\"%s\"",
+ value) == 0) {
+ sql_query("REPLACE INTO antonym VALUES (%lu,%lu)",
+ index, dict_index);
+ sql_query("REPLACE INTO antonym VALUES (%lu,%lu)",
+ dict_index, index);
+ return 0;
+ }
+ return 1;
+}
+
+int
+insert_xref(unsigned long dict_index, u_char *value)
+{
+ unsigned long index;
+ if (sql_query_n(&index,
+ "SELECT ident FROM dict WHERE word=\"%s\"",
+ value) == 0) {
+ sql_query("REPLACE INTO xref VALUES (%lu,%lu)",
+ index, dict_index);
+ sql_query("REPLACE INTO xref VALUES (%lu,%lu)",
+ dict_index, index);
+ return 0;
+ }
+ return 1;
+}
+
+int
+_emit_descr(void *item, void *data)
+{
+ struct descr *descr = item;
+ unsigned long index;
+
+ switch (descr->type) {
+ case descr_topic:
+ if (sql_query_n(&index,
+ "SELECT ident FROM topic WHERE title=\"%s\"",
+ descr->value)) {
+ sql_query("INSERT INTO topic (title) VALUES (\"%s\")",
+ descr->value);
+ sql_query_n(&index, "SELECT LAST_INSERT_ID()");
+ }
+ sql_query("INSERT INTO topic_tab VALUES(%lu,%lu)",
+ index, dict_index);
+ break;
+
+ case descr_meaning:
+ sql_query("INSERT INTO articles VALUES (%lu, %lu, \"%s\")",
+ dict_index,
+ article_index++,
+ descr->value);
+ break;
+
+ case descr_antonym:
+ if (insert_antonym(dict_index, descr->value)) {
+ struct xref *p = emalloc(sizeof(*p));
+ p->index = dict_index;
+ p->value = descr->value;
+ list_append(antonym_list, p);
+ }
+ break;
+
+ case descr_xref:
+ if (insert_xref(dict_index, descr->value)) {
+ struct xref *p = emalloc(sizeof(*p));
+ p->index = dict_index;
+ p->value = descr->value;
+ list_append(xref_list, p);
+ }
+ break;
+ }
+ return 0;
+}
+
+static int
+cmp_descr_type(const void *a, const void *b)
+{
+ const struct descr *da = a, *db = b;
+ return da->type != db->type;
+}
+
+int
+emit_node(void *item, void *data)
+{
+ struct node *node = item;
+ article_index = 0;
+
+ list_iterate(node->header, _emit_headers, NULL);
+ list_iterate(node->descr, _emit_descr, NULL);
+
+ dict_index++;
+ return 0;
+}
+
+int
+_antonym_fixup(void *item, void *data)
+{
+ struct xref *ant = item;
+ if (insert_antonym(ant->index, ant->value)) {
+ fprintf(stderr, "unresolved antonym: %lu - \"%s\"\n",
+ ant->index, ant->value);
+ }
+ return 0;
+}
+
+int
+_xref_fixup(void *item, void *data)
+{
+ struct xref *ant = item;
+ if (insert_xref(ant->index, ant->value)) {
+ fprintf(stderr, "unresolved cross reference: %lu - \"%s\"\n",
+ ant->index, ant->value);
+ }
+ return 0;
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+ int rc;
+
+ while ((rc = getopt(argc, argv, "cd:h:P:p:u:v")) != EOF) {
+ switch (rc) {
+ case 'c':
+ compile_only = 1;
+ break;
+ case 'd':
+ sql_database = optarg;
+ break;
+
+ case 'h':
+ sql_host = optarg;
+ break;
+
+ case 'P':
+ sql_port = atoi(optarg);
+ break;
+
+ case 'p':
+ sql_password = optarg;
+ break;
+
+ case 'u':
+ sql_user = optarg;
+ break;
+
+ case 'v':
+ debug++;
+ break;
+ }
+ }
+
+ node_list = list_create();
+
+ if (parse(argv[optind]) || error_count)
+ return 1;
+
+ if (compile_only)
+ return 0;
+
+ sql_connect();
+
+ antonym_list = list_create();
+ xref_list = list_create();
+
+ sql_query_n(&dict_index,
+ "SELECT ident FROM dict ORDER BY ident DESC LIMIT 1");
+
+ list_iterate(node_list, emit_node, NULL);
+
+ list_iterate(antonym_list, _antonym_fixup, NULL);
+ list_iterate(xref_list, _xref_fixup, NULL);
+ sql_close();
+ return 0;
+}
diff --git a/src/mem.h b/src/mem.h
new file mode 100644
index 0000000..644ec19
--- /dev/null
+++ b/src/mem.h
@@ -0,0 +1,2 @@
+extern void *emalloc(size_t size);
+extern void efree(void *ptr);
diff --git a/src/sql.c b/src/sql.c
new file mode 100644
index 0000000..4b1a02b
--- /dev/null
+++ b/src/sql.c
@@ -0,0 +1,107 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <mysql/mysql.h>
+#include "trans.h"
+
+MYSQL mysql;
+MYSQL_RES *result;
+
+void
+sql_connect()
+{
+ if (!mysql_real_connect(&mysql,
+ sql_host, sql_user,
+ sql_password, sql_database, sql_port,
+ NULL, 0)) {
+ fprintf(stderr,
+ "cannot connect to MySQL server: %s\n",
+ mysql_error(&mysql));
+ exit(1);
+ }
+
+}
+
+void
+sql_close()
+{
+ mysql_close(&mysql);
+}
+
+int
+va_sql_query(char *fmt, va_list ap)
+{
+ char *buf = NULL;
+ int rc;
+
+ if (result) {
+ mysql_free_result(result);
+ result = NULL;
+ }
+
+ vasprintf(&buf, fmt, ap);
+ if (debug)
+ fprintf(stderr, "Executing query: %s\n", buf);
+ rc = mysql_query(&mysql, buf);
+ if (rc) {
+ fprintf(stderr, "MySQL Error: %s\n", mysql_error(&mysql));
+ if (!debug)
+ fprintf(stderr, "The failed query was: %s\n", buf);
+ } else {
+ result = mysql_store_result(&mysql);
+ if (result) {
+ if (debug)
+ fprintf(stderr, "Query returned %lu rows\n",
+ mysql_num_rows(result));
+ } else {
+ if (mysql_field_count(&mysql) == 0) {
+ /* query does not return data */
+ if (debug)
+ fprintf(stderr,
+ "Query affected %lu rows\n",
+ mysql_affected_rows(&mysql));
+ } else {
+ fprintf(stderr,
+ "MySQL Error: %s\n",
+ mysql_error(&mysql));
+ if (!debug)
+ fprintf(stderr,
+ "The failed query was: %s\n",
+ buf);
+ rc = 1;
+ }
+ }
+ }
+
+ free(buf);
+ return rc;
+}
+
+int
+sql_query(char *fmt, ...)
+{
+ va_list ap;
+ int rc;
+ va_start(ap, fmt);
+ rc = va_sql_query(fmt, ap);
+ va_end(ap);
+ return rc;
+}
+
+int
+sql_query_n(unsigned long *pret, char *fmt, ...)
+{
+ va_list ap;
+ int rc;
+ va_start(ap, fmt);
+ rc = va_sql_query(fmt, ap);
+ va_end(ap);
+ if (rc == 0) {
+ MYSQL_ROW row = mysql_fetch_row(result);
+ if (row)
+ *pret = strtoul (row[0], NULL, 0);
+ else
+ rc = 1;
+ }
+ return rc;
+}
diff --git a/src/trans.h b/src/trans.h
new file mode 100644
index 0000000..4b6b35a
--- /dev/null
+++ b/src/trans.h
@@ -0,0 +1,49 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "list.h"
+#include "mem.h"
+
+extern char *file_name;
+extern int input_line;
+
+struct header {
+ u_char *key;
+ char *pos;
+ u_char *forms;
+};
+
+struct node {
+ RAD_LIST *header;
+ RAD_LIST *descr;
+};
+
+enum descr_type {
+ descr_topic,
+ descr_meaning,
+ descr_antonym,
+ descr_xref
+};
+
+struct descr {
+ enum descr_type type;
+ u_char *value;
+};
+
+struct xref {
+ unsigned long index;
+ u_char *value;
+};
+
+void open_input(char *name);
+int sql_query(char *fmt, ...);
+int sql_query_n(unsigned long *pret, char *fmt, ...);
+
+extern char *sql_database;
+extern char *sql_host;
+extern int sql_port;
+extern char *sql_password;
+extern char *sql_user;
+extern int debug;
+
diff --git a/src/xcript.c b/src/xcript.c
new file mode 100644
index 0000000..1c9234f
--- /dev/null
+++ b/src/xcript.c
@@ -0,0 +1,137 @@
+#include "trans.h"
+
+struct xcript_tab {
+ char *in;
+ char *out;
+};
+
+
+struct xcript_tab xcript_tab[] = {
+ { "μπ", "b" },
+ { "γγ", "g" },
+ { "γκ", "g" },
+ { "γχ", "g" },
+ { "ντ", "d" },
+ { "αι", "e" },
+ { "αί", "e" },
+ { "αυ", "au"},
+ { "αύ", "au"},
+ { "ου", "ou"},
+ { "ού", "ou"},
+ { "ευ", "eu"},
+ { "εύ", "eu"},
+ { "οι", "i" },
+ { "ει", "i" },
+ { "εί", "i" },
+ { "υι", "i" },
+
+ { "α", "a" },
+ { "Α", "a" },
+ { "Ά", "a" },
+ { "ά", "a" },
+ { "β", "b" },
+ { "Β", "b" },
+ { "γ", "g" },
+ { "Γ", "g" },
+ { "δ", "d" },
+ { "Δ", "d" },
+ { "ε", "e" },
+ { "Ε", "e" },
+ { "Έ", "e" },
+ { "έ", "e" },
+ { "ζ", "z" },
+ { "Ζ", "z" },
+ { "η", "i" },
+ { "Η", "i" },
+ { "Ή", "i" },
+ { "ή", "i" },
+ { "θ", "t" },
+ { "Θ", "t" },
+ { "ι", "i" },
+ { "Ι", "i" },
+ { "Ί", "i" },
+ { "ί", "i" },
+ { "κ", "k" },
+ { "Κ", "k" },