diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-09-12 18:04:09 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-09-12 18:12:24 +0300 |
commit | c9c623dc8a157735181411b87b12a947a6e98443 (patch) | |
tree | d9d2005d7db5c8bd56cf78e6c0fadb5a8e77b4b6 | |
parent | a25268eaf9dcf889fdc821048d96d9b847379b7e (diff) | |
download | dico-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.am | 1 | ||||
-rw-r--r-- | dicod/database.c | 66 | ||||
-rw-r--r-- | dicod/dicod.h | 53 | ||||
-rw-r--r-- | dicod/loader.c | 102 | ||||
-rw-r--r-- | dicod/result.c | 117 | ||||
-rw-r--r-- | dicod/tests/Makefile.am | 4 | ||||
-rw-r--r-- | dicod/tests/echo.c | 109 | ||||
-rw-r--r-- | dicod/tests/testsuite.at | 20 | ||||
-rw-r--r-- | dicod/tests/virt01.at | 96 | ||||
-rw-r--r-- | dicod/tests/virt02.at | 225 | ||||
-rw-r--r-- | dicod/tests/virt03.at | 243 | ||||
-rw-r--r-- | dicod/tests/virt04.at | 58 | ||||
-rw-r--r-- | dicod/virtual.c | 124 | ||||
-rw-r--r-- | include/dico/types.h | 8 |
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 |