aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-09-12 18:04:09 +0300
committerSergey Poznyakoff <gray@gnu.org>2018-09-12 18:12:24 +0300
commitc9c623dc8a157735181411b87b12a947a6e98443 (patch)
treed9d2005d7db5c8bd56cf78e6c0fadb5a8e77b4b6
parenta25268eaf9dcf889fdc821048d96d9b847379b7e (diff)
downloaddico-c9c623dc8a157735181411b87b12a947a6e98443.tar.gz
dico-c9c623dc8a157735181411b87b12a947a6e98443.tar.bz2
Redo the virtual database support.
* include/dico/types.h (dicod_database_t): New typedef. (DICO_CAPA_OUTPUT_ALL): Remove flag. (dico_result_output_all): Remove method. (dico_result_db): New method. * include/dico/types.h (dicod_database_t): New typedef. (DICO_CAPA_OUTPUT_ALL): Remove flag. (dico_result_output_all): Remove method. (dico_result_db): New method. * dicod/result.c: New file. * dicod/Makefile.am (dicod_SOURCES): Add result.c * dicod/database.c (dicod_database_match) (dicod_database_define): Return dicod_db_result_t * (dicod_database_result_count) (dicod_database_compare_count) (dicod_database_result_free) (dicod_database_result_output) (dicod_database_mime_header): Remove. Use the corresponding dicod_db_result_ family functions instead. * dicod/dicod.h (dicod_db_result_t): New data type. (dicod_db_result_alloc,dicod_db_result_free) (dicod_db_result_count,dicod_db_result_compare_count) (dicod_db_result_output) (dicod_db_result_mime_header) (dicod_db_result_db): New protos. (dicod_database_match) (dicod_database_define): Return dicod_db_result_t * * dicod/loader.c: Use new functions. * dicod/virtual.c: Rewrite. * dicod/tests/Makefile.am: Add new tests. * dicod/tests/echo.c: New open keyword "prefix". * dicod/tests/testsuite.at: Add new tests. * dicod/tests/virt01.at: New file. * dicod/tests/virt02.at: New file. * dicod/tests/virt03.at: New file. * dicod/tests/virt04.at: New file.
-rw-r--r--dicod/Makefile.am1
-rw-r--r--dicod/database.c66
-rw-r--r--dicod/dicod.h53
-rw-r--r--dicod/loader.c102
-rw-r--r--dicod/result.c117
-rw-r--r--dicod/tests/Makefile.am4
-rw-r--r--dicod/tests/echo.c109
-rw-r--r--dicod/tests/testsuite.at20
-rw-r--r--dicod/tests/virt01.at96
-rw-r--r--dicod/tests/virt02.at225
-rw-r--r--dicod/tests/virt03.at243
-rw-r--r--dicod/tests/virt04.at58
-rw-r--r--dicod/virtual.c124
-rw-r--r--include/dico/types.h8
14 files changed, 980 insertions, 246 deletions
diff --git a/dicod/Makefile.am b/dicod/Makefile.am
index 462bcb8..9ccad06 100644
--- a/dicod/Makefile.am
+++ b/dicod/Makefile.am
@@ -39,6 +39,7 @@ dicod_SOURCES=\
mime.c\
ostream.c\
regex.c\
+ result.c\
server.c\
stat.c\
stratcl.c\
diff --git a/dicod/database.c b/dicod/database.c
index 46c57f5..4f12e7c 100644
--- a/dicod/database.c
+++ b/dicod/database.c
@@ -175,75 +175,21 @@ dicod_database_get_languages(dicod_database_t *db, dico_list_t dlist[])
dlist[1] = db->langlist[1];
}
-dico_result_t
+dicod_db_result_t *
dicod_database_match(dicod_database_t *db, const dico_strategy_t strat,
const char *word)
{
struct dico_database_module *mod = db->instance->module;
- return mod->dico_match(db->mod_handle, strat, word);
+ dico_result_t res = mod->dico_match(db->mod_handle, strat, word);
+ return dicod_db_result_alloc(db, res);
}
-dico_result_t
+dicod_db_result_t *
dicod_database_define(dicod_database_t *db, const char *word)
{
struct dico_database_module *mod = db->instance->module;
- return mod->dico_define(db->mod_handle, word);
-}
-
-// FIXME: dico_result_t should contain a pointer to db
-size_t
-dicod_database_result_count(dicod_database_t *db, dico_result_t res)
-{
- return db->instance->module->dico_result_count(res);
-}
-
-// FIXME: See above
-size_t
-dicod_database_compare_count(dicod_database_t *db, dico_result_t res)
-{
- struct dico_database_module *mod = db->instance->module;
- return mod->dico_compare_count ? mod->dico_compare_count(res) : 0;
-}
-
-// FIXME: See above
-void
-dicod_database_result_free(dicod_database_t *db, dico_result_t res)
-{
- struct dico_database_module *mod = db->instance->module;
- mod->dico_free_result(res);
-}
-
-// FIXME: See above
-int
-dicod_database_result_output(dicod_database_t *db, dico_result_t res,
- size_t n, dico_stream_t str)
-{
- struct dico_database_module *mod = db->instance->module;
- return mod->dico_output_result(res, n, str);
-}
-
-dico_assoc_list_t
-dicod_database_mime_header(dicod_database_t *db, dico_result_t res)
-{
- dico_assoc_list_t hdr = NULL;
- struct dico_database_module *mod = db->instance->module;
-
- if (db->mime_headers)
- hdr = dico_assoc_dup(db->mime_headers);
- else
- dico_header_parse(&hdr, NULL);
-
- if (mod->dico_result_headers) {
- dico_assoc_list_t tmp = dico_assoc_dup(hdr);
- if (mod->dico_result_headers(res, tmp) == 0) {
- dico_assoc_destroy(&hdr);
- hdr = tmp;
- } else {
- dico_assoc_destroy(&tmp);
- }
- }
-
- return hdr;
+ dico_result_t res = mod->dico_define(db->mod_handle, word);
+ return dicod_db_result_alloc(db, res);
}
int
diff --git a/dicod/dicod.h b/dicod/dicod.h
index ec23a4a..6fa8f99 100644
--- a/dicod/dicod.h
+++ b/dicod/dicod.h
@@ -154,7 +154,7 @@ typedef struct dicod_module_instance {
#define DICO_DBF_LANG 0x10000
-typedef struct dicod_database {
+struct dicod_database {
int flags;
char *name; /* Dictionary name */
@@ -179,7 +179,7 @@ typedef struct dicod_database {
char **argv; /* ... and pointers */
char *command; /* Handler command line (for diagnostics) */
void *extra;
-} dicod_database_t;
+};
#define CONTENT_TRANSFER_ENCODING_HEADER "Content-transfer-encoding"
@@ -297,6 +297,32 @@ int dicod_module_test(int argc, char **argv);
void dicod_builtin_module_init(void);
+/* result.c */
+typedef struct dicod_db_result {
+ int flags;
+ dicod_database_t *db;
+ dico_result_t res;
+ size_t rcount;
+ size_t ccount;
+} dicod_db_result_t;
+
+dicod_db_result_t *dicod_db_result_alloc(dicod_database_t *db,
+ dico_result_t res);
+void dicod_db_result_free(dicod_db_result_t *dbr);
+size_t dicod_db_result_count(dicod_db_result_t *dbr);
+size_t dicod_db_result_compare_count(dicod_db_result_t *dbr);
+int dicod_db_result_output(dicod_db_result_t *dbr, size_t n, dico_stream_t str);
+dico_assoc_list_t dicod_db_result_mime_header(dicod_db_result_t *dbr, size_t n);
+
+/* Flag values for dicod_db_result_db: */
+enum {
+ result_db_all, /* Return the database no matter what its visibility */
+ result_db_visible /* Return only visible databases */
+};
+
+dicod_database_t *dicod_db_result_db(dicod_db_result_t *dbr, size_t n,
+ int flag);
+
/* database.c */
int dicod_database_init(dicod_database_t *dp);
int dicod_database_open(dicod_database_t *dp);
@@ -311,16 +337,11 @@ char *dicod_database_get_info(dicod_database_t *db);
void dicod_database_free_info(dicod_database_t *db, char *info);
void dicod_database_get_languages(dicod_database_t *db, dico_list_t list[]);
-size_t dicod_database_result_count(dicod_database_t *db, dico_result_t res);
-size_t dicod_database_compare_count(dicod_database_t *db, dico_result_t res);
-void dicod_database_result_free(dicod_database_t *db, dico_result_t res);
-int dicod_database_result_output(dicod_database_t *db, dico_result_t res,
- size_t n, dico_stream_t str);
-
-dico_result_t dicod_database_match(dicod_database_t *db,
- const dico_strategy_t strat,
- const char *word);
-dico_result_t dicod_database_define(dicod_database_t *db, const char *word);
+dicod_db_result_t *dicod_database_match(dicod_database_t *db,
+ const dico_strategy_t strat,
+ const char *word);
+dicod_db_result_t *dicod_database_define(dicod_database_t *db,
+ const char *word);
char *dicod_database_get_info(dicod_database_t *db);
void dicod_database_free_info(dicod_database_t *db, char *info);
@@ -328,14 +349,10 @@ void dicod_database_free_info(dicod_database_t *db, char *info);
char *dicod_database_get_descr(dicod_database_t *db);
void dicod_database_free_descr(dicod_database_t *db, char *descr);
-dico_assoc_list_t dicod_database_mime_header(dicod_database_t *db,
- dico_result_t res);
int dicod_database_flags(dicod_database_t const *db);
-void dicod_database_print_definitions(dicod_database_t *db,
- const char *dbname, const char *dbdescr,
- const char *word,
- dico_result_t res, size_t count,
+void dicod_database_print_definitions(const char *word,
+ dicod_db_result_t *res, size_t count,
dico_stream_t stream);
/* ostream.c */
diff --git a/dicod/loader.c b/dicod/loader.c
index 5242571..60289cc 100644
--- a/dicod/loader.c
+++ b/dicod/loader.c
@@ -58,10 +58,7 @@ module_init(dicod_module_instance_t *inst, struct dico_database_module *pmod,
MODULE_ASSERT(pmod->dico_free_db);
MODULE_ASSERT(pmod->dico_match);
MODULE_ASSERT(pmod->dico_define);
- MODULE_ASSERT((pmod->dico_version > 2
- && (pmod->dico_capabilities & DICO_CAPA_OUTPUT_ALL)
- && pmod->dico_result_output_all)
- || pmod->dico_output_result);
+ MODULE_ASSERT(pmod->dico_output_result);
MODULE_ASSERT(pmod->dico_result_count);
MODULE_ASSERT(pmod->dico_free_result);
}
@@ -186,7 +183,7 @@ static char nomatch[] = "552 No match";
static size_t nomatch_len = (sizeof(nomatch)-1);
-typedef void (*outproc_t)(dicod_database_t *db, dico_result_t res,
+typedef void (*outproc_t)(dicod_db_result_t *res,
const char *word, dico_stream_t stream,
void *data,
size_t count);
@@ -211,31 +208,31 @@ dicod_word_first(dico_stream_t stream, const char *word,
itr = xdico_list_iterator(database_list);
for (db = dico_iterator_first(itr); db; db = dico_iterator_next(itr)) {
if (database_is_visible(db) && !database_is_virtual(db)) {
- dico_result_t res = strat
+ dicod_db_result_t *res = strat
? dicod_database_match(db, strat, word)
: dicod_database_define(db, word);
size_t count;
if (!res)
continue;
- count = dicod_database_result_count(db, res);
+ count = dicod_db_result_count(res);
if (count) {
if (strat)
current_stat.matches = count;
else
current_stat.defines = count;
- current_stat.compares = dicod_database_compare_count(db, res);
+ current_stat.compares = dicod_db_result_compare_count(res);
stream_printf(stream, begfmt, (unsigned long) count);
- proc(db, res, word, stream, data, count);
+ proc(res, word, stream, data, count);
stream_writez(stream, (char*) endmsg);
report_current_timing(stream, tid);
dico_stream_write(stream, "\n", 1);
access_log_status(begfmt, endmsg);
- dicod_database_result_free(db, res);
+ dicod_db_result_free(res);
break;
} else
- dicod_database_result_free(db, res);
+ dicod_db_result_free(res);
}
}
dico_iterator_destroy(&itr);
@@ -245,12 +242,6 @@ dicod_word_first(dico_stream_t stream, const char *word,
}
}
-struct dbres {
- dicod_database_t *db;
- dico_result_t res;
- size_t count;
-};
-
void
dicod_word_all(dico_stream_t stream, const char *word,
const dico_strategy_t strat,
@@ -261,7 +252,7 @@ dicod_word_all(dico_stream_t stream, const char *word,
dico_iterator_t itr;
dico_list_t reslist = xdico_list_create();
size_t total = 0;
- struct dbres *rp;
+ dicod_db_result_t *rp;
begin_timing(tid);
@@ -274,26 +265,22 @@ dicod_word_all(dico_stream_t stream, const char *word,
itr = xdico_list_iterator(database_list);
for (db = dico_iterator_first(itr); db; db = dico_iterator_next(itr)) {
if (database_is_visible(db) && !database_is_virtual(db)) {
- dico_result_t res = strat
+ dicod_db_result_t *res = strat
? dicod_database_match(db, strat, word)
: dicod_database_define(db, word);
size_t count;
if (!res)
continue;
- count = dicod_database_result_count(db, res);
+ count = dicod_db_result_count(res);
if (!count) {
- dicod_database_result_free(db, res);
+ dicod_db_result_free(res);
continue;
}
total += count;
- current_stat.compares += dicod_database_compare_count(db, res);
- rp = xmalloc(sizeof(*rp));
- rp->db = db;
- rp->res = res;
- rp->count = count;
- xdico_list_append(reslist, rp);
+ current_stat.compares += dicod_db_result_compare_count(res);
+ xdico_list_append(reslist, res);
}
}
@@ -311,9 +298,8 @@ dicod_word_all(dico_stream_t stream, const char *word,
current_stat.defines = total;
stream_printf(stream, begfmt, (unsigned long) total);
for (rp = dico_iterator_first(itr); rp; rp = dico_iterator_next(itr)) {
- proc(rp->db, rp->res, word, stream, data, rp->count);
- dicod_database_result_free(rp->db, rp->res);
- free(rp);
+ proc(rp, word, stream, data, dicod_db_result_count(rp));
+ dicod_db_result_free(rp);
}
stream_writez(stream, (char*) endmsg);
report_current_timing(stream, tid);
@@ -325,7 +311,7 @@ dicod_word_all(dico_stream_t stream, const char *word,
}
static void
-print_matches(dicod_database_t *db, dico_result_t res,
+print_matches(dicod_db_result_t *res,
const char *word,
dico_stream_t stream, void *data, size_t count)
{
@@ -333,9 +319,10 @@ print_matches(dicod_database_t *db, dico_result_t res,
dico_stream_t ostr = data;
for (i = 0; i < count; i++) {
+ dicod_database_t *db = dicod_db_result_db(res, i, result_db_visible);
stream_writez(ostr, db->name);
dico_stream_write(ostr, " \"", 2);
- dicod_database_result_output(db, res, i, ostr);
+ dicod_db_result_output(res, i, ostr);
dico_stream_write(ostr, "\"\n", 2);
}
}
@@ -344,7 +331,7 @@ void
dicod_match_word_db(dicod_database_t *db, dico_stream_t stream,
const dico_strategy_t strat, const char *word)
{
- dico_result_t res;
+ dicod_db_result_t *res;
size_t count;
begin_timing("match");
@@ -357,7 +344,7 @@ dicod_match_word_db(dicod_database_t *db, dico_stream_t stream,
return;
}
- count = dicod_database_result_count(db, res);
+ count = dicod_db_result_count(res);
if (count == 0) {
access_log_status(nomatch, nomatch);
dico_stream_writeln(stream, nomatch, nomatch_len);
@@ -365,11 +352,11 @@ dicod_match_word_db(dicod_database_t *db, dico_stream_t stream,
dico_stream_t ostr;
current_stat.matches = count;
- current_stat.compares = dicod_database_compare_count(db, res);
+ current_stat.compares = dicod_db_result_compare_count(res);
stream_printf(stream, "152 %lu matches found: list follows\n",
(unsigned long) count);
ostr = dicod_ostream_create(stream, NULL);
- print_matches(db, res, word, stream, ostr, count);
+ print_matches(res, word, stream, ostr, count);
total_bytes_out += dico_stream_bytes_out(ostr);
dico_stream_close(ostr);
dico_stream_destroy(&ostr);
@@ -380,7 +367,7 @@ dicod_match_word_db(dicod_database_t *db, dico_stream_t stream,
access_log_status("152", "250");
}
- dicod_database_result_free(db, res);
+ dicod_db_result_free(res);
}
void
@@ -411,11 +398,10 @@ dicod_match_word_all(dico_stream_t stream,
dico_stream_destroy(&ostr);
}
+//FIXME
void
-dicod_database_print_definitions(dicod_database_t *db,
- char const *dbname, char const *dbdescr,
- char const *word,
- dico_result_t res, size_t count,
+dicod_database_print_definitions(char const *word,
+ dicod_db_result_t *res, size_t count,
dico_stream_t stream)
{
size_t i;
@@ -423,13 +409,15 @@ dicod_database_print_definitions(dicod_database_t *db,
for (i = 0; i < count; i++) {
dico_stream_t ostr;
dico_assoc_list_t hdr;
-
+ dicod_database_t *db = dicod_db_result_db(res, i, result_db_visible);
+ char *descr = dicod_database_get_descr(db);
stream_printf(stream, "151 \"%s\" %s \"%s\"\n",
- word, dbname, dbdescr ? dbdescr : "");
-
- hdr = dicod_database_mime_header(db, res);
+ word, db->name, descr ? descr : "");
+ dicod_database_free_descr(db, descr);
+
+ hdr = dicod_db_result_mime_header(res, i);
ostr = dicod_ostream_create(stream, hdr);
- dicod_database_result_output(db, res, i, ostr);
+ dicod_db_result_output(res, i, ostr);
total_bytes_out += dico_stream_bytes_out(ostr);
dico_stream_close(ostr);
dico_stream_destroy(&ostr);
@@ -439,26 +427,18 @@ dicod_database_print_definitions(dicod_database_t *db,
}
static void
-print_definitions(dicod_database_t *db, dico_result_t res,
+print_definitions(dicod_db_result_t *res,
const char *word,
dico_stream_t stream, void *data, size_t count)
{
- struct dico_database_module *mod = db->instance->module;
- char *descr = dicod_database_get_descr(db);
- if (mod->dico_capabilities & DICO_CAPA_OUTPUT_ALL) {
- mod->dico_result_output_all(res, db->name, descr, word, stream);
- } else {
- dicod_database_print_definitions(db, db->name, descr,
- word, res, count, stream);
- }
- dicod_database_free_descr(db, descr);
+ dicod_database_print_definitions(word, res, count, stream);
}
void
dicod_define_word_db(dicod_database_t *db, dico_stream_t stream,
const char *word)
{
- dico_result_t res;
+ dicod_db_result_t *res;
size_t count;
begin_timing("define");
@@ -470,23 +450,23 @@ dicod_define_word_db(dicod_database_t *db, dico_stream_t stream,
return;
}
- count = dicod_database_result_count(db, res);
+ count = dicod_db_result_count(res);
if (count == 0) {
access_log_status(nomatch, nomatch);
dico_stream_writeln(stream, nomatch, nomatch_len);
} else {
current_stat.defines = count;
- current_stat.compares = dicod_database_compare_count(db, res);
+ current_stat.compares = dicod_db_result_compare_count(res);
stream_printf(stream, "150 %lu definitions found: list follows\n",
(unsigned long) count);
- print_definitions(db, res, word, stream, NULL, count);
+ print_definitions(res, word, stream, NULL, count);
stream_writez(stream, "250 Command complete");
report_current_timing(stream, "define");
dico_stream_write(stream, "\n", 1);
access_log_status("150", "250");
}
- dicod_database_result_free(db, res);
+ dicod_db_result_free(res);
}
void
diff --git a/dicod/result.c b/dicod/result.c
new file mode 100644
index 0000000..e0c9b0e
--- /dev/null
+++ b/dicod/result.c
@@ -0,0 +1,117 @@
+/* This file is part of GNU Dico.
+ Copyright (C) 1998-2018 Sergey Poznyakoff
+
+ GNU Dico 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 3, or (at your option)
+ any later version.
+
+ GNU Dico 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 Dico. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <dicod.h>
+
+enum {
+ DBRF_NONE = 0,
+ DBRF_RCOUNT = 0x01,
+ DBRF_CCOUNT = 0x02
+};
+
+dicod_db_result_t *
+dicod_db_result_alloc(dicod_database_t *db, dico_result_t res)
+{
+ dicod_db_result_t *dbr;
+ if (!res)
+ return NULL;
+ dbr = xmalloc(sizeof(*dbr));
+ dbr->flags = DBRF_NONE;
+ dbr->db = db;
+ dbr->res = res;
+ return dbr;
+}
+
+static inline struct dico_database_module *
+dicod_db_result_module(dicod_db_result_t *dbr)
+{
+ return dbr->db->instance->module;
+}
+
+void
+dicod_db_result_free(dicod_db_result_t *dbr)
+{
+ dicod_db_result_module(dbr)->dico_free_result(dbr->res);
+ free(dbr);
+}
+
+size_t
+dicod_db_result_count(dicod_db_result_t *dbr)
+{
+ if (!(dbr->flags & DBRF_RCOUNT)) {
+ dbr->rcount = dicod_db_result_module(dbr)->dico_result_count(dbr->res);
+ dbr->flags |= DBRF_RCOUNT;
+ }
+ return dbr->rcount;
+}
+
+size_t
+dicod_db_result_compare_count(dicod_db_result_t *dbr)
+{
+ if (!(dbr->flags & DBRF_CCOUNT)) {
+ dbr->ccount = dicod_db_result_module(dbr)->dico_compare_count(dbr->res);
+ dbr->flags |= DBRF_CCOUNT;
+ }
+ return dbr->ccount;
+}
+
+int
+dicod_db_result_output(dicod_db_result_t *dbr, size_t n, dico_stream_t str)
+{
+ return dicod_db_result_module(dbr)->dico_output_result(dbr->res, n, str);
+}
+
+dico_assoc_list_t
+dicod_db_result_mime_header(dicod_db_result_t *dbr, size_t n)
+{
+ dico_assoc_list_t hdr = NULL;
+ struct dico_database_module *mod = dicod_db_result_module(dbr);
+ dicod_database_t *db = dicod_db_result_db(dbr, n, result_db_all);
+
+ if (db->mime_headers)
+ hdr = dico_assoc_dup(db->mime_headers);
+ else
+ dico_header_parse(&hdr, NULL);
+
+ if (mod->dico_result_headers) {
+ dico_assoc_list_t tmp = dico_assoc_dup(hdr);
+ if (mod->dico_result_headers(dbr->res, tmp) == 0) {
+ dico_assoc_destroy(&hdr);
+ hdr = tmp;
+ } else {
+ dico_assoc_destroy(&tmp);
+ }
+ }
+
+ return hdr;
+}
+
+dicod_database_t *
+dicod_db_result_db(dicod_db_result_t *dbr, size_t n, int flag)
+{
+ dicod_database_t *db = NULL;
+ struct dico_database_module *mod = dicod_db_result_module(dbr);
+ if (mod->dico_result_db) {
+ db = mod->dico_result_db(dbr->res, n);
+ if (db && flag == result_db_visible && !database_is_visible(db))
+ db = dbr->db;
+ }
+ return db ? db : dbr->db;
+}
+
+
+
+
diff --git a/dicod/tests/Makefile.am b/dicod/tests/Makefile.am
index a2548b5..4d25271 100644
--- a/dicod/tests/Makefile.am
+++ b/dicod/tests/Makefile.am
@@ -95,6 +95,10 @@ TESTSUITE_AT = \
vis00.at\
vis01.at\
vis02.at\
+ virt01.at\
+ virt02.at\
+ virt03.at\
+ virt04.at\
testsuite.at
TESTSUITE = $(srcdir)/testsuite
diff --git a/dicod/tests/echo.c b/dicod/tests/echo.c
index c64f139..e33eeab 100644
--- a/dicod/tests/echo.c
+++ b/dicod/tests/echo.c
@@ -28,8 +28,10 @@ enum echo_mode {
ECHO_NULL /* Operate in null mode */
};
-struct echo_handle {
+struct dico_handle_struct {
enum echo_mode mode;
+ char *prefix;
+ size_t prefix_len;
};
static int
@@ -42,10 +44,12 @@ static dico_handle_t
echo_init_db(const char *dbname, int argc, char **argv)
{
int null_mode = 0;
- struct echo_handle *hp;
+ dico_handle_t hp;
+ char *prefix = NULL;
struct dico_option init_db_option[] = {
{ DICO_OPTSTR(null), dico_opt_bool, &null_mode },
+ { DICO_OPTSTR(prefix), dico_opt_string, &prefix },
{ NULL }
};
@@ -53,11 +57,23 @@ echo_init_db(const char *dbname, int argc, char **argv)
return NULL;
hp = malloc(sizeof(*hp));
- if (hp)
+ if (hp) {
hp->mode = null_mode ? ECHO_NULL : ECHO_ECHO;
- else
+ if (prefix) {
+ hp->prefix = strdup(prefix);
+ if (!hp->prefix) {
+ dico_log(L_ERR, 0, "not enough memory");
+ free(hp);
+ return NULL;
+ }
+ hp->prefix_len = strlen(prefix);
+ } else {
+ hp->prefix = NULL;
+ hp->prefix_len = 0;
+ }
+ } else
dico_log(L_ERR, 0, "not enough memory");
- return (dico_handle_t)hp;
+ return hp;
}
static int
@@ -80,9 +96,8 @@ echo_close(dico_handle_t hp)
}
static char *
-echo_info(dico_handle_t hp)
+echo_info(dico_handle_t ep)
{
- struct echo_handle *ep = (struct echo_handle*)hp;
static char *echo_info_str[2] = {
"\
ECHO database.\n\n\
@@ -96,36 +111,56 @@ requests.\n"
}
static char *
-echo_descr(dico_handle_t hp)
+echo_descr(dico_handle_t ep)
{
- struct echo_handle *ep = (struct echo_handle*)hp;
static char *echo_descr_str[2] = {
"GNU Dico ECHO database",
"GNU Dico NULL database"
};
- return strdup(echo_descr_str[ep->mode]);
+ char *res;
+ if (ep->mode == ECHO_ECHO && ep->prefix) {
+ size_t len = strlen(echo_descr_str[ep->mode]) + ep->prefix_len + 11;
+ res = malloc(len);
+ if (res)
+ snprintf(res, len, "%s (prefix %s)",
+ echo_descr_str[ep->mode], ep->prefix);
+ } else
+ res = strdup(echo_descr_str[ep->mode]);
+ return res;
}
static dico_result_t
-echo_match(dico_handle_t hp, const dico_strategy_t strat, const char *word)
+new_result(dico_handle_t ep, char const *word)
+{
+ char *res = malloc(strlen(word) + ep->prefix_len + 1);
+ if (!res)
+ dico_log(L_ERR, 0, "not enough memory");
+ else {
+ if (ep->prefix)
+ memcpy(res, ep->prefix, ep->prefix_len);
+ strcpy(res + ep->prefix_len, word);
+ }
+ return (dico_result_t) res;
+}
+
+static dico_result_t
+echo_match(dico_handle_t ep, const dico_strategy_t strat, const char *word)
{
- struct echo_handle *ep = (struct echo_handle*)hp;
if (ep->mode == ECHO_NULL)
return NULL;
- return (dico_result_t) strdup(word);
+ return new_result(ep, word);
}
static dico_result_t
-echo_define(dico_handle_t hp, const char *word)
+echo_define(dico_handle_t ep, const char *word)
{
- struct echo_handle *ep = (struct echo_handle*)hp;
if (ep->mode == ECHO_NULL)
return NULL;
- return (dico_result_t) strdup(word);
+ return new_result(ep, word);
}
static int
-echo_output_result (dico_result_t rp, size_t n, dico_stream_t str)
+echo_output_result(dico_result_t rp, size_t n, dico_stream_t str)
{
char *word = (char*)rp;
dico_stream_write(str, word, strlen(word));
@@ -150,22 +185,28 @@ echo_free_result(dico_result_t rp)
free(rp);
}
+static char *
+echo_mime_header(dico_handle_t ep)
+{
+ return strdup("Content-Type: text/plain; charset=utf-8\n\
+Content-Transfer-Encoding: 8bit\n");
+}
+
struct dico_database_module DICO_EXPORT(echo, module) = {
- DICO_MODULE_VERSION,
- DICO_CAPA_NONE,
- echo_init,
- echo_init_db,
- echo_free_db,
- echo_open,
- echo_close,
- echo_info,
- echo_descr,
- NULL, /* echo_lang */
- echo_match,
- echo_define,
- echo_output_result,
- echo_result_count,
- echo_compare_count,
- echo_free_result,
- NULL /* echo_result_headers */
+ .dico_version = DICO_MODULE_VERSION,
+ .dico_capabilities = DICO_CAPA_NONE,
+ .dico_init = echo_init,
+ .dico_init_db = echo_init_db,
+ .dico_free_db = echo_free_db,
+ .dico_open = echo_open,
+ .dico_close = echo_close,
+ .dico_db_info = echo_info,
+ .dico_db_descr = echo_descr,
+ .dico_match = echo_match,
+ .dico_define = echo_define,
+ .dico_output_result = echo_output_result,
+ .dico_result_count = echo_result_count,
+ .dico_compare_count = echo_compare_count,
+ .dico_free_result = echo_free_result,
+ .dico_db_mime_header = echo_mime_header
};
diff --git a/dicod/tests/testsuite.at b/dicod/tests/testsuite.at
index 253c1b0..29f2170 100644
--- a/dicod/tests/testsuite.at
+++ b/dicod/tests/testsuite.at
@@ -27,20 +27,38 @@ __EOT__
AT_INIT
DICO_VERSION(dicod)
m4_include([startup.at])
+
+AT_BANNER([HELP output])
m4_include([help00.at])
m4_include([help01.at])
m4_include([help02.at])
m4_include([help03.at])
+
+AT_BANNER([SHOW commands])
m4_include([showstrat.at])
m4_include([showdb.at])
m4_include([info.at])
m4_include([descr.at])
+
+AT_BANNER([MATCH])
m4_include([match.at])
m4_include([nomatch.at])
+
+AT_BANNER([DEFINE])
m4_include([def.at])
m4_include([nodef.at])
-m4_include([apop.at])
+
+AT_BANNER([Visibility])
m4_include([vis00.at])
m4_include([vis01.at])
m4_include([vis02.at])
+
+AT_BANNER([Other features])
+m4_include([apop.at])
m4_include([alias.at])
+
+AT_BANNER([Virtual databases])
+m4_include([virt01.at])
+m4_include([virt02.at])
+m4_include([virt03.at])
+m4_include([virt04.at])
diff --git a/dicod/tests/virt01.at b/dicod/tests/virt01.at
new file mode 100644
index 0000000..6582de2
--- /dev/null
+++ b/dicod/tests/virt01.at
@@ -0,0 +1,96 @@
+# This file is part of GNU Dico -*- Autotest -*-
+# Copyright (C) 2012-2018 Sergey Poznyakoff
+#
+# GNU Dico 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 3, or (at your option)
+# any later version.
+#
+# GNU Dico 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 Dico. If not, see <http://www.gnu.org/licenses/>.
+
+AT_SETUP([show db])
+AT_KEYWORDS([virtual virtual01])
+AT_DATA([input],[show db
+quit
+])
+
+AT_CHECK([
+DICOD_CONFIG([
+database {
+ name db1;
+ handler "echo prefix=1";
+}
+database {
+ name db2;
+ handler "echo prefix=2";
+}
+database {
+ name db3;
+ handler "echo prefix=3";
+}
+database {
+ name virt;
+ handler virtual;
+ database db1;
+ database db2;
+ database db3;
+}
+])
+
+DICOD_RUN],
+[0],
+[220
+110 4 databases present
+db1 "GNU Dico ECHO database (prefix 1)"
+db2 "GNU Dico ECHO database (prefix 2)"
+db3 "GNU Dico ECHO database (prefix 3)"
+virt ""
+.
+250
+221
+])
+
+AT_CHECK([
+DICOD_CONFIG([
+database {
+ name db1;
+ handler "echo prefix=1";
+ visible no;
+}
+database {
+ name db2;
+ handler "echo prefix=2";
+ visible no;
+}
+database {
+ name db3;
+ handler "echo prefix=3";
+ visible no;
+}
+database {
+ name virt;
+ handler virtual;
+ description "virtual db";
+ database db1;
+ database db2;
+ database db3;
+}
+])
+
+DICOD_RUN],
+[0],
+[220
+110 1 databases present
+virt "virtual db"
+.
+250
+221
+])
+
+AT_CLEANUP
diff --git a/dicod/tests/virt02.at b/dicod/tests/virt02.at
new file mode 100644
index 0000000..acd4fb5
--- /dev/null
+++ b/dicod/tests/virt02.at
@@ -0,0 +1,225 @@
+# This file is part of GNU Dico -*- Autotest -*-
+# Copyright (C) 2012-2018 Sergey Poznyakoff
+#
+# GNU Dico 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 3, or (at your option)
+# any later version.
+#
+# GNU Dico 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 Dico. If not, see <http://www.gnu.org/licenses/>.
+
+AT_SETUP([match])
+AT_KEYWORDS([virtual virtual02])
+
+# Explicit matching of a virtual database returns real names of its
+# visible members.
+AT_CHECK([
+DICOD_CONFIG([
+database {
+ name db1;
+ handler "echo prefix=1";
+}
+database {
+ name db2;
+ handler "echo prefix=2";
+}
+database {
+ name db3;
+ handler "echo prefix=3";
+}
+database {
+ name virt;
+ handler virtual;
+ database db1;
+ database db2;
+ database db3;
+}
+])
+
+AT_DATA([input],[match virt . word
+quit
+])
+
+DICOD_RUN],
+[0],
+[220
+152 3 matches found: list follows
+db1 "1word"
+db2 "2word"
+db3 "3word"
+.
+250
+221
+])
+
+# Virtual database is excluded from wildcard matching.
+AT_CHECK([
+DICOD_CONFIG([
+database {
+ name db1;
+ handler "echo prefix=1";
+}
+database {
+ name db2;
+ handler "echo prefix=2";
+}
+database {
+ name db3;
+ handler "echo prefix=3";
+}
+database {
+ name